Fixed a bug in setting the starting time of tracing MPI_Isend
[charm.git] / src / conv-core / cpuaffinity.c
1
2 /*
3  This scheme relies on using IP address to identify nodes and assigning 
4 cpu affinity.  
5
6  when CMK_NO_SOCKETS, which is typically on cray xt3 and bluegene/L.
7  There is no hostname for the compute nodes.
8  *
9  * last updated 3/20/2010   Gengbin Zheng
10  * new options +pemap +commmap takes complex pattern of a list of cores
11 */
12
13 #define _GNU_SOURCE
14
15 #include "converse.h"
16 #include "sockRoutines.h"
17
18 #define DEBUGP(x)   /* CmiPrintf x;  */
19 CpvDeclare(int, myCPUAffToCore);
20 #if CMK_OS_IS_LINUX
21 /* 
22  * /proc/<PID>/[task/<TID>]/stat file descriptor 
23  * Used to retrieve the info about which physical
24  * coer this process or thread is on.
25  **/
26 CpvDeclare(void *, myProcStatFP);
27 #endif
28
29 #if CMK_HAS_SETAFFINITY || defined (_WIN32) || CMK_HAS_BINDPROCESSOR
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <unistd.h>
34
35 #ifdef _WIN32
36 #include <windows.h>
37 #include <winbase.h>
38 #else
39 #define _GNU_SOURCE
40 #include <sched.h>
41 //long sched_setaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr);
42 //long sched_getaffinity(pid_t pid, unsigned int len, unsigned long *user_mask_ptr);
43 #endif
44
45 #if CMK_OS_IS_LINUX
46 #include <sys/syscall.h>
47 #endif
48
49 #if defined(__APPLE__) 
50 #include <Carbon/Carbon.h> /* Carbon APIs for Multiprocessing */
51 #endif
52
53 #if defined(ARCH_HPUX11) ||  defined(ARCH_HPUX10)
54 #include <sys/mpctl.h>
55 #endif
56
57
58 #define MAX_EXCLUDE      32
59 static int excludecore[MAX_EXCLUDE] = {-1};
60 static int excludecount = 0;
61
62 static int affinity_doneflag = 0;
63
64 static int in_exclude(int core)
65 {
66   int i;
67   for (i=0; i<excludecount; i++) if (core == excludecore[i]) return 1;
68   return 0;
69 }
70
71 static void add_exclude(int core)
72 {
73   if (in_exclude(core)) return;
74   CmiAssert(excludecount < MAX_EXCLUDE);
75   excludecore[excludecount++] = core;
76 }
77
78 #if CMK_HAS_BINDPROCESSOR
79 #include <sys/processor.h>
80 #endif
81
82 #define SET_MASK(cpuid)    \
83   /* set the affinity mask if possible */      \
84   if ((cpuid / 8) > len) {      \
85     printf("Mask size too small to handle requested CPU ID\n");   \
86     return -1;      \
87   } else {    \
88     mask = 1 << cpuid;   /* set the affinity mask exclusively to one CPU */ \
89   }
90
91
92 /* This implementation assumes the default x86 CPU mask size used by Linux */
93 /* For a large SMP machine, this code should be changed to use a variable sized   */
94 /* CPU affinity mask buffer instead, as the present code will fail beyond 32 CPUs */
95 int set_cpu_affinity(unsigned int cpuid) {
96   unsigned long mask = 0xffffffff;
97   unsigned int len = sizeof(mask);
98   int retValue = 0;
99   int pid;
100
101  #ifdef _WIN32
102    HANDLE hProcess;
103  #endif
104  
105 #ifdef _WIN32
106   SET_MASK(cpuid)
107   hProcess = GetCurrentProcess();
108   if (SetProcessAffinityMask(hProcess, mask) == 0) {
109     return -1;
110   }
111 #elif CMK_HAS_BINDPROCESSOR
112   pid = getpid();
113   if (bindprocessor(BINDPROCESS, pid, cpuid) == -1) return -1;
114 #else
115   cpu_set_t cpuset;
116   CPU_ZERO(&cpuset);
117   CPU_SET(cpuid, &cpuset);
118   /*SET_MASK(cpuid)*/
119
120   /* PID 0 refers to the current process */
121   /*if (sched_setaffinity(0, len, &mask) < 0) {*/
122   if (sched_setaffinity(0, sizeof(cpuset), &cpuset) < 0) {
123     perror("sched_setaffinity");
124     return -1;
125   }
126 #endif
127
128   return 0;
129 }
130
131 #if CMK_SMP
132 int set_thread_affinity(int cpuid) {
133   unsigned long mask = 0xffffffff;
134   unsigned int len = sizeof(mask);
135
136 #ifdef _WIN32
137   HANDLE hThread;
138 #endif  
139   
140 #ifdef _WIN32
141   SET_MASK(cpuid)
142   hThread = GetCurrentThread();
143   if (SetThreadAffinityMask(hThread, mask) == 0) {
144     return -1;
145   }
146 #elif  CMK_HAS_PTHREAD_SETAFFINITY
147   int s, j;
148   cpu_set_t cpuset;
149   pthread_t thread;
150
151   thread = pthread_self();
152
153   CPU_ZERO(&cpuset);
154   CPU_SET(cpuid, &cpuset);
155
156   s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
157   if (s != 0) {
158     perror("pthread_setaffinity");
159     return -1;
160   }
161 #elif CMK_HAS_BINDPROCESSOR
162   if (bindprocessor(BINDTHREAD, thread_self(), cpuid) != 0)
163     return -1;
164 #else
165   return set_cpu_affinity(cpuid);
166 #endif
167
168   return 0;
169 }
170 #endif
171
172
173 int CmiSetCPUAffinity(int mycore)
174 {
175   int core = mycore;
176   if (core < 0) {
177     core = CmiNumCores() + core;
178   }
179   if (core < 0) {
180     CmiError("Error: Invalid cpu affinity core number: %d\n", mycore);
181     CmiAbort("CmiSetCPUAffinity failed");
182   }
183
184   CpvAccess(myCPUAffToCore) = core;
185
186   /* set cpu affinity */
187 #if CMK_SMP
188   return set_thread_affinity(core);
189 #else
190   return set_cpu_affinity(core);
191   /* print_cpu_affinity(); */
192 #endif
193 }
194
195 /* This implementation assumes the default x86 CPU mask size used by Linux */
196 /* For a large SMP machine, this code should be changed to use a variable sized   */
197 /* CPU affinity mask buffer instead, as the present code will fail beyond 32 CPUs */
198 int print_cpu_affinity() {
199 #ifdef _WIN32
200   unsigned long pMask, sMask;
201   HANDLE hProcess = GetCurrentProcess();
202   if(GetProcessAffinityMask(hProcess, &pMask, &sMask)){
203         perror("On Windows: GetProcessAffinityMask");
204     return -1;
205   }
206   
207  CmiPrintf("[%d] CPU affinity mask is: 0x%08lx\n", CmiMyPe(), pMask);
208   
209 #elif CMK_HAS_BINDPROCESSOR
210   printf("[%d] CPU affinity mask is unknown for AIX. \n", CmiMyPe());
211 #else
212   /*unsigned long mask;
213   unsigned int len = sizeof(mask);*/
214   cpu_set_t cpuset;
215   char str[256], pe[16];
216   int i;
217   CPU_ZERO(&cpuset);
218  
219   /* PID 0 refers to the current process */
220   /*if (sched_getaffinity(0, len, &mask) < 0) {*/
221   if (sched_getaffinity(0, sizeof(cpuset), &cpuset) < 0) {
222     perror("sched_getaffinity");
223     return -1;
224   }
225
226   sprintf(str, "[%d] CPU affinity mask is: ", CmiMyPe());
227   for (i = 0; i < CPU_SETSIZE; i++)
228         if (CPU_ISSET(i, &cpuset)) {
229             sprintf(pe, " %d ", i);
230             strcat(str, pe);
231         }
232   CmiPrintf("%s\n", str);  
233 #endif
234   return 0;
235 }
236
237 #if CMK_SMP
238 int print_thread_affinity() {
239   unsigned long mask;
240   size_t len = sizeof(mask);
241
242 #if  CMK_HAS_PTHREAD_SETAFFINITY
243   int s, j;
244   cpu_set_t cpuset;
245   pthread_t thread;
246   char str[256], pe[16];
247
248   thread = pthread_self();
249   s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
250   if (s != 0) {
251     perror("pthread_getaffinity");
252     return -1;
253   }
254
255   sprintf(str, "[%d] %s affinity is: ", CmiMyPe(), CmiMyPe()>=CmiNumPes()?"communication pthread":"pthread");
256   for (j = 0; j < CPU_SETSIZE; j++)
257         if (CPU_ISSET(j, &cpuset)) {
258             sprintf(pe, " %d ", j);
259             strcat(str, pe);
260         }
261   CmiPrintf("%s\n", str);
262 #endif
263   return 0;
264 }
265 #endif
266
267 int CmiPrintCPUAffinity()
268 {
269 #if CMK_SMP
270   return print_thread_affinity();
271 #else
272   return print_cpu_affinity();
273 #endif
274 }
275
276 int CmiOnCore(void) {
277 #if CMK_OS_IS_LINUX
278   /*
279    * The info (task_cpu) is read from the Linux /proc virtual file system.
280    * The /proc/<PID>/[task/<TID>]/stat is explained in the Linux
281    * kernel documentation. The online one could be found in:
282    * http://www.mjmwired.net/kernel/Documentation/filesystems/proc.txt
283    * Based on the documentation, task_cpu is found at the 39th field in
284    * the stat file.
285    **/
286 #define TASK_CPU_POS (39)
287   int n;
288   char str[128];
289   FILE *fp = (FILE *)CpvAccess(myProcStatFP);
290   if (fp == NULL){
291     printf("WARNING: CmiOnCore IS NOT SUPPORTED ON THIS PLATFORM\n");
292     return -1;
293   }
294   fseek(fp, 0, SEEK_SET);
295   for (n=0; n<TASK_CPU_POS; n++)  {
296     fscanf(fp, "%s", str);
297   }  
298   return atoi(str);
299 #else
300   printf("WARNING: CmiOnCore IS NOT SUPPORTED ON THIS PLATFORM\n");
301   return -1;
302 #endif
303 }
304
305
306 static int cpuAffinityHandlerIdx;
307 static int cpuAffinityRecvHandlerIdx;
308
309 typedef struct _hostnameMsg {
310   char core[CmiMsgHeaderSizeBytes];
311   int pe;
312   skt_ip_t ip;
313   int ncores;
314   int rank;
315   int seq;
316 } hostnameMsg;
317
318 typedef struct _rankMsg {
319   char core[CmiMsgHeaderSizeBytes];
320   int *ranks;                  /* PE => core rank mapping */
321   int *nodes;                  /* PE => node number mapping */
322 } rankMsg;
323
324 static rankMsg *rankmsg = NULL;
325 static CmmTable hostTable;
326 static CmiNodeLock affLock = NULL;
327
328 /* called on PE 0 */
329 static void cpuAffinityHandler(void *m)
330 {
331   static int count = 0;
332   static int nodecount = 0;
333   hostnameMsg *rec;
334   hostnameMsg *msg = (hostnameMsg *)m;
335   hostnameMsg *tmpm;
336   int tag, tag1, pe, myrank;
337   int npes = CmiNumPes();
338
339 /*   for debug
340   char str[128];
341   skt_print_ip(str, msg->ip);
342   printf("hostname: %d %s\n", msg->pe, str);
343 */
344   CmiAssert(CmiMyPe()==0 && rankmsg != NULL);
345   tag = *(int*)&msg->ip;
346   pe = msg->pe;
347   if ((rec = (hostnameMsg *)CmmProbe(hostTable, 1, &tag, &tag1)) != NULL) {
348     CmiFree(msg);
349   }
350   else {
351     rec = msg;
352     rec->seq = nodecount;
353     nodecount++;                          /* a new node record */
354     CmmPut(hostTable, 1, &tag, msg);
355   }
356   myrank = rec->rank%rec->ncores;
357   while (in_exclude(myrank)) {             /* skip excluded core */
358     myrank = (myrank+1)%rec->ncores;
359     rec->rank ++;
360   }
361   rankmsg->ranks[pe] = myrank;             /* core rank */
362   rankmsg->nodes[pe] = rec->seq;           /* on which node */
363   rec->rank ++;
364   count ++;
365   if (count == CmiNumPes()) {
366     /* CmiPrintf("Cpuaffinity> %d unique compute nodes detected! \n", CmmEntries(hostTable)); */
367     tag = CmmWildCard;
368     while (tmpm = CmmGet(hostTable, 1, &tag, &tag1)) CmiFree(tmpm);
369     CmmFree(hostTable);
370 #if 1
371     /* bubble sort ranks on each node according to the PE number */
372     {
373     int i,j;
374     for (i=0; i<npes-1; i++)
375       for(j=i+1; j<npes; j++) {
376         if (rankmsg->nodes[i] == rankmsg->nodes[j] && 
377               rankmsg->ranks[i] > rankmsg->ranks[j]) 
378         {
379           int tmp = rankmsg->ranks[i];
380           rankmsg->ranks[i] = rankmsg->ranks[j];
381           rankmsg->ranks[j] = tmp;
382         }
383       }
384     }
385 #endif
386     CmiSyncBroadcastAllAndFree(sizeof(rankMsg)+CmiNumPes()*sizeof(int)*2, (void *)rankmsg);
387   }
388 }
389
390 /* called on each processor */
391 static void cpuAffinityRecvHandler(void *msg)
392 {
393   int myrank, mynode;
394   rankMsg *m = (rankMsg *)msg;
395   m->ranks = (int *)((char*)m + sizeof(rankMsg));
396   m->nodes = (int *)((char*)m + sizeof(rankMsg) + CmiNumPes()*sizeof(int));
397   myrank = m->ranks[CmiMyPe()];
398   mynode = m->nodes[CmiMyPe()];
399
400   /*CmiPrintf("[%d %d] set to core #: %d\n", CmiMyNode(), CmiMyPe(), myrank);*/
401
402   if (-1 != CmiSetCPUAffinity(myrank)) {
403     DEBUGP(("Processor %d is bound to core #%d on node #%d\n", CmiMyPe(), myrank, mynode));
404   }
405   else{
406     CmiPrintf("Processor %d set affinity failed!\n", CmiMyPe());
407     CmiAbort("set cpu affinity abort!\n");
408   }
409   CmiFree(m);
410 }
411
412 #if defined(_WIN32) && ! defined(__CYGWIN__)
413   /* strtok is thread safe in VC++ */
414 #define strtok_r(x,y,z) strtok(x,y)
415 #endif
416
417 static int search_pemap(char *pecoremap, int pe)
418 {
419   int *map = (int *)malloc(CmiNumPes()*sizeof(int));
420   char *ptr = NULL;
421   int i, j, count;
422   char *str;
423
424   char *mapstr = (char*)malloc(strlen(pecoremap)+1);
425   strcpy(mapstr, pecoremap);
426
427   str = strtok_r(mapstr, ",", &ptr);
428   count = 0;
429   while (str && count < CmiNumPes())
430   {
431       int hasdash=0, hascolon=0, hasdot=0;
432       int start, end, stride=1, block=1;
433       for (i=0; i<strlen(str); i++) {
434           if (str[i] == '-' && i!=0) hasdash=1;
435           if (str[i] == ':') hascolon=1;
436           if (str[i] == '.') hasdot=1;
437       }
438       if (hasdash) {
439           if (hascolon) {
440             if (hasdot) {
441               if (sscanf(str, "%d-%d:%d.%d", &start, &end, &stride, &block) != 4)
442                  printf("Warning: Check the format of \"%s\".\n", str);
443             }
444             else {
445               if (sscanf(str, "%d-%d:%d", &start, &end, &stride) != 3)
446                  printf("Warning: Check the format of \"%s\".\n", str);
447             }
448           }
449           else {
450             if (sscanf(str, "%d-%d", &start, &end) != 2)
451                  printf("Warning: Check the format of \"%s\".\n", str);
452           }
453       }
454       else {
455           sscanf(str, "%d", &start);
456           end = start;
457       }
458       if (block > stride) {
459         printf("Warning: invalid block size in \"%s\" ignored.\n", str);
460         block=1;
461       }
462       for (i = start; i<=end; i+=stride) {
463         for (j=0; j<block; j++) {
464           if (i+j>end) break;
465           map[count++] = i+j;
466           if (count == CmiNumPes()) break;
467         }
468         if (count == CmiNumPes()) break;
469       }
470       str = strtok_r(NULL, ",", &ptr);
471   }
472   i = map[pe % count];
473
474   free(map);
475   free(mapstr);
476   return i;
477 }
478
479 #if CMK_CRAYXT
480 extern int getXTNodeID(int mpirank, int nummpiranks);
481 #endif
482
483
484 void CmiInitCPUAffinity(char **argv)
485 {
486   static skt_ip_t myip;
487   int ret, i, exclude;
488   hostnameMsg  *msg;
489   char *pemap = NULL;
490   char *commap = NULL;
491  
492   int show_affinity_flag;
493   int affinity_flag = CmiGetArgFlagDesc(argv,"+setcpuaffinity",
494                                                 "set cpu affinity");
495
496   while (CmiGetArgIntDesc(argv,"+excludecore", &exclude, "avoid core when setting cpuaffinity")) 
497     if (CmiMyRank() == 0) add_exclude(exclude);
498
499   CmiGetArgStringDesc(argv, "+pemap", &pemap, "define pe to core mapping");
500   if (pemap!=NULL && excludecount>0)
501     CmiAbort("Charm++> +pemap can not be used with +excludecore.\n");
502   CmiGetArgStringDesc(argv, "+commap", &commap, "define comm threads to core mapping");
503   show_affinity_flag = CmiGetArgFlagDesc(argv,"+showcpuaffinity",
504                                                 "print cpu affinity");
505
506   cpuAffinityHandlerIdx =
507        CmiRegisterHandler((CmiHandler)cpuAffinityHandler);
508   cpuAffinityRecvHandlerIdx =
509        CmiRegisterHandler((CmiHandler)cpuAffinityRecvHandler);
510
511   if (CmiMyRank() ==0) {
512      affLock = CmiCreateLock();
513   }
514
515   if (!affinity_flag) {
516     if (show_affinity_flag) CmiPrintCPUAffinity();
517     return;
518   }
519   else if (CmiMyPe() == 0) {
520      CmiPrintf("Charm++> cpu affinity enabled. \n");
521      if (excludecount > 0) {
522        CmiPrintf("Charm++> cpuaffinity excludes core: %d", excludecore[0]);
523        for (i=1; i<excludecount; i++) CmiPrintf(" %d", excludecore[i]);
524        CmiPrintf(".\n");
525      }
526      if (pemap!=NULL)
527        CmiPrintf("Charm++> cpuaffinity PE-core map : %s\n", pemap);
528   }
529
530   if (CmiMyPe() >= CmiNumPes()) {         /* this is comm thread */
531       /* comm thread either can float around, or pin down to the last rank.
532          however it seems to be reportedly slower if it is floating */
533     CmiNodeAllBarrier();
534     if (commap != NULL) {
535       int mycore = search_pemap(commap, CmiMyPe()-CmiNumPes());
536       printf("Charm++> set comm %d on node %d to core #%d\n", CmiMyPe()-CmiNumPes(), CmiMyNode(), mycore); 
537       if (-1 == CmiSetCPUAffinity(mycore))
538         CmiAbort("set_cpu_affinity abort!");
539     }
540     else {
541     /* if (CmiSetCPUAffinity(CmiNumCores()-1) == -1) CmiAbort("set_cpu_affinity abort!"); */
542     }
543     if (pemap == NULL) {
544 #if CMK_MACHINE_PROGRESS_DEFINED
545     while (affinity_doneflag < CmiMyNodeSize())  CmiNetworkProgress();
546 #else
547 #if CMK_SMP
548     #error "Machine progress call needs to be implemented for cpu affinity!"
549 #endif
550 #endif
551     }
552     CmiNodeAllBarrier();
553     if (show_affinity_flag) CmiPrintCPUAffinity();
554     return;    /* comm thread return */
555   }
556
557   if (pemap != NULL) {
558     int mycore = search_pemap(pemap, CmiMyPe());
559     CmiPrintf("Charm++> set PE %d on node %d to core #%d\n", CmiMyPe(), CmiMyNode(), mycore); 
560     if (mycore >= CmiNumCores()) {
561       CmiPrintf("Error> Invalid core number %d, only have %d cores (0-%d) on the node. \n", mycore, CmiNumCores(), CmiNumCores()-1);
562       CmiAbort("Invalid core number");
563     }
564     if (CmiSetCPUAffinity(mycore) == -1) CmiAbort("set_cpu_affinity abort!");
565     CmiNodeAllBarrier();
566     CmiNodeAllBarrier();
567     if (show_affinity_flag) CmiPrintCPUAffinity();
568     return;
569   }
570
571     /* get my ip address */
572   if (CmiMyRank() == 0)
573   {
574 #if CMK_CRAYXT
575     ret = getXTNodeID(CmiMyNode(), CmiNumNodes());
576     memcpy(&myip, &ret, sizeof(int));
577 #elif CMK_HAS_GETHOSTNAME
578     myip = skt_my_ip();        /* not thread safe, so only calls on rank 0 */
579 #else
580     CmiAbort("Can not get unique name for the compute nodes. \n");
581 #endif
582   }
583   CmiNodeAllBarrier();
584
585     /* prepare a msg to send */
586   msg = (hostnameMsg *)CmiAlloc(sizeof(hostnameMsg));
587   CmiSetHandler((char *)msg, cpuAffinityHandlerIdx);
588   msg->pe = CmiMyPe();
589   msg->ip = myip;
590   msg->ncores = CmiNumCores();
591   DEBUGP(("PE %d's node has %d number of cores. \n", CmiMyPe(), msg->ncores));
592   msg->rank = 0;
593   CmiSyncSendAndFree(0, sizeof(hostnameMsg), (void *)msg);
594
595   if (CmiMyPe() == 0) {
596     int i;
597     hostTable = CmmNew();
598     rankmsg = (rankMsg *)CmiAlloc(sizeof(rankMsg)+CmiNumPes()*sizeof(int)*2);
599     CmiSetHandler((char *)rankmsg, cpuAffinityRecvHandlerIdx);
600     rankmsg->ranks = (int *)((char*)rankmsg + sizeof(rankMsg));
601     rankmsg->nodes = (int *)((char*)rankmsg + sizeof(rankMsg) + CmiNumPes()*sizeof(int));
602     for (i=0; i<CmiNumPes(); i++) {
603       rankmsg->ranks[i] = 0;
604       rankmsg->nodes[i] = -1;
605     }
606
607     for (i=0; i<CmiNumPes(); i++) CmiDeliverSpecificMsg(cpuAffinityHandlerIdx);
608   }
609
610     /* receive broadcast from PE 0 */
611   CmiDeliverSpecificMsg(cpuAffinityRecvHandlerIdx);
612   CmiLock(affLock);
613   affinity_doneflag++;
614   CmiUnlock(affLock);
615   CmiNodeAllBarrier();
616
617   if (show_affinity_flag) CmiPrintCPUAffinity();
618 }
619
620 /* called in ConverseCommonInit to initialize basic variables */
621 void CmiInitCPUAffinityUtil(){
622     CpvInitialize(int, myCPUAffToCore);
623     CpvAccess(myCPUAffToCore) = -1;
624 #if CMK_OS_IS_LINUX
625     char fname[128];
626 #if CMK_SMP
627     sprintf(fname, "/proc/%d/task/%d/stat", getpid(), syscall(SYS_gettid));
628 #else
629     sprintf(fname, "/proc/%d/stat", getpid());
630 #endif  
631     CpvInitialize(void *, myProcStatFP);
632     CpvAccess(myProcStatFP) = (void *)fopen(fname, "r");
633 /*
634     if(CmiMyPe()==0 && CpvAccess(myProcStatFP) == NULL){
635         CmiPrintf("WARNING: ERROR IN OPENING FILE %s on PROC %d, CmiOnCore() SHOULDN'T BE CALLED\n", fname, CmiMyPe()); 
636     }
637 */
638 #endif
639 }
640
641 #else           /* not supporting affinity */
642
643
644 int CmiPrintCPUAffinity()
645 {
646   CmiPrintf("Warning: CmiPrintCPUAffinity not supported.\n");
647 }
648
649 void CmiInitCPUAffinity(char **argv)
650 {
651   char *pemap = NULL;
652   char *commap = NULL;
653   int excludecore = -1;
654   int affinity_flag = CmiGetArgFlagDesc(argv,"+setcpuaffinity",
655                                                 "set cpu affinity");
656   while (CmiGetArgIntDesc(argv,"+excludecore",&excludecore, "avoid core when setting cpuaffinity"));
657   CmiGetArgStringDesc(argv, "+pemap", &pemap, "define pe to core mapping");
658   CmiGetArgStringDesc(argv, "+commap", &commap, "define comm threads to core mapping");
659   if (affinity_flag && CmiMyPe()==0)
660     CmiPrintf("sched_setaffinity() is not supported, +setcpuaffinity disabled.\n");
661 }
662
663 /* called in ConverseCommonInit to initialize basic variables */
664 void CmiInitCPUAffinityUtil(){
665     CpvInitialize(int, myCPUAffToCore);
666     CpvAccess(myCPUAffToCore) = -1;
667 #if CMK_OS_IS_LINUX     
668     CpvInitialize(void *, myProcStatFP);
669     CpvAccess(myProcStatFP) = NULL;
670  #endif
671 }
672
673 int CmiOnCore(){
674   printf("WARNING: CmiOnCore IS NOT SUPPORTED ON THIS PLATFORM\n");
675   return -1;
676 }
677 #endif