5
/* $Id: armci.c,v 1.114.2.17 2007-08-30 22:58:18 manoj Exp $ */
9
* This material was prepared as an account of work sponsored by an
10
* agency of the United States Government. Neither the United States
11
* Government nor the United States Department of Energy, nor Battelle,
12
* nor any of their employees, MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
13
* ASSUMES ANY LEGAL LIABILITY OR RESPONSIBILITY FOR THE ACCURACY,
14
* COMPLETENESS, OR USEFULNESS OF ANY INFORMATION, APPARATUS, PRODUCT,
15
* SOFTWARE, OR PROCESS DISCLOSED, OR REPRESENTS THAT ITS USE WOULD NOT
16
* INFRINGE PRIVATELY OWNED RIGHTS.
21
* This software and its documentation were produced with United States
22
* Government support under Contract Number DE-AC06-76RLO-1830 awarded by
23
* the United States Department of Energy. The United States Government
24
* retains a paid-up non-exclusive, irrevocable worldwide license to
25
* reproduce, prepare derivative works, perform publicly and display
26
* publicly by or for the US Government, including the right to
27
* distribute to other US Government contractors.
36
#if defined(CRAY) && !defined(__crayx1)
37
# include <sys/category.h>
38
# include <sys/resource.h>
42
# include "lapidefs.h"
49
#include "signaltrap.h"
58
extern void armci_msg_barrier(void);
63
# include <mpp/shmem.h>
71
/* global variables */
72
int armci_me, armci_Sme, armci_nproc;
73
int armci_clus_me, armci_nclus, armci_master;
74
int armci_clus_first, armci_clus_last;
75
int *_armci_argc=NULL;
76
char ***_armci_argv=NULL;
77
int _armci_initialized_args=0;
78
int _armci_initialized=0;
79
int _armci_terminating =0;
80
thread_id_t armci_usr_tid;
81
armci_ireq_t armci_inb_handle[ARMCI_MAX_IMPLICIT];/*implicit non-blocking handle*/
83
double armci_internal_buffer[BUFSIZE_DBL];
85
#if defined(SYSV) || defined(WIN32) || defined(MMAP) || defined(HITACHI) || defined(CATAMOUNT) || defined(BGML)
90
int* armci_prot_switch_fence=NULL;
91
int armci_prot_switch_preproc = -1;
92
int armci_prot_switch_preop = -1;
95
/* void armci_allocate_locks(); */
96
void armci_init_memlock();
99
#ifdef LIBELAN_ATOMICS
101
#warning "Enabling new atomics"
110
armci_notify_t **_armci_notify_arr;
114
#if defined(DATA_SERVER)
115
#if defined(LIBONESIDED)
119
armci_wait_for_server();
124
#if (defined(SYSV) || defined(WIN32) || defined(MMAP))&& !defined(HITACHI)
125
Delete_All_Regions();
132
ARMCI_RestoreSignals();
136
armci_transport_cleanup();
140
int armci_getbufsize()
145
void armci_notify_init()
147
int rc,bytes=sizeof(armci_notify_t)*armci_nproc;
150
armci_elan_notify_init();
155
(armci_notify_t**)malloc(armci_nproc*sizeof(armci_notify_t*));
156
if(!_armci_notify_arr)armci_die("armci_notify_ini:malloc failed",armci_nproc);
158
if((rc=PARMCI_Malloc((void **)_armci_notify_arr, bytes)))
159
armci_die(" armci_notify_init: armci_malloc failed",bytes);
160
bzero(_armci_notify_arr[armci_me], bytes);
164
static void armci_perror_msg()
168
sprintf(perr_str,"Last System Error Message from Task %d:",armci_me);
172
static void armci_abort(int code)
179
/* data server process cannot use message-passing library to abort
180
* it simply exits, parent will get SIGCHLD and abort the program
182
#if defined(DATA_SERVER)
183
if(armci_me<0)_exit(1);
186
armci_msg_abort(code);
190
void armci_die(char *msg, int code)
194
if(_armci_terminating)return;
195
else _armci_terminating=1;
198
fprintf(stdout,"%d(s):%s: %d\n",armci_me, msg, code); fflush(stdout);
199
// fprintf(stderr,"%d(s):%s: %d\n",armci_me, msg, code);
201
fprintf(stdout,"%d:%s: %d\n",armci_me, msg, code); fflush(stdout);
202
//fprintf(stderr,"%d:%s: %d\n",armci_me, msg, code);
206
backtrace_symbols_fd(bt, backtrace(bt, 100), 2);
213
void armci_die2(char *msg, int code1, int code2)
217
if(_armci_terminating)return;
218
else _armci_terminating=1;
221
fprintf(stdout,"%d(s):%s: (%d,%d)\n",armci_me,msg,code1,code2);
223
fprintf(stderr,"%d(s):%s: (%d,%d)\n",armci_me,msg,code1,code2);
225
fprintf(stdout,"%d:%s: (%d,%d)\n",armci_me,msg,code1,code2);
227
fprintf(stderr,"%d:%s: (%d,%d)\n",armci_me,msg,code1,code2);
230
backtrace_symbols_fd(bt, backtrace(bt, 100), 2);
236
void ARMCI_Error(char *msg, int code)
242
void armci_allocate_locks()
244
/* note that if ELAN_ACC is defined the scope of locks is limited to SMP */
245
#if !defined(CRAY_SHMEM) && (defined(HITACHI) || defined(CATAMOUNT) || \
246
(defined(QUADRICS) && defined(_ELAN_LOCK_H) && !defined(ELAN_ACC)))
247
armcill_allocate_locks(NUM_LOCKS);
248
#elif (defined(SYSV) || defined(WIN32) || defined(MMAP)) && !defined(HITACHI)
249
if(armci_nproc == 1)return;
250
# if defined(SPINLOCK) || defined(PMUTEXES)
251
CreateInitLocks(NUM_LOCKS, &lockid);
253
if(armci_master==armci_me)CreateInitLocks(NUM_LOCKS, &lockid);
254
armci_msg_clus_brdcst(&lockid, sizeof(lockid));
255
if(armci_master != armci_me)InitLocks(NUM_LOCKS, lockid);
261
void ARMCI_Set_shm_limit(unsigned long shmemlimit)
263
#if (defined(SYSV) || defined(WIN32) || defined(MMAP)) && !defined(HITACHI)
264
#define EXTRASHM 1024 /* extra shmem used internally in ARMCI */
266
limit = armci_clus_info[armci_clus_me].nslave * shmemlimit + EXTRASHM;
267
armci_set_shmem_limit(limit);
273
/*\ allocate and initialize memory locking data structure
275
void armci_init_memlock()
277
int bytes = MAX_SLOTS*sizeof(memlock_t);
278
int rc, msize_per_proc=bytes;
280
#ifdef MEMLOCK_SHMEM_FLAG
281
/* last proc on node allocates memlock flag in shmem */
282
if(armci_clus_last == armci_me) bytes += sizeof(int);
285
memlock_table_array = malloc(armci_nproc*sizeof(void*));
286
if(!memlock_table_array) armci_die("malloc failed for ARMCI lock array",0);
288
rc = PARMCI_Malloc(memlock_table_array, bytes);
289
if(rc) armci_die("failed to allocate ARMCI memlock array",rc);
293
bzero(memlock_table_array[armci_me],bytes);
296
bgml_init_locks ((void *) memlock_table_array[armci_me]);
298
ARMCIX_init_memlock ((memlock_t *) memlock_table_array[armci_me]);
302
#ifdef MEMLOCK_SHMEM_FLAG
303
/* armci_use_memlock_table is a pointer to local memory variable=1
304
* we overwrite the pointer with address of shared memory variable
305
* armci_use_memlock_table and initialize it >0
307
armci_use_memlock_table = (int*) (msize_per_proc +
308
(char*) memlock_table_array[armci_clus_last]);
310
/* printf("%d: last=%d bytes=%d ptr =(%d, %d)\n",
311
armci_me,armci_clus_last,bytes,armci_use_memlock_table,
312
memlock_table_array[armci_clus_last]); fflush(stdout); */
314
if(armci_clus_last == armci_me) *armci_use_memlock_table =1+armci_me;
318
*armci_use_memlock_table = 0;
323
#if defined(SYSV) || defined(WIN32)
324
static void armci_check_shmmax()
327
mylimit = limit = (long) armci_max_region();
328
armci_msg_bcast_scope(SCOPE_MASTERS, &limit, sizeof(long), 0);
329
if(mylimit != limit){
330
printf("%d:Shared mem limit in ARMCI is %ld bytes on node %s vs %ld on %s\n",
331
armci_me,mylimit<<10,armci_clus_info[armci_clus_me].hostname,
332
limit<<10, armci_clus_info[0].hostname);
333
fflush(stdout); sleep(1);
334
armci_die("All nodes must have the same SHMMAX limit if NO_SHM is not defined",0);
339
extern void armci_region_shm_malloc(void *ptr_arr[], size_t bytes);
344
/*armci_portals_net_init();*/
347
int PARMCI_Init_args(int *argc, char ***argv)
349
armci_msg_init(argc,argv);
353
_armci_initialized_args=1;
358
extern void *sbrk(intptr_t);
359
extern void code_summary();
363
caddr_t atbeginbrval = (caddr_t)sbrk(0);
364
if(_armci_initialized>0) return 0;
366
mallopt(M_MMAP_MAX, 0);
367
mallopt(M_TRIM_THRESHOLD, -1);
370
armci_msg_init(NULL, NULL);
372
armci_nproc = armci_msg_nproc();
373
armci_me = armci_msg_me();
374
armci_usr_tid = THREAD_ID_SELF(); /*remember the main user thread id */
375
armci_init_clusinfo();
376
armci_prot_switch_fence = malloc(sizeof(int*)*armci_nproc);
377
assert(armci_prot_switch_fence !=NULL);
379
armci_onesided_init();
385
armci_krmalloc_init_localmem();
387
#if defined(SYSV) || defined(WIN32) || defined(MMAP)
388
if(ARMCI_Uses_shm() ) {
392
armci_allocate_locks();
394
#if ARMCI_ENABLE_GPC_CALLS
398
armci_init_memlock(); /* allocate data struct for locking memory areas */
400
//if(armci_me == 0) code_summary();
402
armci_msg_gop_init();
403
_armci_initialized++;
408
void PARMCI_Finalize()
410
if(!_armci_initialized)return;
411
_armci_initialized--;
412
if(_armci_initialized)return;
414
_armci_terminating =1;
416
if(armci_me==armci_master) ARMCI_ParentRestoreSignals();
419
request_header_t msg;
420
portals_ds_req_t req;
421
ptl_process_id_t dsid = portals_id_map[armci_me];
422
msg.operation = QUIT;
424
if(armci_me == armci_master) {
425
portalsBlockingRemoteOperationToNode(&msg,sizeof(request_header_t),armci_clus_me);
429
portals_cp_finalize();
435
armci_group_finalize();
436
free(armci_prot_switch_fence);
439
MPI_Comm_free(&ARMCI_COMM_WORLD); /*JD: free at last*/
444
/* Indicates whether ARMCI_Init or ARMCI_Init_args has been called. */
445
int PARMCI_Initialized()
447
return (_armci_initialized > 0) ? 1 : 0;
451
#if !(defined(SYSV) || defined(WIN32))
452
void ARMCI_Set_shmem_limit(unsigned long shmemlimit)
454
/* not applicable here
455
* aborting would make user's life harder
462
void ARMCI_Copy(void *src, void *dst, int n)
464
armci_copy(src,dst,n);
467
extern void cpu_yield();
468
void armci_util_wait_int(volatile int *p, int val, int maxspin)
471
extern void cpu_yield();
473
if((++count)<maxspin);
475
/*printf("\n%d:flag=%d val=%d",armci_me,*p,val);*/
478
#if defined(MACX) && defined(__ppc__) && defined(__GNUC__)
479
__asm__ __volatile__ ("sync" ::: "memory");
481
__asm__ __volatile__ ("mfence" ::: "memory");
482
__asm__ __volatile__ ("sfence" ::: "memory");
485
void armci_util_wait_long(volatile long *p, long val, int maxspin)
488
extern void cpu_yield();
490
if((++count)<maxspin);
492
/*printf("\n%d:flag=%d val=%d",armci_me,*p,val);*/
495
#if defined(MACX) && defined(__ppc__) && defined(__GNUC__)
496
__asm__ __volatile__ ("sync" ::: "memory");
498
__asm__ __volatile__ ("mfence" ::: "memory");
499
__asm__ __volatile__ ("sfence" ::: "memory");
503
/*\ returns 1 if specified process resides on the same smp node as calling task
505
int ARMCI_Same_node(int proc)
507
int direct=SAMECLUSNODE(proc);
511
/*\ blocks the calling process until a nonblocking operation represented
512
* by the user handle completes
514
int PARMCI_Wait(armci_hdl_t* usr_hdl){
515
armci_ihdl_t nb_handle = (armci_ihdl_t)usr_hdl;
517
int direct=SAMECLUSNODE(nb_handle->proc);
523
if(nb_handle->agg_flag) {
524
armci_agg_complete(nb_handle, UNSET);
527
if(nb_handle->tag!=0 && nb_handle->bufid==NB_NONE){
528
ARMCI_NB_WAIT(nb_handle->cmpl_info);
529
__asm__ __volatile__ ("mfence" ::: "memory");
530
__asm__ __volatile__ ("sfence" ::: "memory");
533
# ifdef COMPLETE_HANDLE
534
COMPLETE_HANDLE(nb_handle->bufid,nb_handle->tag,(&success));
538
__asm__ __volatile__ ("mfence" ::: "memory");
539
__asm__ __volatile__ ("sfence" ::: "memory");
546
static char hdl_flag[ARMCI_MAX_IMPLICIT];
547
static int impcount=0;
548
armci_ihdl_t armci_set_implicit_handle (int op, int proc) {
550
int i=impcount%ARMCI_MAX_IMPLICIT;
552
PARMCI_Wait((armci_hdl_t*)&armci_inb_handle[i]);
555
armci_inb_handle[i].count=0;
557
armci_inb_handle[i].tag = GET_NEXT_NBTAG();
558
armci_inb_handle[i].op = op;
559
armci_inb_handle[i].proc = proc;
560
armci_inb_handle[i].bufid = NB_NONE;
561
armci_inb_handle[i].agg_flag = 0;
564
return &armci_inb_handle[i];
568
/* wait for all non-blocking operations to finish */
569
int PARMCI_WaitAll (void) {
577
for(i=0; i<ARMCI_MAX_IMPLICIT; i++) {
578
if(hdl_flag[i] == '1') {
579
PARMCI_Wait((armci_hdl_t*)&armci_inb_handle[i]);
589
/* wait for all non-blocking operations to a particular process to finish */
590
int PARMCI_WaitProc (int proc) {
594
ARMCIX_WaitProc (proc);
598
for(i=0; i<ARMCI_MAX_IMPLICIT; i++) {
599
if(hdl_flag[i]=='1' && armci_inb_handle[i].proc==proc) {
600
PARMCI_Wait((armci_hdl_t*)&armci_inb_handle[i]);
609
static unsigned int _armci_nb_tag=0;
610
unsigned int _armci_get_next_tag(){
611
return((++_armci_nb_tag));
614
void ARMCI_SET_AGGREGATE_HANDLE(armci_hdl_t* nb_handle) {
615
((armci_ihdl_t)(nb_handle))->agg_flag = 1;
616
((armci_ihdl_t)(nb_handle))->proc = -1;
619
void ARMCI_UNSET_AGGREGATE_HANDLE(armci_hdl_t* nb_handle) {
620
((armci_ihdl_t)(nb_handle))->agg_flag = 0;
621
((armci_ihdl_t)(nb_handle))->proc = -1;
624
int armci_notify(int proc)
631
#if defined(GM) || (defined(DOELAN4) && defined(ELAN_ACC))
633
extern int armci_inotify_proc(int);
634
return(armci_inotify_proc(proc));
637
armci_notify_t *pnotify = _armci_notify_arr[armci_me]+proc;
640
if(SAMECLUSNODE(proc)) MEM_FENCE;
642
PARMCI_Put(&pnotify->sent,&(_armci_notify_arr[proc]+armci_me)->received,
643
sizeof(pnotify->sent),proc);
644
return(pnotify->sent);
649
/*\ blocks until received count becomes >= waited count
650
* return received count and store waited count in *pval
652
int parmci_notify_wait(int proc,int *pval)
664
#if defined(GM) || (defined(DOELAN4) && defined(ELAN_ACC))
666
extern int armci_inotify_wait(int,int*);
667
retval=armci_inotify_wait(proc,pval);
672
armci_notify_t *pnotify = _armci_notify_arr[armci_me]+proc;
674
while( pnotify->waited > pnotify->received) {
675
if(++loop == 1000) { loop=0;cpu_yield(); }
676
armci_util_spin(loop, pnotify);
678
*pval = pnotify->waited;
679
retval=pnotify->received;
686
long armci_util_long_getval(long* p)
691
int armci_util_int_getval(int* p)
697
int PARMCI_Test(armci_hdl_t *usr_hdl)
699
armci_ihdl_t nb_handle = (armci_ihdl_t)usr_hdl;
702
success=(int)nb_handle->count;
704
int direct=SAMECLUSNODE(nb_handle->proc);
705
if(direct)return(success);
707
if(nb_handle->agg_flag) {
708
armci_die("test for aggregate handle not yet implemented\n",0);
712
# ifdef ARMCI_NB_TEST
713
if(nb_handle->tag==0){
714
ARMCI_NB_TEST(nb_handle->cmpl_info,&success);
718
if(nb_handle->tag!=0 && nb_handle->bufid==NB_NONE){
719
ARMCI_NB_TEST(nb_handle->cmpl_info,&success);
725
TEST_HANDLE(nb_handle->bufid,nb_handle->tag,(&success));
733
void ARMCI_Ckpt_create_ds(armci_ckpt_ds_t *ckptds, int count)
735
armci_create_ckptds(ckptds,count);
738
int ARMCI_Ckpt_init(char *filename, ARMCI_Group *grp, int savestack, int saveheap, armci_ckpt_ds_t *ckptds)
741
rid = armci_icheckpoint_init(filename,grp,savestack,saveheap,ckptds);
745
int ARMCI_Ckpt(int rid)
747
return(armci_icheckpoint(rid));
750
void ARMCI_Ckpt_Recover(int rid, int iamreplacement)
752
armci_irecover(rid, iamreplacement);
754
void ARMCI_Ckpt_finalize(int rid)
756
armci_icheckpoint_finalize(rid);
759
#if ARMCI_ENABLE_GPC_CALLS
760
int armci_gpc(int hndl, int proc, void *hdr, int hlen, void *data, int dlen,
761
void *rhdr, int rhlen, void *rdata, int rdlen,
763
armci_ihdl_t nb_handle = (armci_ihdl_t)nbh;
764
armci_giov_t darr[2]; /* = {{&rhdr, &rhdr, 1, rhlen}, {&rdata, &rdata, 1, rdlen}};*/
768
/* initialize giov */
769
darr[0].src_ptr_array = &rhdr;
770
darr[0].dst_ptr_array = &rhdr;
771
darr[0].ptr_array_len = 1;
772
darr[0].bytes = rhlen;
774
darr[1].src_ptr_array = &rdata;
775
darr[1].dst_ptr_array = &rdata;
776
darr[1].ptr_array_len = 1;
777
darr[1].bytes = rdlen;
780
/* if(hlen<0 || hlen>=ARMCI_Gpc_get_hlen()) */
782
/* if(rhlen<0 || rhlen>=ARMCI_Gpc_get_hlen()) */
784
/* if(dlen<0 || dlen>=ARMCI_Gpc_get_dlen()) */
786
/* if(rdlen<0 || rdlen>=ARMCI_Gpc_get_dlen()) */
789
if(hlen>0 && hdr==NULL)
791
if(rhlen>0 && rhdr==NULL)
793
if(dlen>0 && data==NULL)
795
if(rdlen>0 && rdata==NULL)
798
if(proc<0 || proc >= armci_nproc)
808
nb_handle->tag = GET_NEXT_NBTAG();
810
nb_handle->proc= proc;
811
nb_handle->bufid=NB_NONE;
814
ORDER(GET,proc); /*ensure ordering */
818
#if defined(LAPI) || defined(GM) || defined(VAPI) || defined(QUADRICS)
819
if(armci_rem_gpc(GET, darr, 2, &send, proc, 1, nb_handle))
825
int armci_sameclusnode(int proc) {
826
return SAMECLUSNODE(proc);
830
void _armci_init_handle(armci_hdl_t *hdl)
832
((double *)((hdl)->data))[0]=0;
833
((double *)((hdl)->data))[1]=0;
836
static inline int val_to_char(int v)
838
if (v >= 0 && v < 10)
840
else if (v >= 10 && v < 16)
841
return ('a' - 10) + v;
845
static const char *nexttoken(const char *q, int sep)
854
#ifdef PORTALS_UNRESOLVED
855
int cstr_to_cpuset(cpu_set_t * mask, const char *str)
861
while (p = q, q = nexttoken(q, ','), p) {
862
unsigned int a; /* beginning of range */
863
unsigned int b; /* end of range */
864
unsigned int s; /* stride */
866
if (sscanf(p, "%u", &a) < 1)
870
c1 = nexttoken(p, '-');
871
c2 = nexttoken(p, ',');
872
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
873
if (sscanf(c1, "%u", &b) < 1)
875
c1 = nexttoken(c1, ':');
876
if (c1 != NULL && (c2 == NULL || c1 < c2))
877
if (sscanf(c1, "%u", &s) < 1) {
891
char *cpuset_to_cstr(cpu_set_t * mask, char *str)
896
for (i = 0; i < CPU_SETSIZE; i++) {
897
if (CPU_ISSET(i, mask)) {
901
for (j = i + 1; j < CPU_SETSIZE; j++) {
902
if (CPU_ISSET(j, mask))
908
sprintf(ptr, "%d,", i);
910
sprintf(ptr, "%d,%d,", i, i + 1);
913
sprintf(ptr, "%d-%d,", i, i + run);
925
char *cpuset_to_str(cpu_set_t * mask, char *str)
930
for (base = CPU_SETSIZE - 4; base >= 0; base -= 4) {
932
if (CPU_ISSET(base, mask))
934
if (CPU_ISSET(base + 1, mask))
936
if (CPU_ISSET(base + 2, mask))
938
if (CPU_ISSET(base + 3, mask))
942
*ptr++ = val_to_char(val);
945
return ret ? ret : ptr - 1;
950
long armci_cksm_copy(char *src, char *dst, size_t bytes)
955
sum += * (unsigned int *) src++;
960
printf("\nblistering barnicles");
961
sum += * (unsigned char *) src;
965
sum = (sum & 0xffffffff) + (sum >> 32);
969
void code_summary() {
970
printf("\nActive #defines that could affect ARMCI");
971
printf("\n----------------------------------------");
972
# ifdef ORNL_USE_DS_FOR_REMOTE_GETS
973
printf("\n#define ORNL_USE_DS_FOR_REMOTE_GETS");
976
# ifdef PORTALS_USE_RENDEZ_VOUS
977
printf("\n#define PORTALS_USE_RENDEZ_VOUS");
980
# ifdef PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE
981
printf("\n#define PORTALS_LIMIT_REMOTE_REQUESTS_BY_NODE");
984
# ifdef PORTALS_AFFINITY
985
printf("\n#define PORTALS_AFFINITY");
989
# ifdef CRAY_USE_MDMD_COPY
990
printf("\n#define CRAY_USE_MDMD_COPY");
993
printf("\n----------------------------------------");
994
printf("\nInfo @ armci/src/code_options.h");
995
printf("\n----------------------------------------\n");
998
portals_print_summary();