1fc34e7284445e6f8c64693bb3eeb6a5e84b5cfd
[charm.git] / src / conv-ldb / cldb.rand.c
1 #include "converse.h"
2
3 /* CldEnqueue is the load balancer.  It accepts a message, and
4  * enqueues the message on some processor of its own choosing.
5  * Processors are chosen in such a way as to help distribute the
6  * workload.
7  *
8  * The user of the load balancer must set aside some space in the
9  * message for load balancer to store temporary data.  The number of
10  * bytes that must be reserved is CLD_FIELDSIZE.  There is no
11  * stipulation about where in the message this field must be.
12  *
13  * If the message is to be prioritized, then the message must also
14  * contain its priority.  This can be omitted if the message is to
15  * have the null priority.  There is no stipulation about where in
16  * the message the priority must be stored.
17  *
18  * The user of the load balancer must write an "info" function.
19  * The load-balancer will call the info function when it needs to
20  * know any of the following pieces of information:
21  *
22  *    - the length of the message, in bytes.
23  *    - the queueing strategy of the message.
24  *    - where the priority is, in the message.
25  *    - where the ldb field is, in the message.
26  *
27  * The info function must be able to determine all this information.
28  * The info function must be registered, much like a converse handler,
29  * using CldRegisterInfoFn.  It must have this prototype:
30  *
31  *    void Info(void *msg, 
32  *              int *len,
33  *              void *ldbfield,
34  *              int *queuing,
35  *              int *priobits,
36  *              int **prioptr);
37  *
38  * The user of the load balancer must also write a "pack" function.
39  * When the load balancer is about to send the message across
40  * processor boundaries, it will call the pack function.  The
41  * pack function may modify the message in any way.  The pack function
42  * must be registered using CldRegisterPackFn, and must have this
43  * prototype:
44  *
45  *    void Pack(void **msg);
46  *
47  * Normally, CldEnqueue is used for load-balancing.  It can also be
48  * used as a convenience that helps you enqueue a message on a processor
49  * of your choosing.  The parameter 'pe' lets you specify which processor
50  * the message is to go to.  If the value CLD_ANYWHERE is given, then
51  * the message is load-balanced.  If it is CLD_BROADCAST, the message
52  * is broadcast to all other processors.  If it is CLD_BROADCAST_ALL,
53  * the message is broadcast to all processors.  If it is a processor
54  * number, the message is sent to a specific location.
55  *
56  */
57
58 typedef struct CldField
59 {
60   CLD_STANDARD_FIELD_STUFF
61   int infofn;
62 }
63 *CldField;
64
65 int Cld_fieldsize = sizeof(struct CldField);
66
67 void CldHandler(char *msg)
68 {
69   int len, queueing, priobits; CldField ldbfield;
70   unsigned int *prioptr; CldInfoFn ifn;
71   CmiGrabBuffer(&msg);
72   CldRestoreHandler(msg, &ldbfield);
73   ifn = (CldInfoFn)CmiHandlerToFunction(ldbfield->infofn);
74   ifn(msg, &len, &ldbfield, &queueing, &priobits, &prioptr);
75   CsdEnqueueGeneral(msg, queueing, priobits, prioptr);
76 }
77
78 CpvDeclare(int, CldHandlerIndex);
79
80 void CldEnqueue(int pe, void *msg, int infofn, int packfn)
81 {
82   int len, queueing, priobits; unsigned int *prioptr; CldField ldbfield;
83   CldInfoFn ifn = (CldInfoFn)CmiHandlerToFunction(infofn);
84   CldPackFn pfn = (CldPackFn)CmiHandlerToFunction(packfn);
85   if (CmiGetHandler(msg) >= CpvAccess(CmiHandlerMax)) *((int*)0)=0;
86   if (pe == CLD_ANYWHERE) pe = (((rand()+CmiMyPe())&0x7FFFFFFF)%CmiNumPes());
87   if (pe == CmiMyPe()) {
88     ifn(msg, &len, &ldbfield, &queueing, &priobits, &prioptr);
89     CsdEnqueueGeneral(msg, queueing, priobits, prioptr);
90   } else {
91     pfn(&msg);
92     ifn(msg, &len, &ldbfield, &queueing, &priobits, &prioptr);
93     CldSwitchHandler(msg, ldbfield, CpvAccess(CldHandlerIndex));
94     ldbfield->infofn = infofn;
95     if (pe==CLD_BROADCAST) CmiSyncBroadcastAndFree(len, msg);
96     else if (pe==CLD_BROADCAST_ALL) CmiSyncBroadcastAllAndFree(len, msg);
97     else CmiSyncSendAndFree(pe, len, msg);
98   }
99 }
100
101 void CldModuleInit()
102 {
103   CpvInitialize(int, CldHandlerIndex);
104   CpvAccess(CldHandlerIndex) = CmiRegisterHandler(CldHandler);
105 }