~ubuntu-branches/ubuntu/vivid/mpich/vivid-proposed

« back to all changes in this revision

Viewing changes to src/mpid/ch3/src/ch3u_rma_ops.c

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2014-04-01 20:24:20 UTC
  • mfrom: (5.2.4 sid)
  • Revision ID: package-import@ubuntu.com-20140401202420-t5ey1ia2klt5dkq3
Tags: 3.1-4
* [c3e3398] Disable test_primitives, which is unreliable on some platforms.
            (Closes: #743047)
* [265a699] Add minimal autotest.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
 *      See COPYRIGHT in top-level directory.
5
5
 */
6
6
 
7
 
#include "mpidi_ch3_impl.h"
8
7
#include "mpidrma.h"
9
8
 
10
9
static int enableShortACC=1;
11
10
 
12
 
#ifdef USE_MPIU_INSTR
13
 
MPIU_INSTR_DURATION_EXTERN_DECL(wincreate_allgather);
14
 
MPIU_INSTR_DURATION_EXTERN_DECL(winfree_rs);
15
 
MPIU_INSTR_DURATION_EXTERN_DECL(winfree_complete);
16
 
MPIU_INSTR_DURATION_EXTERN_DECL(rmaqueue_alloc);
17
 
MPIU_INSTR_DURATION_EXTERN_DECL(rmaqueue_set);
18
 
extern void MPIDI_CH3_RMA_InitInstr(void);
19
 
#endif
 
11
MPIR_T_PVAR_DOUBLE_TIMER_DECL_EXTERN(RMA, rma_rmaqueue_alloc);
 
12
MPIR_T_PVAR_DOUBLE_TIMER_DECL_EXTERN(RMA, rma_rmaqueue_set);
 
13
extern void MPIDI_CH3_RMA_Init_Pvars(void);
20
14
 
21
15
#define MPIDI_PASSIVE_TARGET_DONE_TAG  348297
22
16
#define MPIDI_PASSIVE_TARGET_RMA_TAG 563924
44
38
#define FCNAME MPIDI_QUOTE(FUNCNAME)
45
39
int MPIDI_Win_free(MPID_Win **win_ptr)
46
40
{
47
 
    int mpi_errno=MPI_SUCCESS, total_pt_rma_puts_accs;
 
41
    int mpi_errno=MPI_SUCCESS;
48
42
    int in_use;
49
43
    MPID_Comm *comm_ptr;
50
 
    int errflag = FALSE;
51
44
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_WIN_FREE);
52
45
        
53
46
    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_WIN_FREE);
55
48
    MPIU_ERR_CHKANDJUMP((*win_ptr)->epoch_state != MPIDI_EPOCH_NONE,
56
49
                        mpi_errno, MPI_ERR_RMA_SYNC, "**rmasync");
57
50
 
 
51
    mpi_errno = MPIDI_CH3I_Wait_for_pt_ops_finish(*win_ptr);
 
52
    if(mpi_errno) MPIU_ERR_POP(mpi_errno);
 
53
 
58
54
    comm_ptr = (*win_ptr)->comm_ptr;
59
 
    MPIU_INSTR_DURATION_START(winfree_rs);
60
 
    mpi_errno = MPIR_Reduce_scatter_block_impl((*win_ptr)->pt_rma_puts_accs, 
61
 
                                               &total_pt_rma_puts_accs, 1, 
62
 
                                               MPI_INT, MPI_SUM, comm_ptr, &errflag);
63
 
    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
64
 
    MPIU_ERR_CHKANDJUMP(errflag, mpi_errno, MPI_ERR_OTHER, "**coll_fail");
65
 
    MPIU_INSTR_DURATION_END(winfree_rs);
66
 
 
67
 
    if (total_pt_rma_puts_accs != (*win_ptr)->my_pt_rma_puts_accs)
