ch3u_rma_reqops.c 15 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
/*
 *  (C) 2012 by Argonne National Laboratory.
 *      See COPYRIGHT in top-level directory.
 */

#include "mpidi_ch3_impl.h"
#include "mpidrma.h"

/* Request-based RMA operations are implemented using generalized requests.
 * Below are the generalized request state and handlers for these operations.
 */

typedef struct {
    MPID_Request *request;
    MPID_Win     *win_ptr;
    int           target_rank;
} MPIDI_CH3I_Rma_req_state_t;


#undef FUNCNAME
#define FUNCNAME MPIDI_CH3I_Rma_req_poll
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
static int MPIDI_CH3I_Rma_req_poll(void *state, MPI_Status *status)
{
    int mpi_errno = MPI_SUCCESS;
    MPIDI_CH3I_Rma_req_state_t *req_state = (MPIDI_CH3I_Rma_req_state_t*) state;

    MPIU_UNREFERENCED_ARG(status);

33
34
35
36
37
38
    /* Call flush to complete the operation */
    /* FIXME: We need per-operation completion to make this more efficient. */
    mpi_errno = req_state->win_ptr->RMAFns.Win_flush(req_state->target_rank,
                                                     req_state->win_ptr);

    if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
39
40
41
42
43
44
45
46
47
48

    MPIR_Grequest_complete_impl(req_state->request);

 fn_exit:
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#undef FUNCNAME
#define FUNCNAME MPIDI_CH3I_Rma_req_wait
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
static int MPIDI_CH3I_Rma_req_wait(int count, void **states, double timeout,
                                   MPI_Status *status)
{
    int mpi_errno = MPI_SUCCESS;
    int i;

    for (i = 0; i < count; i++) {
        /* Call poll to complete the operation */
        mpi_errno = MPIDI_CH3I_Rma_req_poll(states[i], status);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }

 fn_exit:
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}


72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#undef FUNCNAME
#define FUNCNAME MPIDI_CH3I_Rma_req_query
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
static int MPIDI_CH3I_Rma_req_query(void *state, MPI_Status *status)
{
    int mpi_errno = MPI_SUCCESS;

    MPIU_UNREFERENCED_ARG(state);

    /* All status fields, except the error code, are undefined */
    status->count = 0;
    status->cancelled = FALSE;
    status->MPI_SOURCE = MPI_UNDEFINED;
    status->MPI_TAG = MPI_UNDEFINED;

 fn_exit:
    status->MPI_ERROR = mpi_errno;
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}


#undef FUNCNAME
#define FUNCNAME MPIDI_CH3I_Rma_req_free
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
static int MPIDI_CH3I_Rma_req_free(void *state)
{
    MPIU_Free(state);

    return MPI_SUCCESS;
}


#undef FUNCNAME
#define FUNCNAME MPIDI_CH3I_Rma_req_cancel
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
static int MPIDI_CH3I_Rma_req_cancel(void *state, int complete)
{
    int mpi_errno = MPI_SUCCESS;

    MPIU_UNREFERENCED_ARG(state);

    /* This operation can't be cancelled */
    if (!complete) {
        MPIU_ERR_SETANDJUMP(mpi_errno, MPI_ERR_OTHER, "**rmareqcancel");
    }

 fn_exit:
    return mpi_errno;
 fn_fail:
    goto fn_exit;
}


#undef FUNCNAME
#define FUNCNAME MPIDI_Rput
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
int MPIDI_Rput(const void *origin_addr, int origin_count,
               MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp,
               int target_count, MPI_Datatype target_datatype, MPID_Win *win_ptr,
               MPID_Request **request)
{
    int mpi_errno = MPI_SUCCESS;
    MPIDI_CH3I_Rma_req_state_t *req_state;
    MPIU_CHKPMEM_DECL(1);
142
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_RPUT);
143
144
145

    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_RPUT);

146
    MPIU_ERR_CHKANDJUMP(win_ptr->epoch_state != MPIDI_EPOCH_LOCK &&
147
148
                        win_ptr->epoch_state != MPIDI_EPOCH_LOCK_ALL &&
                        target_rank != MPI_PROC_NULL,
149
150
                        mpi_errno, MPI_ERR_RMA_SYNC, "**rmasync");

151
152
153
154
155
156
157
    MPIU_CHKPMEM_MALLOC(req_state, MPIDI_CH3I_Rma_req_state_t*,
                        sizeof(MPIDI_CH3I_Rma_req_state_t), mpi_errno,
                        "req-based RMA state");

    req_state->win_ptr = win_ptr;
    req_state->target_rank = target_rank;

