Made charm++ to compile and run with Solaris 2.6.
[charm.git] / src / ck-core / ck.c
1 /***************************************************************************
2  * RCS INFORMATION:
3  *
4  *      $RCSfile$
5  *      $Author$        $Locker$                $State$
6  *      $Revision$      $Date$
7  *
8  ***************************************************************************
9  * DESCRIPTION:
10  *
11  ***************************************************************************
12  * REVISION HISTORY:
13  *
14  * $Log$
15  * Revision 2.24  1998-01-13 17:03:20  milind
16  * Made charm++ to compile and run with Solaris 2.6.
17  * In particular, changed INTBITS to CINTBITS, and handled EALREADY.
18  *
19  * Revision 2.23  1997/10/03 19:51:31  milind
20  * Made charmc to work again, after inserting trace calls in converse part,
21  * i.e. threads and user events.
22  *
23  * Revision 2.22  1997/07/18 21:21:03  milind
24  * all files of the form perf-*.c have been changed to trace-*.c, with
25  * name expansions. For example, perf-proj.c has been changed to
26  * trace-projections.c.
27  * performance.h has been renamed as trace.h, and perfio.c has been
28  * renamed as traceio.c.
29  * Corresponding changes have been made in the Makefile too.
30  * Earlier, there used to be three libck-core-*.a where * was projections,
31  * summary or none. Now, there will be a single libck-core.a and
32  * three libck-trace-*.a where *=projections, summary and none.
33  * The execmode parameter to charmc script has been renamed as
34  * tracemode.
35  * Also, the perfModuleInit function has been renamed as traceModuleInit,
36  * RecdPerfMsg => RecdTraceMsg
37  * CollectPerfFromNodes => CollectTraceFromNodes
38  *
39  * Revision 2.21  1997/04/21 20:58:48  jyelon
40  * Simplified the shutdown protocol a little.
41  *
42  * Revision 2.20  1997/03/24 23:14:01  milind
43  * Made Charm-runtime 64-bit safe by removing conversions of pointers to
44  * integers. Also, removed charm runtime's dependence of unused argv[]
45  * elements being 0. Also, added sim-irix-64 version. It works.
46  *
47  * Revision 2.19  1995/11/13 04:04:33  gursoy
48  * made changes related to initial msg synchronization
49  *
50  * Revision 2.18  1995/11/07  17:53:45  sanjeev
51  * fixed bugs in statistics collection
52  *
53  * Revision 2.17  1995/11/05  18:26:26  sanjeev
54  * removed trace_creation in CkLdbSend
55  *
56  * Revision 2.16  1995/10/27  23:56:49  jyelon
57  * removed more ansi
58  *
59  * Revision 2.15  1995/10/27  21:31:25  jyelon
60  * changed NumPe --> NumPes
61  *
62  * Revision 2.14  1995/10/27  09:09:31  jyelon
63  * *** empty log message ***
64  *
65  * Revision 2.13  1995/10/11  17:54:40  sanjeev
66  * fixed Charm++ chare creation
67  *
68  * Revision 2.12  1995/09/06  21:48:50  jyelon
69  * Eliminated 'CkProcess_BocMsg', using 'CkProcess_ForChareMsg' instead.
70  *
71  * Revision 2.11  1995/09/01  02:13:17  jyelon
72  * VID_BLOCK, CHARE_BLOCK, BOC_BLOCK consolidated.
73  *
74  * Revision 2.10  1995/08/24  15:48:26  gursoy
75  * worng cpv-macro usage for EpInfoTable (it is a Csv type not Cpv)
76  * fixed
77  *
78  * Revision 2.9  1995/07/27  20:29:34  jyelon
79  * Improvements to runtime system, general cleanup.
80  *
81  * Revision 2.8  1995/07/25  00:29:31  jyelon
82  * *** empty log message ***
83  *
84  * Revision 2.7  1995/07/24  01:54:40  jyelon
85  * *** empty log message ***
86  *
87  * Revision 2.6  1995/07/22  23:44:13  jyelon
88  * *** empty log message ***
89  *
90  * Revision 2.5  1995/07/19  22:15:22  jyelon
91  * *** empty log message ***
92  *
93  * Revision 2.4  1995/07/12  16:28:45  jyelon
94  * *** empty log message ***
95  *
96  * Revision 2.3  1995/07/06  22:42:11  narain
97  * Changes for LDB interface revision
98  *
99  * Revision 2.2  1995/06/29  21:38:00  narain
100  * Added #define CldNewChareFromLocal, and code for CkMakeFreeCharesMessage,
101  * CkQueueFreeCharesMessage, and SetNewChareMsg
102  *
103  * Revision 2.1  1995/06/08  17:09:41  gursoy
104  * Cpv macro changes done
105  *
106  * Revision 1.13  1995/05/04  22:02:40  jyelon
107  * *** empty log message ***
108  *
109  * Revision 1.12  1995/04/23  20:52:58  sanjeev
110  * Removed Core....
111  *
112  * Revision 1.11  1995/04/23  14:27:44  brunner
113  * Now includes converse.h, to get declaration of sysDone
114  *
115  * Revision 1.10  1995/04/14  21:05:01  milind
116  * Changed HostPeNum to NumPes
117  *
118  * Revision 1.9  1995/04/13  20:53:15  sanjeev
119  * Changed Mc to Cmi
120  *
121  * Revision 1.8  1995/04/02  00:47:39  sanjeev
122  * changes for separating Converse
123  *
124  * Revision 1.7  1995/03/25  18:24:05  sanjeev
125  * *** empty log message ***
126  *
127  * Revision 1.6  1995/03/24  16:41:38  sanjeev
128  * *** empty log message ***
129  *
130  * Revision 1.5  1995/03/17  23:36:25  sanjeev
131  * changes for better message format
132  *
133  * Revision 1.4  1994/12/01  23:55:30  sanjeev
134  * interop stuff
135  *
136  * Revision 1.3  1994/11/18  20:33:53  narain
137  * Changed CkExit() into CkEndCharm and CkExit() with CkExit only setting the
138  * value of sysDone to 1. (CkExit messages now have encoded sequence numbers
139  *   - Sanjeev and Narain
140  *
141  * Revision 1.2  1994/11/09  21:43:18  sanjeev
142  * printf consts
143  *
144  * Revision 1.1  1994/11/03  17:38:49  brunner
145  * Initial revision
146  *
147  ***************************************************************************/
148 static char ident[] = "@(#)$Header$";
149 #include "chare.h"
150 #include "globals.h"
151 #include "trace.h"
152 #include "converse.h"
153
154 #include <varargs.h>
155
156 extern void *FIFO_Create();
157 void CkLdbSend();
158 extern CHARE_BLOCK *CreateChareBlock();
159
160
161 CpvStaticDeclare(int, num_exits);
162 CpvStaticDeclare(int, num_endcharms);
163
164
165
166 void ckModuleInit()
167 {
168    CpvInitialize(int, num_exits);
169    CpvInitialize(int, num_endcharms);
170
171    CpvAccess(num_exits)=0;
172    CpvAccess(num_endcharms)=0;
173 }
174
175
176 /*************************************************************************
177   EXIT PROTOCOL FOR CHARM
178
179   How do the CkExit and CkEndCharm protocols work?
180
181   CkExits send a message with an iteration number whose value is num_exits
182   CkEndCharms send -1 in the message ..
183
184   To prevent the sending of two messages for a particular CkExit,
185     *  the seq number in the message should equal the value of num_exits for
186        a CkExit to be processed (thus no two CkExits with the same seq number
187        are processed).
188   Also, CkEndCharm has a synchronization : the broadcast for statistics
189   collection is done only after all processors have reported a CkEndCharm.
190
191   The scheme is necessitated by the possibility of use of more than one 
192   "DoCharm()" (now Scheduler()) and CkExits in each of them.
193
194   The control flow - Any processor calling CkExit or CkEndCharm sends a 
195   BroadcastExitMessage to node 0 which broadcasts to ExitMessage on all 
196   processors.
197
198   ExitMessage handles CkExit and CkEndCharm requests differently.
199
200 **************************************************************************/
201
202
203 CkExit()
204 {
205         int *msg;
206
207         msg = (int *) CkAllocMsg(sizeof(int));
208         CkMemError(msg);
209         *msg = CpvAccess(num_exits);
210
211         GeneralSendMsgBranch(CsvAccess(CkEp_Stat_BroadcastExitMessage),
212                         msg, 0, BocMsg, StatisticBocNum);
213 }
214
215
216 CkEndCharm()
217 {
218         int *msg;
219
220         msg = (int *) CkAllocMsg(sizeof(int));
221         CkMemError(msg);
222         *msg = -1;
223
224         GeneralSendMsgBranch(CsvAccess(CkEp_Stat_BroadcastExitMessage),
225                         msg, 0, BocMsg, StatisticBocNum);
226 }
227
228 BroadcastExitMessage(usr, data)
229 void *usr, *data;
230 {
231 /* This function is executed only on node 0 - corresponds to 
232                  CsvAccess(CkEp_Stat_BroadcastExitMessage) */
233
234         int *msg;
235         
236         if (*((int *)usr) == -1) { /* For CkEndCharm */
237                 CpvAccess(num_endcharms)++ ;
238                 if( CpvAccess(num_endcharms) < CmiNumPes() ) 
239                         return;
240         }
241         else {  /* For CkExit */
242                 if(*((int *)usr) < CpvAccess(num_exits))
243                          return;
244                 CpvAccess(num_exits)++;
245         }
246         
247         msg = (int *) CkAllocMsg(sizeof(int));
248         CkMemError(msg);
249         *msg = *((int *)usr);
250         GeneralBroadcastMsgBranch(CsvAccess(CkEp_Stat_ExitMessage), msg, 
251                         BroadcastBocMsg, StatisticBocNum);
252         CpvAccess(disable_sys_msgs) = 1;
253 }
254
255 ExitMessage(usr, data)
256 void *usr, *data;
257 {
258         if(*((int *)usr) == -1) /* If the user called CkEndCharm */
259         {
260                 SendNodeStatistics();
261                 send_log();
262                 if ( CmiMyPe() != 0 && CpvAccess(CtrRecdTraceMsg) 
263                                     && CpvAccess(RecdStatMsg) ) 
264                         ExitNode();
265         }
266         else /* If the user called CkExit */
267         {
268                 CkEndCharm();
269                 if(CmiMyPe())
270                         CpvAccess(num_exits)++;
271         }
272 }
273
274
275 SendNodeStatistics()
276 {
277         (*(CsvAccess(EpInfoTable)[CsvAccess(CkEp_Stat_Data)].function)) 
278                                                                 (NULL,NULL);
279 }
280
281
282 ExitNode()
283 {
284         char *msg;
285         ENVELOPE *env;
286
287         /* close_log(); moved to convcore.c */
288         if (CmiMyPe() == 0)
289         {
290                 /* First print out statistics. */
291                 PrintOutStatistics();
292         }
293
294         /* Complete the loop */ 
295         CsdExitScheduler();
296 }
297
298
299
300
301
302
303 /**********************************************************************
304  * These are utility routines for chares 
305 ***********************************************************************/
306
307 ChareExit()
308 {
309         SetID_chare_magic_number(CpvAccess(currentChareBlock)->selfID,-1);
310         CmiFree(CpvAccess(currentChareBlock));
311 }
312
313
314 CHARE_BLOCK *CreateChareBlock(sizeData, kind, magic)
315 int sizeData, magic, kind;
316 {
317   CHARE_BLOCK *p = (CHARE_BLOCK *)CmiAlloc(sizeof(CHARE_BLOCK) + sizeData);
318   CkMemError(p);
319   SetID_chare_magic_number(p->selfID, magic);
320   SetID_onPE(p->selfID, CmiMyPe());
321   SetID_chareBlockPtr(p->selfID, p);
322   p->charekind = kind;
323
324   /* the chare data area is just after the chare-block, by default */
325   p->chareptr = (void *)(p+1); 
326   return((void *) p);
327 }
328
329 IsChareLocal(chareid)
330 ChareIDType * chareid;
331 {
332         if (GetID_onPE((*chareid)) == CmiMyPe()) return 1;
333         return 0;
334 }
335
336 void *GetChareDataPtr(chareid)
337 ChareIDType * chareid;
338 {
339         return ((CHARE_BLOCK *) GetID_chareBlockPtr((*chareid))) + 1;
340 }
341
342 MyChareID(pChareID)
343 ChareIDType * pChareID;
344 {
345     *pChareID = CpvAccess(currentChareBlock)->selfID;
346 }
347
348
349 /* Deleted already commented out MyParentID function : SANJEEV May 24, 93 */
350
351 MainChareID(pChareID)
352 ChareIDType * pChareID;
353 {
354         SetID_onPE((*pChareID), 0);
355         if (CmiMyPe() == 0)
356                 SetID_chare_magic_number((*pChareID),
357                     GetID_chare_magic_number(CpvAccess(mainChareBlock)->selfID));
358         else
359                 SetID_chare_magic_number((*pChareID), CpvAccess(mainChare_magic_number));
360         SetID_chareBlockPtr((*pChareID), CpvAccess(mainChareBlock));
361 }
362
363
364
365 /* this is the general CreateChare call: all the user level CreateChare
366    calls are mapped to this call: they include 
367
368         CreateChare(Charename, Entry, Msg, [vid [,destPE]]) 
369
370    If vid is NULL_VID it is a CreateChare call ("without ID"). 
371    if DestPe is CK_PE_ANY  then it may go to any destination node
372    if DestPe is not CK_PE_SPECIAL then the message is bound for a regular destination
373
374 */
375
376 CreateChare(id, Entry, Msg, vid, destPE)
377 int id;
378 EntryNumType Entry;
379 void *Msg;
380 ChareIDType *vid;
381 int destPE;
382 {
383   ENVELOPE *env;
384   CHARE_BLOCK *vidblock;
385
386   if (id!=CsvAccess(EpInfoTable)[Entry].chareindex) 
387     CmiPrintf("** ERROR ** Illegal combination of CHAREINDEX/EP in CreateChare\n");
388
389   TRACE(CmiPrintf("[%d] CreateChare: Entry=%d\n", CmiMyPe(), Entry));
390   
391   CpvAccess(nodecharesCreated)++;
392   env = ENVELOPE_UPTR(Msg);
393   
394   SetEnv_EP(env, Entry);
395   
396   if (vid != NULL_VID) {
397     vidblock = (CHARE_BLOCK *)CreateChareBlock(0, CHAREKIND_UVID, rand());
398     vidblock->x.vid_queue = (void *)FIFO_Create();
399     (*vid) = vidblock->selfID;
400     SetEnv_vidPE(env, GetID_onPE(vidblock->selfID));
401     SetEnv_vidBlockPtr(env, GetID_chareBlockPtr(vidblock->selfID));
402   } else {
403     SetEnv_vidPE(env, -1);
404     SetEnv_vidBlockPtr(env, NULL);
405   }
406   
407   trace_creation(NewChareMsg, Entry, env);
408   QDCountThisCreation(Entry, USERcat, NewChareMsg, 1);
409
410   if (CK_PE_SPECIAL(destPE)) {
411     if (destPE != CK_PE_ANY) {
412       CmiPrintf("** ERROR ** Illegal destPE in CreateChare\n");
413     }
414     SetEnv_msgType(env, NewChareMsg);
415     /* This CmiSetHandler is here because load balancer will fail to call */
416     /* CkCheck_and_Send on local messages.  Fix this.                     */
417     CmiSetHandler(env, CpvAccess(HANDLE_INCOMING_MSG_Index));
418     CldNewSeedFromLocal(env, LDB_ELEMENT_PTR(env),
419                         CkLdbSend,
420                         GetEnv_queueing(env),
421                         GetEnv_priosize(env),
422                         GetEnv_priobgn(env));
423   } else {
424     SetEnv_msgType(env, NewChareNoBalanceMsg);
425     CkCheck_and_Send(destPE, env);
426   }
427
428 }
429
430
431
432 SendMsg(Entry, Msg, pChareID)
433 int Entry;
434 void * Msg;
435 ChareIDType * pChareID;
436 {
437   ENVELOPE * env;
438   int destPE = GetID_onPE((*pChareID));
439
440   CpvAccess(nodeforCharesCreated)++;
441   env = ENVELOPE_UPTR(Msg);
442   SetEnv_msgType(env, ForChareMsg);
443   SetEnv_EP(env, Entry);
444   SetEnv_chareBlockPtr(env, GetID_chareBlockPtr((*pChareID)));
445   SetEnv_chare_magic_number(env, GetID_chare_magic_number((*pChareID)));
446   QDCountThisCreation(Entry, USERcat, ForChareMsg, 1);
447   trace_creation(GetEnv_msgType(env), Entry, env);
448   CkCheck_and_Send(destPE, env);
449 }
450
451
452 /*****************************************************************/
453 /** Gets reference number.                                      **/
454 /*****************************************************************/
455 GetRefNumber(msg)
456 void *msg;
457 {
458         ENVELOPE *env = (ENVELOPE *) ENVELOPE_UPTR(msg);
459
460         return GetEnv_ref(env);
461 }
462
463
464 /*****************************************************************/
465 /** Sets reference number.                                      **/
466 /*****************************************************************/
467 SetRefNumber(msg, number)
468 void *msg;
469 int number;
470 {
471         ENVELOPE *env = (ENVELOPE *) ENVELOPE_UPTR(msg);
472
473         SetEnv_ref(env, number);
474 }
475
476
477 void CkSetQueueing(usrptr, kind)
478 void *usrptr;
479 int kind;
480 {
481   SetEnv_queueing(ENVELOPE_UPTR(usrptr), kind);
482 }
483
484 /*****************************************************************************
485  * CkLdbSend is a function that is passed to the Ldb strategy to send out a
486  * message to another processor
487  *****************************************************************************/
488
489 void CkLdbSend(msgst, destPE)
490      void *msgst;
491      int destPE;
492 {
493   ENVELOPE *env = (ENVELOPE *)msgst;
494
495 /* trace_creation is NOT needed here because it has already been done in
496    the CreateChare
497   trace_creation(GetEnv_msgType(env), GetEnv_EP(env), env);  */
498
499   CkCheck_and_Send(destPE, env);
500 }
501
502 CkEnqueue(env)
503 void *env;
504 {
505   CsdEnqueueGeneral(env,
506     GetEnv_queueing(env),
507     GetEnv_priosize(env),
508     GetEnv_priobgn(env));
509 }
510
511 /************************************************************************
512  *
513  * CkPrioConcat
514  *
515  * Copies all the priority bits from the bitvector in 'srcmsg' onto
516  * the bitvector in 'dstmsg', then, if there is any space left in the
517  * bitvector of 'dstmsg', that space is filled by bits taken from the
518  * lsb of 'delta'.
519  *
520  * The code works as follows:
521  *
522  * step 1: Copy old bitvector onto new. Always copies a multiple of
523  * 32 bits, therefore, may copy some "padding" bits.  The number of
524  * padding bits copied can be found in 'padbits'.
525  *
526  * step 2: move bits in delta to msb-end.
527  *
528  * step 3: if any padding-bits were copied, overwrite them with a
529  * piece of delta.
530  *
531  * step 4: if padding-bits were insufficient to hold all of delta,
532  * store remainder of delta in next word.
533  *
534  ************************************************************************/
535
536 #define CINTBITS (sizeof(int)*8)
537
538 void CkPrioConcatFn(srcmsg, dstmsg, delta)
539 void *srcmsg;
540 void *dstmsg;
541 unsigned int delta;
542 {
543   int padbits, deltabits;
544   ENVELOPE *srcenv = ENVELOPE_UPTR(srcmsg);
545   ENVELOPE *dstenv = ENVELOPE_UPTR(dstmsg);
546   int srcbits = GetEnv_priosize(srcenv);
547   int dstbits = GetEnv_priosize(dstenv);
548   int srcwords = (srcbits+CINTBITS-1)/CINTBITS;
549   int dstwords = (dstbits+CINTBITS-1)/CINTBITS;
550   unsigned int *srcptr = GetEnv_prioend(srcenv) - srcwords;
551   unsigned int *dstptr = GetEnv_prioend(dstenv) - dstwords;
552   deltabits = dstbits - srcbits;
553   if (deltabits < 0) {
554     CmiPrintf("CkPrioConcat: prio-bits from source message don't fit in destination message.\n");
555     exit(1);
556   }
557   if (deltabits > CINTBITS) {
558     CmiPrintf("CkPrioConcat: prio-bits from source message plus bits of delta don't fill destination-message.\n");
559     exit(1);
560   }
561   while (srcbits>0) { *dstptr++ = *srcptr++; srcbits -= CINTBITS; }
562   padbits = -srcbits;
563   delta <<= (CINTBITS-deltabits);
564   if (padbits) {
565     dstptr[-1] &= (((unsigned int)(-1))<<padbits);
566     dstptr[-1] |= (delta>>(CINTBITS-padbits));
567   }
568   if (deltabits>padbits) dstptr[0] = (delta<<padbits);
569 }
570
571 int CkPrioSizeBitsFn(msg) void *msg;
572 {
573     return GetEnv_priosize(ENVELOPE_UPTR(msg));
574 }
575
576 int CkPrioSizeBytesFn(msg) void *msg;
577 {
578     return GetEnv_priobytes(ENVELOPE_UPTR(msg));
579 }
580
581 int CkPrioSizeWordsFn(msg) void *msg;
582 {
583     return GetEnv_priowords(ENVELOPE_UPTR(msg));
584 }
585
586 unsigned int *CkPrioPtrFn(msg) void *msg;
587 {
588     return GetEnv_priobgn(ENVELOPE_UPTR(msg));
589 }