68
 
    {
69
 
        MPID_Progress_state progress_state;
70
 
            
71
 
        /* poke the progress engine until the two are equal */
72
 
        MPIU_INSTR_DURATION_START(winfree_complete);
73
 
        MPID_Progress_start(&progress_state);
74
 
        while (total_pt_rma_puts_accs != (*win_ptr)->my_pt_rma_puts_accs)
75
 
        {
76
 
            mpi_errno = MPID_Progress_wait(&progress_state);
77
 
            /* --BEGIN ERROR HANDLING-- */
78
 
            if (mpi_errno != MPI_SUCCESS)
79
 
            {
80
 
                MPID_Progress_end(&progress_state);
81
 
                MPIU_ERR_SETANDJUMP(mpi_errno,MPI_ERR_OTHER,"**winnoprogress");
82
 
            }
83
 
            /* --END ERROR HANDLING-- */
84
 
        }
85
 
        MPID_Progress_end(&progress_state);
86
 
        MPIU_INSTR_DURATION_END(winfree_complete);
87
 
    }
88
 
 
89
55
    mpi_errno = MPIR_Comm_free_impl(comm_ptr);
90
56
    if (mpi_errno) MPIU_ERR_POP(mpi_errno);
91
57
 
97
63
    MPIU_Free((*win_ptr)->pt_rma_puts_accs);
98
64
 
99
65
    /* Free the attached buffer for windows created with MPI_Win_allocate() */
100
 
    if ((*win_ptr)->create_flavor == MPI_WIN_FLAVOR_ALLOCATE && (*win_ptr)->size > 0) {
101
 
      MPIU_Free((*win_ptr)->base);
 
66
    if ((*win_ptr)->create_flavor == MPI_WIN_FLAVOR_ALLOCATE || (*win_ptr)->create_flavor == MPI_WIN_FLAVOR_SHARED) {
 
67
        if ((*win_ptr)->shm_allocated == FALSE && (*win_ptr)->size > 0) {
 
68
            MPIU_Free((*win_ptr)->base);
 
69
        }
102
70
    }
103
71
 
104
72
    MPIU_Object_release_ref(*win_ptr, &in_use);
116
84
 
117
85
 
118
86
#undef FUNCNAME
119
 
#define FUNCNAME MPIDI_SHM_Win_free
120
 
#undef FCNAME
121
 
#define FCNAME MPIDI_QUOTE(FUNCNAME)
122
 
int MPIDI_SHM_Win_free(MPID_Win **win_ptr)
123
 
{
124
 
    int mpi_errno = MPI_SUCCESS;
125
 
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_SHM_WIN_FREE);
126
 
 
127
 
    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_SHM_WIN_FREE);
128
 
 
129
 
    /* Free memory allocated by the default shared memory window
130
 
       implementation.  Note that this implementation works only for
131
 
       MPI_COMM_SELF and does not map a shared segment. */
132
 
 
133
 
    MPIU_Free((*win_ptr)->base);
134
 
    MPIU_Free((*win_ptr)->shm_base_addrs);
135
 
 
136
 
    mpi_errno = MPIDI_Win_free(win_ptr);
137
 
    if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
138
 
 
139
 
 fn_exit:
140
 
    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_SHM_WIN_FREE);
141
 
    return mpi_errno;
142
 
    /* --BEGIN ERROR HANDLING-- */
143
 
 fn_fail:
144
 
    goto fn_exit;
145
 
    /* --END ERROR HANDLING-- */
146
 
}
147
 
 
148
 
 
149
 
#undef FUNCNAME
150
87
#define FUNCNAME MPIDI_Win_shared_query
151
88
#undef FCNAME
152
89
#define FCNAME MPIDI_QUOTE(FUNCNAME)
158
95
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_WIN_SHARED_QUERY);
159
96
    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_WIN_SHARED_QUERY);
160
97
 
161
 
    *(void**) baseptr = win_ptr->shm_base_addrs[0];
 