158
159
160
161
162
163
    /* Enqueue or perform the RMA operation */
    if (target_rank != MPI_PROC_NULL) {
        mpi_errno = win_ptr->RMAFns.Put(origin_addr, origin_count,
                                        origin_datatype, target_rank,
                                        target_disp, target_count,
                                        target_datatype, win_ptr);
164

165
166
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
167

168
169
170
    /* If the operation is already complete, return a completed request.
     * Otherwise, generate a grequest. */
    /* FIXME: We still may need to flush or sync for shared memory windows */
171
172
173
    if (target_rank == MPI_PROC_NULL || target_rank == win_ptr->myrank ||
        win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
    {
174
175
176
177
178
        mpi_errno = MPIR_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             req_state, &req_state->request);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
179

180
181
182
183
184
185
186
187
188
189
190
191
        MPIR_Grequest_complete_impl(req_state->request);
    }
    else {
        mpi_errno = MPIX_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             MPIDI_CH3I_Rma_req_poll,
                                             MPIDI_CH3I_Rma_req_wait,
                                             req_state, &req_state->request);

        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
192
193
194
195

    *request = req_state->request;

 fn_exit:
196
    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_RPUT);
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
    return mpi_errno;
 fn_fail:
    MPIU_CHKPMEM_REAP();
    goto fn_exit;
}


#undef FUNCNAME
#define FUNCNAME MPIDI_Rget
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
int MPIDI_Rget(void *origin_addr, int origin_count,
               MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp,
               int target_count, MPI_Datatype target_datatype, MPID_Win *win_ptr,
               MPID_Request **request)
{
    int mpi_errno = MPI_SUCCESS;
    MPIDI_CH3I_Rma_req_state_t *req_state;
    MPIU_CHKPMEM_DECL(1);
216
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_RGET);
217
218
219

    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_RGET);

220
    MPIU_ERR_CHKANDJUMP(win_ptr->epoch_state != MPIDI_EPOCH_LOCK &&
221
222
                        win_ptr->epoch_state != MPIDI_EPOCH_LOCK_ALL &&
                        target_rank != MPI_PROC_NULL,
223
224
                        mpi_errno, MPI_ERR_RMA_SYNC, "**rmasync");

225
226
227
228
229
230
231
    MPIU_CHKPMEM_MALLOC(req_state, MPIDI_CH3I_Rma_req_state_t*,
                        sizeof(MPIDI_CH3I_Rma_req_state_t), mpi_errno,
                        "req-based RMA state");

    req_state->win_ptr = win_ptr;
    req_state->target_rank = target_rank;

232
233
234
235
236
237
    /* Enqueue or perform the RMA operation */
    if (target_rank != MPI_PROC_NULL) {
        mpi_errno = win_ptr->RMAFns.Get(origin_addr, origin_count,
                                        origin_datatype, target_rank,
                                        target_disp, target_count,
                                        target_datatype, win_ptr);
238

239
240
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
241

242
243
244
    /* If the operation is already complete, return a completed request.
     * Otherwise, generate a grequest. */
    /* FIXME: We still may need to flush or sync for shared memory windows */
245
246
247
    if (target_rank == MPI_PROC_NULL || target_rank == win_ptr->myrank ||
        win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
    {
248
249
250
251
252
        mpi_errno = MPIR_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             req_state, &req_state->request);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
253

254
255
256
257
258
259
260
261
262
263
264
265
        MPIR_Grequest_complete_impl(req_state->request);
    }
    else {
        mpi_errno = MPIX_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             MPIDI_CH3I_Rma_req_poll,
                                             MPIDI_CH3I_Rma_req_wait,
                                             req_state, &req_state->request);

        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
266
267
268
269

    *request = req_state->request;

 fn_exit:
270
    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_RGET);
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
    return mpi_errno;
 fn_fail:
    MPIU_CHKPMEM_REAP();
    goto fn_exit;
}


#undef FUNCNAME
#define FUNCNAME MPIDI_Raccumulate
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
int MPIDI_Raccumulate(const void *origin_addr, int origin_count,
                      MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp,
                      int target_count, MPI_Datatype target_datatype, MPI_Op op, MPID_Win *win_ptr,
                      MPID_Request **request)
{
    int mpi_errno = MPI_SUCCESS;
    MPIDI_CH3I_Rma_req_state_t *req_state;
    MPIU_CHKPMEM_DECL(1);
290
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_RACCUMULATE);
291
292
293

    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_RACCUMULATE);

294
    MPIU_ERR_CHKANDJUMP(win_ptr->epoch_state != MPIDI_EPOCH_LOCK &&
295
296
                        win_ptr->epoch_state != MPIDI_EPOCH_LOCK_ALL &&
                        target_rank != MPI_PROC_NULL,
297
298
                        mpi_errno, MPI_ERR_RMA_SYNC, "**rmasync");

299
300
301
302
303
304
305
    MPIU_CHKPMEM_MALLOC(req_state, MPIDI_CH3I_Rma_req_state_t*,
                        sizeof(MPIDI_CH3I_Rma_req_state_t), mpi_errno,
                        "req-based RMA state");

    req_state->win_ptr = win_ptr;
    req_state->target_rank = target_rank;

