doc: Add serial to list of ci file reserved words
[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      64
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() {
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 = 0;
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, k, 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, hasstar1=0, hasstar2 = 0;
432       int start, end, stride=1, block=1;
433       int iter=1;
434       for (i=0; i<strlen(str); i++) {
435           if (str[i] == '-' && i!=0) hasdash=1;
436           else if (str[i] == ':') hascolon=1;
437           else if (str[i] == '.') hasdot=1;
438           else if (str[i] == 'x') hasstar1=1;
439           else if (str[i] == 'X') hasstar2=1;
440       }
441       if (hasstar1 || hasstar2) {
442           if (hasstar1) sscanf(str, "%dx", &iter);
443           if (hasstar2) sscanf(str, "%dX", &iter);
444           while (*str!='x' && *str!='X') str++;
445           str++;
446       }
447       if (hasdash) {
448           if (hascolon) {
449             if (hasdot) {
450               if (sscanf(str, "%d-%d:%d.%d", &start, &end, &stride, &block) != 4)
451                  printf("Warning: Check the format of \"%s\".\n", str);
452             }
453             else {
454               if (sscanf(str, "%d-%d:%d", &start, &end, &stride) != 3)
455                  printf("Warning: Check the format of \"%s\".\n", str);
456             }
457           }
458           else {
459             if (sscanf(str, "%d-%d", &start, &end) != 2)
460                  printf("Warning: Check the format of \"%s\".\n", str);
461           }
462       }
463       else {
464           sscanf(str, "%d", &start);
465           end = start;
466       }
467       if (block > stride) {
468         printf("Warning: invalid block size in \"%s\" ignored.\n", str);
469         block=1;
470       }
471       //if (CmiMyPe() == 0) printf("iter: %d start: %d end: %d stride: %d, block: %d.\n", iter, start, end, stride, block);
472       for (k = 0; k<iter; k++) {
473         for (i = start; i<=end; i+=stride) {
474           for (j=0; j<block; j++) {
475             if (i+j>end) break;
476             map[count++] = i+j;
477             if (count == CmiNumPes()) break;
478           }
479           if (count == CmiNumPes()) break;
480         }
481         if (count == CmiNumPes()) break;
482       }
483       str = strtok_r(NULL, ",", &ptr);
484   }
485   i = map[pe % count];
486
487   free(map);
488   free(mapstr);
489   return i;
490 }
491
492 #if CMK_CRAYXT || CMK_CRAYXE
493 extern int getXTNodeID(int mpirank, int nummpiranks);
494 #endif
495
496
497 void CmiInitCPUAffinity(char **argv)
498 {
499   static skt_ip_t myip;
500   int ret, i, exclude;
501   hostnameMsg  *msg;
502   char *pemap = NULL;
503   char *commap = NULL;
504   char *pemapfile = NULL;
505  
506   int show_affinity_flag;
507   int affinity_flag = CmiGetArgFlagDesc(argv,"+setcpuaffinity",
508                                                 "set cpu affinity");
509
510   while (CmiGetArgIntDesc(argv,"+excludecore", &exclude, "avoid core when setting cpuaffinity"))  {
511     if (CmiMyRank() == 0) add_exclude(exclude);
512     affinity_flag = 1;
513   }
514
515   if (CmiGetArgStringDesc(argv, "+pemapfile", &pemapfile, "define pe to core mapping file")) {
516     FILE *fp;
517     char buf[128];
518     pemap = (char*)malloc(1024);
519     fp = fopen(pemapfile, "r");
520     if (fp == NULL) CmiAbort("pemapfile does not exist");
521     while (!feof(fp)) {
522       if (fgets(buf, 128, fp)) {
523         if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0;
524         strcat(pemap, buf);
525       }
526     }
527     if (CmiMyPe()==0) CmiPrintf("Charm++> read from pemap file '%s': %s\n", pemapfile, pemap);
528   }
529
530   CmiGetArgStringDesc(argv, "+pemap", &pemap, "define pe to core mapping");
531   if (pemap!=NULL && excludecount>0)
532     CmiAbort("Charm++> +pemap can not be used with +excludecore.\n");
533
534   CmiGetArgStringDesc(argv, "+commap", &commap, "define comm threads to core mapping");
535
536   if (pemap!=NULL || commap!=NULL) affinity_flag = 1;
537
538   show_affinity_flag = CmiGetArgFlagDesc(argv,"+showcpuaffinity",
539                                                 "print cpu affinity");
540
541   cpuAffinityHandlerIdx =
542        CmiRegisterHandler((CmiHandler)cpuAffinityHandler);
543   cpuAffinityRecvHandlerIdx =
544        CmiRegisterHandler((CmiHandler)cpuAffinityRecvHandler);
545
546   if (CmiMyRank() ==0) {
547      affLock = CmiCreateLock();
548   }
549
550 #if CMK_BLUEGENEP | CMK_BLUEGENEQ
551   if(affinity_flag){
552       affinity_flag = 0;
553       if(CmiMyPe()==0) CmiPrintf("Charm++> cpu affinity setting is not needed on BG/P, thus ignored.\n");
554   }
555   if(show_affinity_flag){
556       show_affinity_flag = 0;
557       if(CmiMyPe()==0) CmiPrintf("Charm++> printing cpu affinity is not supported on BG/P.\n");
558   }
559 #endif
560
561   if (!affinity_flag) {
562     if (show_affinity_flag) CmiPrintCPUAffinity();
563     return;
564   }
565
566   if (CmiMyPe() == 0) {
567      CmiPrintf("Charm++> cpu affinity enabled. \n");
568      if (excludecount > 0) {
569        CmiPrintf("Charm++> cpuaffinity excludes core: %d", excludecore[0]);
570        for (i=1; i<excludecount; i++) CmiPrintf(" %d", excludecore[i]);
571        CmiPrintf(".\n");
572      }
573      if (pemap!=NULL)
574        CmiPrintf("Charm++> cpuaffinity PE-core map : %s\n", pemap);
575   }
576
577   if (CmiMyPe() >= CmiNumPes()) {         /* this is comm thread */
578       /* comm thread either can float around, or pin down to the last rank.
579          however it seems to be reportedly slower if it is floating */
580     CmiNodeAllBarrier();
581     if (commap != NULL) {
582       int mycore = search_pemap(commap, CmiMyPe()-CmiNumPes());
583       if(CmiMyPe()-CmiNumPes()==0) printf("Charm++> set comm %d on node %d to core #%d\n", CmiMyPe()-CmiNumPes(), CmiMyNode(), mycore); 
584       if (-1 == CmiSetCPUAffinity(mycore))
585         CmiAbort("set_cpu_affinity abort!");
586       CmiNodeAllBarrier();
587       if (show_affinity_flag) CmiPrintCPUAffinity();
588       return;    /* comm thread return */
589     }
590     else {
591     /* if (CmiSetCPUAffinity(CmiNumCores()-1) == -1) CmiAbort("set_cpu_affinity abort!"); */
592 #if !CMK_CRAYXT && !CMK_CRAYXE && !CMK_BLUEGENEQ
593       if (pemap == NULL) {
594 #if CMK_MACHINE_PROGRESS_DEFINED
595         while (affinity_doneflag < CmiMyNodeSize())  CmiNetworkProgress();
596 #else
597 #if CMK_SMP
598        #error "Machine progress call needs to be implemented for cpu affinity!"
599 #endif
600 #endif
601       }
602 #endif
603 #if CMK_CRAYXT || CMK_CRAYXE
604       /* if both pemap and commmap are NULL, will compute one */
605       if (pemap != NULL)      
606 #endif
607       {
608       CmiNodeAllBarrier();
609       if (show_affinity_flag) CmiPrintCPUAffinity();
610       return;    /* comm thread return */
611       }
612     }
613   }
614
615   if (pemap != NULL && CmiMyPe()<CmiNumPes()) {    /* work thread */
616     int mycore = search_pemap(pemap, CmiMyPe());
617     if(show_affinity_flag) CmiPrintf("Charm++> set PE %d on node %d to core #%d\n", CmiMyPe(), CmiMyNode(), mycore); 
618     if (mycore >= CmiNumCores()) {
619       CmiPrintf("Error> Invalid core number %d, only have %d cores (0-%d) on the node. \n", mycore, CmiNumCores(), CmiNumCores()-1);
620       CmiAbort("Invalid core number");
621     }
622     if (CmiSetCPUAffinity(mycore) == -1) CmiAbort("set_cpu_affinity abort!");
623     CmiNodeAllBarrier();
624     CmiNodeAllBarrier();
625     /* if (show_affinity_flag) CmiPrintCPUAffinity(); */
626     return;
627   }
628
629 #if CMK_CRAYXT || CMK_CRAYXE
630   {
631     int numPes = CmiNumPes();
632     int numNodes = CmiNumNodes();
633     int numCores = CmiNumCores();
634
635     int myid = getXTNodeID(CmiMyNode(), CmiNumNodes());
636     int myrank;
637     int pe, mype = CmiMyPe();
638     int node = CmiMyNode();
639     int nnodes = 0;
640 #if CMK_SMP
641     if (CmiMyPe() >= CmiNumPes()) {         /* this is comm thread */
642       int node = CmiMyPe() - CmiNumPes();
643       mype = CmiNodeFirst(node) + CmiMyNodeSize() - 1; /* last pe on SMP node */
644     }
645 #endif
646     pe = mype - 1;
647     while (pe >= 0) {
648       int n = CmiNodeOf(pe);
649       if (n != node) { nnodes++; node = n; }
650       if (getXTNodeID(n, numNodes) != myid) break;
651       pe --;
652     }
653     CmiAssert(numCores > 0);
654     myrank = (mype - pe - 1 + nnodes)%numCores;
655 #if CMK_SMP
656     if (CmiMyPe() >= CmiNumPes()) 
657         myrank = (myrank + 1)%numCores;
658 #endif
659
660     if (-1 != CmiSetCPUAffinity(myrank)) {
661       DEBUGP(("Processor %d is bound to core #%d on node #%d\n", CmiMyPe(), myrank, mynode));
662     }
663     else{
664       CmiPrintf("Processor %d set affinity failed!\n", CmiMyPe());
665       CmiAbort("set cpu affinity abort!\n");
666     }
667   }
668   if (CmiMyPe() < CmiNumPes()) 
669   CmiNodeAllBarrier();
670   CmiNodeAllBarrier();
671 #else
672     /* get my ip address */
673   if (CmiMyRank() == 0)
674   {
675 #if CMK_HAS_GETHOSTNAME
676     myip = skt_my_ip();        /* not thread safe, so only calls on rank 0 */
677 #else
678     CmiAbort("Can not get unique name for the compute nodes. \n");
679 #endif
680   }
681   CmiNodeAllBarrier();
682
683     /* prepare a msg to send */
684   msg = (hostnameMsg *)CmiAlloc(sizeof(hostnameMsg));
685   CmiSetHandler((char *)msg, cpuAffinityHandlerIdx);
686   msg->pe = CmiMyPe();
687   msg->ip = myip;
688   msg->ncores = CmiNumCores();
689   DEBUGP(("PE %d's node has %d number of cores. \n", CmiMyPe(), msg->ncores));
690   msg->rank = 0;
691   CmiSyncSendAndFree(0, sizeof(hostnameMsg), (void *)msg);
692
693   if (CmiMyPe() == 0) {
694     int i;
695     hostTable = CmmNew();
696     rankmsg = (rankMsg *)CmiAlloc(sizeof(rankMsg)+CmiNumPes()*sizeof(int)*2);
697     CmiSetHandler((char *)rankmsg, cpuAffinityRecvHandlerIdx);
698     rankmsg->ranks = (int *)((char*)rankmsg + sizeof(rankMsg));
699     rankmsg->nodes = (int *)((char*)rankmsg + sizeof(rankMsg) + CmiNumPes()*sizeof(int));
700     for (i=0; i<CmiNumPes(); i++) {
701       rankmsg->ranks[i] = 0;
702       rankmsg->nodes[i] = -1;
703     }
704
705     for (i=0; i<CmiNumPes(); i++) CmiDeliverSpecificMsg(cpuAffinityHandlerIdx);
706   }
707
708     /* receive broadcast from PE 0 */
709   CmiDeliverSpecificMsg(cpuAffinityRecvHandlerIdx);
710   CmiLock(affLock);
711   affinity_doneflag++;
712   CmiUnlock(affLock);
713   CmiNodeAllBarrier();
714 #endif
715
716   if (show_affinity_flag) CmiPrintCPUAffinity();
717 }
718
719 /* called in ConverseCommonInit to initialize basic variables */
720 void CmiInitCPUAffinityUtil(){
721     CpvInitialize(int, myCPUAffToCore);
722     CpvAccess(myCPUAffToCore) = -1;
723 #if CMK_OS_IS_LINUX
724     CpvInitialize(void *, myProcStatFP);
725     char fname[64];
726     CmiLock(_smp_mutex);
727 #if CMK_SMP
728     sprintf(fname, "/proc/%d/task/%d/stat", getpid(), syscall(SYS_gettid));
729 #else
730     sprintf(fname, "/proc/%d/stat", getpid());
731 #endif
732     CpvAccess(myProcStatFP) = (void *)fopen(fname, "r");
733     CmiUnlock(_smp_mutex);
734 /*
735     if(CmiMyPe()==0 && CpvAccess(myProcStatFP) == NULL){
736         CmiPrintf("WARNING: ERROR IN OPENING FILE %s on PROC %d, CmiOnCore() SHOULDN'T BE CALLED\n", fname, CmiMyPe()); 
737     }
738 */
739 #endif
740 }
741
742 #else           /* not supporting affinity */
743
744
745 int CmiPrintCPUAffinity()
746 {
747   CmiPrintf("Warning: CmiPrintCPUAffinity not supported.\n");
748 }
749
750 void CmiInitCPUAffinity(char **argv)
751 {
752   char *pemap = NULL;
753   char *pemapfile = NULL;
754   char *commap = NULL;
755   int excludecore = -1;
756   int affinity_flag = CmiGetArgFlagDesc(argv,"+setcpuaffinity",
757                                                 "set cpu affinity");
758   while (CmiGetArgIntDesc(argv,"+excludecore",&excludecore, "avoid core when setting cpuaffinity"));
759   CmiGetArgStringDesc(argv, "+pemap", &pemap, "define pe to core mapping");
760   CmiGetArgStringDesc(argv, "+pemapfile", &pemapfile, "define pe to core mapping file");
761   CmiGetArgStringDesc(argv, "+commap", &commap, "define comm threads to core mapping");
762   if (affinity_flag && CmiMyPe()==0)
763     CmiPrintf("sched_setaffinity() is not supported, +setcpuaffinity disabled.\n");
764 }
765
766 /* called in ConverseCommonInit to initialize basic variables */
767 void CmiInitCPUAffinityUtil(){
768     CpvInitialize(int, myCPUAffToCore);
769     CpvAccess(myCPUAffToCore) = -1;
770 #if CMK_OS_IS_LINUX     
771     CpvInitialize(void *, myProcStatFP);
772     CpvAccess(myProcStatFP) = NULL;
773  #endif
774 }
775
776 int CmiOnCore(){
777   printf("WARNING: CmiOnCore IS NOT SUPPORTED ON THIS PLATFORM\n");
778   return -1;
779 }
780 #endif