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