98
    *(void**) baseptr = win_ptr->base;
162
99
    *size             = win_ptr->size;
163
100
    *disp_unit        = win_ptr->disp_unit;
164
101
 
181
118
            int target_count, MPI_Datatype target_datatype, MPID_Win *win_ptr)
182
119
{
183
120
    int mpi_errno = MPI_SUCCESS;
184
 
    int dt_contig ATTRIBUTE((unused)), rank, predefined;
 
121
    int dt_contig ATTRIBUTE((unused)), rank;
185
122
    MPID_Datatype *dtp;
186
123
    MPI_Aint dt_true_lb ATTRIBUTE((unused));
187
124
    MPIDI_msg_sz_t data_sz;
 
125
    MPIDI_VC_t *orig_vc, *target_vc;
188
126
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_PUT);
189
127
        
190
128
    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_PUT);
207
145
        goto fn_exit;
208
146
    }
209
147
 
210
 
    rank = win_ptr->myrank;
 
148
    rank = win_ptr->comm_ptr->rank;
211
149
    
 
150
    if (win_ptr->shm_allocated == TRUE && target_rank != rank && win_ptr->create_flavor != MPI_WIN_FLAVOR_SHARED) {
 
151
        /* check if target is local and shared memory is allocated on window,
 
152
           if so, we directly perform this operation on shared memory region. */
 
153
 
 
154
        /* FIXME: Here we decide whether to perform SHM operations by checking if origin and target are on
 
155
           the same node. However, in ch3:sock, even if origin and target are on the same node, they do
 
156
           not within the same SHM region. Here we filter out ch3:sock by checking shm_allocated flag first,
 
157
           which is only set to TRUE when SHM region is allocated in nemesis.
 
158
           In future we need to figure out a way to check if origin and target are in the same "SHM comm".
 
159
        */
 
160
        MPIDI_Comm_get_vc(win_ptr->comm_ptr, rank, &orig_vc);
 
161
        MPIDI_Comm_get_vc(win_ptr->comm_ptr, target_rank, &target_vc);
 
162
    }
 
163
 
212
164
    /* If the put is a local operation, do it here */
213
 
    if (target_rank == rank || win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
 
165
    if (target_rank == rank || win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED ||
 
166
        (win_ptr->shm_allocated == TRUE && orig_vc->node_id == target_vc->node_id))
214
167
    {
215
 
        void *base;
216
 
        int disp_unit;
217
 
 
218
 
        if (win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED) {
219
 
            base = win_ptr->shm_base_addrs[target_rank];
220
 
            disp_unit = win_ptr->disp_units[target_rank];
221
 
        }
222
 
        else {
223
 
            base = win_ptr->base;
224
 
            disp_unit = win_ptr->disp_unit;
225
 
        }
226
 
 
227
 
        mpi_errno = MPIR_Localcopy(origin_addr, origin_count, origin_datatype,
228
 
                                   (char *) base + disp_unit * target_disp,
229
 
                                   target_count, target_datatype);
230
 
        if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
 
168
        mpi_errno = MPIDI_CH3I_Shm_put_op(origin_addr, origin_count, origin_datatype, target_rank,
 
169
                                          target_disp, target_count, target_datatype, win_ptr);
 
170
        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
231
171
    }
232
172
    else
233
173
    {
235
175
        MPIDI_RMA_Op_t *new_ptr = NULL;
236
176
 
237
177
        /* queue it up */
238
 
        MPIU_INSTR_DURATION_START(rmaqueue_alloc);
 
178
        MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_alloc);
239
179
        mpi_errno = MPIDI_CH3I_RMA_Ops_alloc_tail(ops_list, &new_ptr);
240
 
        MPIU_INSTR_DURATION_END(rmaqueue_alloc);
 
180
        MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_alloc);
241
181
        if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
242
182
 
243
 
        MPIU_INSTR_DURATION_START(rmaqueue_set);
 
