Added the language-specific load estimator API.
[charm.git] / src / conv-ldb / cldb.c
1 #include "converse.h"
2
3 /*
4  * CldSwitchHandler takes a message and a new handler number.  It
5  * changes the handler number to the new handler number and move the
6  * old to the Xhandler part of the header.  When the message gets
7  * handled, the handler should call CldRestoreHandler to put the old
8  * handler back.
9  *
10  * CldPutToken puts a message in the scheduler queue in such a way
11  * that it can be retreived from the queue.  Once the message gets
12  * handled, it can no longer be retreived.  CldGetToken removes a
13  * message that was placed in the scheduler queue in this way.
14  * CldCountTokens tells you how many tokens are currently retreivable.
15  */
16
17 typedef struct {
18   int count;
19   CldEstimator fns[16];
20 } CldEstimatorTable;
21  
22 CpvStaticDeclare(CldEstimatorTable, _estfns);
23
24 void CldRegisterEstimator(CldEstimator fn)
25 {
26   CpvAccess(_estfns).fns[CpvAccess(_estfns).count++] = fn;
27 }
28
29 int CldEstimate(void)
30 {
31   CldEstimatorTable *estab = &(CpvAccess(_estfns));
32   int i, load=0;
33   for(i=0; i<estab->count; i++)
34     load += (*(estab->fns[i]))();
35   return load;
36 }
37
38 static int CsdEstimator(void)
39 {
40   return CsdLength();
41 }
42
43 int CldRegisterInfoFn(CldInfoFn fn)
44 {
45   return CmiRegisterHandler((CmiHandler)fn);
46 }
47
48 int CldRegisterPackFn(CldPackFn fn)
49 {
50   return CmiRegisterHandler((CmiHandler)fn);
51 }
52
53 void CldSwitchHandler(char *cmsg, int handler)
54 {
55   CmiSetXHandler(cmsg, CmiGetHandler(cmsg));
56   CmiSetHandler(cmsg, handler);
57 }
58
59 void CldRestoreHandler(char *cmsg)
60 {
61   CmiSetHandler(cmsg, CmiGetXHandler(cmsg));
62 }
63
64 void Cldhandler(void *);
65  
66 typedef struct CldToken_s {
67   char msg_header[CmiMsgHeaderSizeBytes];
68   void *msg;  /* if null, message already removed */
69   struct CldToken_s *pred;
70   struct CldToken_s *succ;
71 } *CldToken;
72
73 typedef struct CldProcInfo_s {
74   int tokenhandleridx;
75   int load; /* number of items in doubly-linked circle besides sentinel */
76   CldToken sentinel;
77 } *CldProcInfo;
78
79 CpvDeclare(CldProcInfo, CldProc);
80
81 static void CldTokenHandler(CldToken tok)
82 {
83   CldProcInfo proc = CpvAccess(CldProc);
84   CldToken pred, succ;
85   if (tok->msg) {
86     tok->pred->succ = tok->succ;
87     tok->succ->pred = tok->pred;
88     proc->load --;
89     CmiHandleMessage(tok->msg);
90   }
91 }
92
93 int CldCountTokens()
94 {
95   CldProcInfo proc = CpvAccess(CldProc);
96   return proc->load;
97 }
98
99 void CldPutToken(void *msg)
100 {
101   CldProcInfo proc = CpvAccess(CldProc);
102   CldInfoFn ifn = (CldInfoFn)CmiHandlerToFunction(CmiGetInfo(msg));
103   CldToken tok = (CldToken)CmiAlloc(sizeof(struct CldToken_s));
104   int len, queueing, priobits; unsigned int *prioptr;
105   CldPackFn pfn;
106
107   tok->msg = msg;
108
109   /* add token to the doubly-linked circle */
110   tok->pred = proc->sentinel->pred;
111   tok->succ = proc->sentinel;
112   tok->pred->succ = tok;
113   tok->succ->pred = tok;
114   proc->load ++;
115   
116   /* add token to the scheduler */
117   CmiSetHandler(tok, proc->tokenhandleridx);
118   ifn(msg, &pfn, &len, &queueing, &priobits, &prioptr);
119
120   queueing = CQS_QUEUEING_LIFO; 
121   CsdEnqueueGeneral(tok, queueing, priobits, prioptr);
122 }
123
124 void CldGetToken(void **msg)
125 {
126   CldProcInfo proc = CpvAccess(CldProc);
127   CldToken tok;
128   tok = proc->sentinel->succ;
129   if (tok == proc->sentinel) {
130     *msg = 0; return;
131   }
132   tok->pred->succ = tok->succ;
133   tok->succ->pred = tok->pred;
134   proc->load --;
135   *msg = tok->msg;
136   tok->msg = 0;
137 }
138
139 void CldModuleGeneralInit()
140 {
141   CldToken sentinel = (CldToken)CmiAlloc(sizeof(struct CldToken_s));
142   CldProcInfo proc;
143
144   CpvInitialize(CldProcInfo, CldProc);
145   CpvInitialize(CldEstimatorTable, _estfns);
146   CpvAccess(_estfns).count = 0;
147   CldRegisterEstimator(CsdEstimator);
148   CpvAccess(CldProc) = (CldProcInfo)CmiAlloc(sizeof(struct CldProcInfo_s));
149   proc = CpvAccess(CldProc);
150   proc->load = 0;
151   proc->tokenhandleridx = CmiRegisterHandler((CmiHandler)CldTokenHandler);
152   proc->sentinel = sentinel;
153   sentinel->succ = sentinel;
154   sentinel->pred = sentinel;
155 }