306
307
308
309
310
311
312
313
    /* Enqueue or perform the RMA operation */
    if (target_rank != MPI_PROC_NULL) {
        mpi_errno = win_ptr->RMAFns.Accumulate(origin_addr, origin_count,
                                               origin_datatype, target_rank,
                                               target_disp, target_count,
                                               target_datatype, op, win_ptr);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
314

315
316
317
    /* If the operation is already complete, return a completed request.
     * Otherwise, generate a grequest. */
    /* FIXME: We still may need to flush or sync for shared memory windows */
318
319
320
    if (target_rank == MPI_PROC_NULL || target_rank == win_ptr->myrank ||
        win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
    {
321
322
323
324
325
        mpi_errno = MPIR_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             req_state, &req_state->request);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
326

327
328
329
330
331
332
333
334
335
        MPIR_Grequest_complete_impl(req_state->request);
    }
    else {
        mpi_errno = MPIX_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             MPIDI_CH3I_Rma_req_poll,
                                             MPIDI_CH3I_Rma_req_wait,
                                             req_state, &req_state->request);
336

337
338
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
339
340
341
342

    *request = req_state->request;

 fn_exit:
343
    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_RACCUMULATE);
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
    return mpi_errno;
 fn_fail:
    MPIU_CHKPMEM_REAP();
    goto fn_exit;
}


#undef FUNCNAME
#define FUNCNAME MPIDI_Rget_accumulate
#undef FCNAME
#define FCNAME MPIDI_QUOTE(FUNCNAME)
int MPIDI_Rget_accumulate(const void *origin_addr, int origin_count,
                          MPI_Datatype origin_datatype, void *result_addr, int result_count,
                          MPI_Datatype result_datatype, int target_rank, MPI_Aint target_disp,
                          int target_count, MPI_Datatype target_datatype, MPI_Op op, MPID_Win *win_ptr,
                          MPID_Request **request)
{
    int mpi_errno = MPI_SUCCESS;
    MPIDI_CH3I_Rma_req_state_t *req_state;
    MPIU_CHKPMEM_DECL(1);
364
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_RGET_ACCUMULATE);
365
366
367

    MPIDI_FUNC_ENTER(MPID_STATE_MPIDI_RGET_ACCUMULATE);

368
    MPIU_ERR_CHKANDJUMP(win_ptr->epoch_state != MPIDI_EPOCH_LOCK &&
369
370
                        win_ptr->epoch_state != MPIDI_EPOCH_LOCK_ALL &&
                        target_rank != MPI_PROC_NULL,
371
372
                        mpi_errno, MPI_ERR_RMA_SYNC, "**rmasync");

373
374
375
376
377
378
379
    MPIU_CHKPMEM_MALLOC(req_state, MPIDI_CH3I_Rma_req_state_t*,
                        sizeof(MPIDI_CH3I_Rma_req_state_t), mpi_errno,
                        "req-based RMA state");

    req_state->win_ptr = win_ptr;
    req_state->target_rank = target_rank;

380
381
382
383
384
385
386
387
388
389
    /* Enqueue or perform the RMA operation */
    if (target_rank != MPI_PROC_NULL) {
        mpi_errno = win_ptr->RMAFns.Get_accumulate(origin_addr, origin_count,
                                                   origin_datatype, result_addr,
                                                   result_count, result_datatype,
                                                   target_rank, target_disp,
                                                   target_count, target_datatype,
                                                   op, win_ptr);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
390

391
392
393
    /* If the operation is already complete, return a completed request.
     * Otherwise, generate a grequest. */
    /* FIXME: We still may need to flush or sync for shared memory windows */
394
395
396
    if (target_rank == MPI_PROC_NULL || target_rank == win_ptr->myrank ||
        win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
    {
397
398
399
400
401
        mpi_errno = MPIR_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             req_state, &req_state->request);
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
402

403
404
405
406
407
408
409
410
411
        MPIR_Grequest_complete_impl(req_state->request);
    }
    else {
        mpi_errno = MPIX_Grequest_start_impl(MPIDI_CH3I_Rma_req_query,
                                             MPIDI_CH3I_Rma_req_free,
                                             MPIDI_CH3I_Rma_req_cancel,
                                             MPIDI_CH3I_Rma_req_poll,
                                             MPIDI_CH3I_Rma_req_wait,
                                             req_state, &req_state->request);
412

413
414
        if (mpi_errno != MPI_SUCCESS) { MPIU_ERR_POP(mpi_errno); }
    }
415
416
417
418

    *request = req_state->request;

 fn_exit:
419
    MPIDI_FUNC_EXIT(MPID_STATE_MPIDI_RGET_ACCUMULATE);
420
421
422
423
424
425
    return mpi_errno;
 fn_fail:
    MPIU_CHKPMEM_REAP();
    goto fn_exit;
}