183
        MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_set);
244
184
        /* FIXME: For contig and very short operations, use a streamlined op */
245
185
        new_ptr->type = MPIDI_RMA_PUT;
246
186
        /* Cast away const'ness for the origin address, as the
253
193
        new_ptr->target_disp = target_disp;
254
194
        new_ptr->target_count = target_count;
255
195
        new_ptr->target_datatype = target_datatype;
256
 
        MPIU_INSTR_DURATION_END(rmaqueue_set);
 
196
        MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_set);
257
197
 
258
198
        /* if source or target datatypes are derived, increment their
259
 
           reference counts */ 
260
 
        MPIDI_CH3I_DATATYPE_IS_PREDEFINED(origin_datatype, predefined);
261
 
        if (!predefined)
 
199
           reference counts */
 
200
        if (!MPIR_DATATYPE_IS_PREDEFINED(origin_datatype))
262
201
        {
263
202
            MPID_Datatype_get_ptr(origin_datatype, dtp);
264
203
            MPID_Datatype_add_ref(dtp);
265
204
        }
266
 
        MPIDI_CH3I_DATATYPE_IS_PREDEFINED(target_datatype, predefined);
267
 
        if (!predefined)
 
205
        if (!MPIR_DATATYPE_IS_PREDEFINED(target_datatype))
268
206
        {
269
207
            MPID_Datatype_get_ptr(target_datatype, dtp);
270
208
            MPID_Datatype_add_ref(dtp);
293
231
{
294
232
    int mpi_errno = MPI_SUCCESS;
295
233
    MPIDI_msg_sz_t data_sz;
296
 
    int dt_contig ATTRIBUTE((unused)), rank, predefined;
 
234
    int dt_contig ATTRIBUTE((unused)), rank;
297
235
    MPI_Aint dt_true_lb ATTRIBUTE((unused));
298
236
    MPID_Datatype *dtp;
 
237
    MPIDI_VC_t *orig_vc, *target_vc;
299
238
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_GET);
300
239
        
301
240
    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_GET);
318
257
        goto fn_exit;
319
258
    }
320
259
 
321
 
    rank = win_ptr->myrank;
 
260
    rank = win_ptr->comm_ptr->rank;
 
261
 
 
262
    if (win_ptr->shm_allocated == TRUE && target_rank != rank && win_ptr->create_flavor != MPI_WIN_FLAVOR_SHARED) {
 
263
        /* check if target is local and shared memory is allocated on window,
 
264
           if so, we directly perform this operation on shared memory region. */
 
265
 
 
266
        /* FIXME: Here we decide whether to perform SHM operations by checking if origin and target are on
 
267
           the same node. However, in ch3:sock, even if origin and target are on the same node, they do
 
268
           not within the same SHM region. Here we filter out ch3:sock by checking shm_allocated flag first,
 
269
           which is only set to TRUE when SHM region is allocated in nemesis.
 
270
           In future we need to figure out a way to check if origin and target are in the same "SHM comm".
 
271
        */
 
272
        MPIDI_Comm_get_vc(win_ptr->comm_ptr, rank, &orig_vc);
 
273
        MPIDI_Comm_get_vc(win_ptr->comm_ptr, target_rank, &target_vc);
 
274
    }
322
275
    
323
276
    /* If the get is a local operation, do it here */
324
 
    if (target_rank == rank || win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
 
277
    if (target_rank == rank || win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED ||
 
278
        (win_ptr->shm_allocated == TRUE && orig_vc->node_id == target_vc->node_id))
325
279
    {
326
 
        void *base;
327
 
        int disp_unit;
328
 
 
329
 
        if (win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED) {
330
 
            base = win_ptr->shm_base_addrs[target_rank];
331
 
            disp_unit = win_ptr->disp_units[target_rank];
332
 
        }
333
 
        else {
334
 
            base = win_ptr->base;
335
 
            disp_unit = win_ptr->disp_unit;
336
 
        }
337
 
 
338
 
        mpi_errno = MPIR_Localcopy((char *) base + disp_unit * target_disp,
339
 
                                   target_count, target_datatype, origin_addr,
340
 
                                   origin_count, origin_datatype);
341
 
        if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
 
280
        mpi_errno = MPIDI_CH3I_Shm_get_op(origin_addr, origin_count, origin_datatype, target_rank,
 
281
                                          target_disp, target_count, target_datatype, win_ptr);
 
282
        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
342
283
    }
343
284
    else
344
285
    {
346
287
        MPIDI_RMA_Op_t *new_ptr = NULL;
347
288
 
348
289
        /* queue it up */
349
 
        MPIU_INSTR_DURATION_START(rmaqueue_alloc);
 
290
        MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_alloc);
350
291
        mpi_errno = MPIDI_CH3I_RMA_Ops_alloc_tail(ops_list, &new_ptr);
351
 
        MPIU_INSTR_DURATION_END(rmaqueue_alloc);
 
292
        MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_alloc);
352
293
        if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
353
294
 
354
 
        MPIU_INSTR_DURATION_START(rmaqueue_set);
 
295
        MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_set);
355
296
        /* FIXME: For contig and very short operations, use a streamlined op */
356
297
        new_ptr->type = MPIDI_RMA_GET;
357
298
        new_ptr->origin_addr = origin_addr;
361
302
        new_ptr->target_disp = target_disp;
362
303
        new_ptr->target_count = target_count;
363
304
        new_ptr->target_datatype = target_datatype;
364
 
        MPIU_INSTR_DURATION_END(rmaqueue_set);
 
305
        MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_set);
365
306
        
366
307
        /* if source or target datatypes are derived, increment their
367
 
           reference counts */ 
368
 
        MPIDI_CH3I_DATATYPE_IS_PREDEFINED(origin_datatype, predefined);
369
 
        if (!predefined)
 
308
           reference counts */
 
309
        if (!MPIR_DATATYPE_IS_PREDEFINED(origin_datatype))
370
310
        {
371
311
            MPID_Datatype_get_ptr(origin_datatype, dtp);
372
312
            MPID_Datatype_add_ref(dtp);
373
313
        }
374
 
        MPIDI_CH3I_DATATYPE_IS_PREDEFINED(target_datatype, predefined);
375
 
        if (!predefined)
 
314
        if (!MPIR_DATATYPE_IS_PREDEFINED(target_datatype))
376
315
        {
377
316
            MPID_Datatype_get_ptr(target_datatype, dtp);
378
317
            MPID_Datatype_add_ref(dtp);
402
341
{
403
342
    int mpi_errno=MPI_SUCCESS;
404
343
    MPIDI_msg_sz_t data_sz;
405
 
    int dt_contig ATTRIBUTE((unused)), rank, origin_predefined, target_predefined;
 
344
    int dt_contig ATTRIBUTE((unused)), rank;
406
345
    MPI_Aint dt_true_lb ATTRIBUTE((unused));
407
346
    MPID_Datatype *dtp;
408
 
    MPIU_CHKLMEM_DECL(2);
 
347
    MPIDI_VC_t *orig_vc, *target_vc;
409
348
    MPIDI_STATE_DECL(MPID_STATE_MPIDI_ACCUMULATE);
410
349
    
411
350
    MPIDI_RMA_FUNC_ENTER(MPID_STATE_MPIDI_ACCUMULATE);
428
367
        goto fn_exit;
429
368
    }
430
369
 
431
 
    rank = win_ptr->myrank;
 
370
    rank = win_ptr->comm_ptr->rank;
432
371
    
433
 
    MPIDI_CH3I_DATATYPE_IS_PREDEFINED(origin_datatype, origin_predefined);
434
 
    MPIDI_CH3I_DATATYPE_IS_PREDEFINED(target_datatype, target_predefined);
 
372
    if (win_ptr->shm_allocated == TRUE && target_rank != rank && win_ptr->create_flavor != MPI_WIN_FLAVOR_SHARED) {
 
373
        /* check if target is local and shared memory is allocated on window,
 
374
           if so, we directly perform this operation on shared memory region. */
 
375
 
 
376
        /* FIXME: Here we decide whether to perform SHM operations by checking if origin and target are on
 
377
           the same node. However, in ch3:sock, even if origin and target are on the same node, they do
 
378
           not within the same SHM region. Here we filter out ch3:sock by checking shm_allocated flag first,
 
379
           which is only set to TRUE when SHM region is allocated in nemesis.
 
380
           In future we need to figure out a way to check if origin and target are in the same "SHM comm".
 
381
        */
 
382
        MPIDI_Comm_get_vc(win_ptr->comm_ptr, rank, &orig_vc);
 
383
        MPIDI_Comm_get_vc(win_ptr->comm_ptr, target_rank, &target_vc);
 
384
    }
435
385
 
436
386
    /* Do =! rank first (most likely branch?) */
437
 
    if (target_rank == rank || win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED)
 
387
    if (target_rank == rank || win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED ||
 
388
        (win_ptr->shm_allocated == TRUE && orig_vc->node_id == target_vc->node_id))
438
389
    {
439
 
        MPI_User_function *uop;
440
 
        void *base;
441
 
        int disp_unit, shm_op = 0;
442
 
 
443
 
        if (win_ptr->create_flavor == MPI_WIN_FLAVOR_SHARED) {
444
 
            shm_op = 1;
445
 
            base = win_ptr->shm_base_addrs[target_rank];
446
 
            disp_unit = win_ptr->disp_units[target_rank];
447
 
        }
448
 
        else {
449
 
            base = win_ptr->base;
450
 
            disp_unit = win_ptr->disp_unit;
451
 
        }
452
 
        
453
 
        if (op == MPI_REPLACE)
454
 
        {
455
 
            if (shm_op) MPIDI_CH3I_SHM_MUTEX_LOCK(win_ptr);
456
 
            mpi_errno = MPIR_Localcopy(origin_addr, origin_count,
457
 
                                       origin_datatype,
458
 
                                       (char *) base + disp_unit * target_disp,
459
 
                                       target_count, target_datatype);
460
 
            if (shm_op) MPIDI_CH3I_SHM_MUTEX_UNLOCK(win_ptr);
461
 
            if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
462
 
            goto fn_exit;
463
 
        }
464
 
        
465
 
        MPIU_ERR_CHKANDJUMP1((HANDLE_GET_KIND(op) != HANDLE_KIND_BUILTIN), 
466
 
                             mpi_errno, MPI_ERR_OP, "**opnotpredefined",
467
 
                             "**opnotpredefined %d", op );
468
 
        
469
 
        /* get the function by indexing into the op table */
470
 
        uop = MPIR_OP_HDL_TO_FN(op);
471
 
        
472
 
        if (origin_predefined && target_predefined)
473
 
        {    
474
 
            /* Cast away const'ness for origin_address in order to
475
 
             * avoid changing the prototype for MPI_User_function */
476
 
            if (shm_op) MPIDI_CH3I_SHM_MUTEX_LOCK(win_ptr);
477
 
            (*uop)((void *) origin_addr, (char *) base + disp_unit*target_disp,
478
 
                   &target_count, &target_datatype);
479
 
            if (shm_op) MPIDI_CH3I_SHM_MUTEX_UNLOCK(win_ptr);
480
 
        }
481
 
        else
482
 
        {
483
 
            /* derived datatype */
484
 
            
485
 
            MPID_Segment *segp;
486
 
            DLOOP_VECTOR *dloop_vec;
487
 
            MPI_Aint first, last;
488
 
            int vec_len, i, type_size, count;
489
 
            MPI_Datatype type;
490
 
            MPI_Aint true_lb, true_extent, extent;
491
 
            void *tmp_buf=NULL, *target_buf;
492
 
            const void *source_buf;
493
 
            
494
 
            if (origin_datatype != target_datatype)
495
 
            {
496
 
                /* first copy the data into a temporary buffer with
497
 
                   the same datatype as the target. Then do the
498
 
                   accumulate operation. */
499
 
                
500
 
                MPIR_Type_get_true_extent_impl(target_datatype, &true_lb, &true_extent);
501
 
                MPID_Datatype_get_extent_macro(target_datatype, extent); 
502
 
                
503
 
                MPIU_CHKLMEM_MALLOC(tmp_buf, void *, 
504
 
                        target_count * (MPIR_MAX(extent,true_extent)), 
505
 
                        mpi_errno, "temporary buffer");
506
 
                /* adjust for potential negative lower bound in datatype */
507
 
                tmp_buf = (void *)((char*)tmp_buf - true_lb);
508
 
                
509
 
                mpi_errno = MPIR_Localcopy(origin_addr, origin_count,
510
 
                                           origin_datatype, tmp_buf,
511
 
                                           target_count, target_datatype);  
512
 
                if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
513
 
            }
514
 
 
515
 
            if (target_predefined) { 
516
 
                /* target predefined type, origin derived datatype */
517
 
 
518
 
                if (shm_op) MPIDI_CH3I_SHM_MUTEX_LOCK(win_ptr);
519
 
                (*uop)(tmp_buf, (char *) base + disp_unit * target_disp,
520
 
                       &target_count, &target_datatype);
521
 
                if (shm_op) MPIDI_CH3I_SHM_MUTEX_UNLOCK(win_ptr);
522
 
            }
523
 
            else {
524
 
            
525
 
                segp = MPID_Segment_alloc();
526
 
                MPIU_ERR_CHKANDJUMP1((!segp), mpi_errno, MPI_ERR_OTHER, 
527
 
                                    "**nomem","**nomem %s","MPID_Segment_alloc"); 
528
 
                MPID_Segment_init(NULL, target_count, target_datatype, segp, 0);
529
 
                first = 0;
530
 
                last  = SEGMENT_IGNORE_LAST;
531
 
                
532
 
                MPID_Datatype_get_ptr(target_datatype, dtp);
533
 
                vec_len = dtp->max_contig_blocks * target_count + 1; 
534
 
                /* +1 needed because Rob says so */
535
 
                MPIU_CHKLMEM_MALLOC(dloop_vec, DLOOP_VECTOR *, 
536
 
                                    vec_len * sizeof(DLOOP_VECTOR), 
537
 
                                    mpi_errno, "dloop vector");
538
 
                
539
 
                MPID_Segment_pack_vector(segp, first, &last, dloop_vec, &vec_len);
540
 
                
541
 
                source_buf = (tmp_buf != NULL) ? tmp_buf : origin_addr;
542
 
                target_buf = (char *) base + disp_unit * target_disp;
543
 
                type = dtp->eltype;
544
 
                type_size = MPID_Datatype_get_basic_size(type);
545
 
                if (shm_op) MPIDI_CH3I_SHM_MUTEX_LOCK(win_ptr);
546
 
                for (i=0; i<vec_len; i++)
547
 
                {
548
 
                    count = (dloop_vec[i].DLOOP_VECTOR_LEN)/type_size;
549
 
                    (*uop)((char *)source_buf + MPIU_PtrToAint(dloop_vec[i].DLOOP_VECTOR_BUF),
550
 
                           (char *)target_buf + MPIU_PtrToAint(dloop_vec[i].DLOOP_VECTOR_BUF),
551
 
                           &count, &type);
552
 
                }
553
 
                if (shm_op) MPIDI_CH3I_SHM_MUTEX_UNLOCK(win_ptr);
554
 
                
555
 
                MPID_Segment_free(segp);
556
 
            }
557
 
        }
 
390
        mpi_errno = MPIDI_CH3I_Shm_acc_op(origin_addr, origin_count, origin_datatype,
 
391
                                          target_rank, target_disp, target_count, target_datatype,
 
392
                                          op, win_ptr);
 
393
        if (mpi_errno) MPIU_ERR_POP(mpi_errno);
558
394
    }
559
395
    else
560
396
    {
562
398
        MPIDI_RMA_Op_t *new_ptr = NULL;
563
399
 
564
400
        /* queue it up */
565
 
        MPIU_INSTR_DURATION_START(rmaqueue_alloc);
 
401
        MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_alloc);
566
402
        mpi_errno = MPIDI_CH3I_RMA_Ops_alloc_tail(ops_list, &new_ptr);
567
 
        MPIU_INSTR_DURATION_END(rmaqueue_alloc);
 
403
        MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_alloc);
568
404
        if (mpi_errno) { MPIU_ERR_POP(mpi_errno); }
569
405
 
570
406
        /* If predefined and contiguous, use a simplified element */
571
 
        if (origin_predefined && target_predefined && enableShortACC) {
572
 
            MPIU_INSTR_DURATION_START(rmaqueue_set);
 
407
        if (MPIR_DATATYPE_IS_PREDEFINED(origin_datatype) &&
 
408
            MPIR_DATATYPE_IS_PREDEFINED(target_datatype) && enableShortACC) {
 
409
            MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_set);
573
410
            new_ptr->type = MPIDI_RMA_ACC_CONTIG;
574
411
            /* Only the information needed for the contig/predefined acc */
575
412
            /* Cast away const'ness for origin_address as
582
419
            new_ptr->target_count = target_count;
583
420
            new_ptr->target_datatype = target_datatype;
584
421
            new_ptr->op = op;
585
 
            MPIU_INSTR_DURATION_END(rmaqueue_set);
 
422
            MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_set);
586
423
            goto fn_exit;
587
424
        }
588
425
 
589
 
        MPIU_INSTR_DURATION_START(rmaqueue_set);
 
426
        MPIR_T_PVAR_TIMER_START(RMA, rma_rmaqueue_set);
590
427
        new_ptr->type = MPIDI_RMA_ACCUMULATE;
591
428
        /* Cast away const'ness for origin_address as MPIDI_RMA_Op_t
592
429
         * contain both PUT and GET like ops */
598
435
        new_ptr->target_count = target_count;
599
436
        new_ptr->target_datatype = target_datatype;
600
437
        new_ptr->op = op;
601
 
        MPIU_INSTR_DURATION_END(rmaqueue_set);
 
438
        MPIR_T_PVAR_TIMER_END(RMA, rma_rmaqueue_set);
602
439
        
603
440
        /* if source or target datatypes are derived, increment their
604
 
           reference counts */ 
605
 
        if (!origin_predefined)
 
441
           reference counts */
 
442
        if (!MPIR_DATATYPE_IS_PREDEFINED(origin_datatype))
606
443
        {
607
444
            MPID_Datatype_get_ptr(origin_datatype, dtp);
608
445
            MPID_Datatype_add_ref(dtp);
609
446
        }
610
 
        if (!target_predefined)
 
447
        if (!MPIR_DATATYPE_IS_PREDEFINED(target_datatype))
611
448
        {
612
449
            MPID_Datatype_get_ptr(target_datatype, dtp);
613
450
            MPID_Datatype_add_ref(dtp);
615
452
    }
616
453
 
617
454
 fn_exit:
618
 
    MPIU_CHKLMEM_FREEALL();
619
455
    MPIDI_RMA_FUNC_EXIT(MPID_STATE_MPIDI_ACCUMULATE);
620
456
    return mpi_errno;
621
457