Fixed all the memory leaks in cldb.c and cldb.graph.c
[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  * Caution: these functions are using the function "CmiReference"
17  * which I just added to the Cmi memory allocator (it increases the
18  * reference count field, making it possible to free the memory
19  * twice.)  I'm not sure how well this is going to work.  I need this
20  * because the message should not be freed until it's out of the
21  * scheduler queue AND out of the user's hands.  It needs to stay
22  * around while it's in the scheduler queue because it may contain
23  * a priority.  I should probably rewrite these subroutines so that
24  * they simply copy the priority, I would feel safer that way.
25  *
26  */
27
28 CpvDeclare(int, CldAvgLoad);
29
30 int CldRegisterInfoFn(CldInfoFn fn)
31 {
32   return CmiRegisterHandler((CmiHandler)fn);
33 }
34
35 int CldRegisterPackFn(CldPackFn fn)
36 {
37   return CmiRegisterHandler((CmiHandler)fn);
38 }
39
40 void CldSwitchHandler(char *cmsg, int handler)
41 {
42   CmiSetXHandler(cmsg, CmiGetHandler(cmsg));
43   CmiSetHandler(cmsg, handler);
44 }
45
46 void CldRestoreHandler(char *cmsg)
47 {
48   CmiSetHandler(cmsg, CmiGetXHandler(cmsg));
49 }
50
51 void Cldhandler(void *);
52  
53 typedef struct CldToken_s {
54   char msg_header[CmiMsgHeaderSizeBytes];
55   void *msg;  /* if null, message already removed */
56   struct CldToken_s *pred;
57   struct CldToken_s *succ;
58 } *CldToken;
59
60 typedef struct CldProcInfo_s {
61   int tokenhandleridx;
62   int load; /* number of items in doubly-linked circle besides sentinel */
63   CldToken sentinel;
64 } *CldProcInfo;
65
66 CpvDeclare(CldProcInfo, CldProc);
67 extern void CldNotify(int);
68
69 static void CldTokenHandler(CldToken tok)
70 {
71   CldProcInfo proc = CpvAccess(CldProc);
72   CldToken pred, succ;
73   if (tok->msg) {
74     tok->pred->succ = tok->succ;
75     tok->succ->pred = tok->pred;
76     proc->load --;
77     CmiHandleMessage(tok->msg);
78     CldNotify(proc->load);
79   }
80 }
81
82 int CldCountTokens()
83 {
84   CldProcInfo proc = CpvAccess(CldProc);
85   return proc->load;
86 }
87
88 void CldPutToken(void *msg)
89 {
90   CldProcInfo proc = CpvAccess(CldProc);
91   CldInfoFn ifn = (CldInfoFn)CmiHandlerToFunction(CmiGetInfo(msg));
92   CldToken tok = (CldToken)CmiAlloc(sizeof(struct CldToken_s));
93   int len, queueing, priobits; unsigned int *prioptr;
94   CldPackFn pfn;
95
96   tok->msg = msg;
97
98   /* add token to the doubly-linked circle */
99   tok->pred = proc->sentinel->pred;
100   tok->succ = proc->sentinel;
101   tok->pred->succ = tok;
102   tok->succ->pred = tok;
103   proc->load ++;
104   
105   /* add token to the scheduler */
106   CmiSetHandler(tok, proc->tokenhandleridx);
107   ifn(msg, &pfn, &len, &queueing, &priobits, &prioptr);
108
109   queueing = CQS_QUEUEING_LIFO; 
110   CsdEnqueueGeneral(tok, queueing, priobits, prioptr);
111 }
112
113 void CldGetToken(void **msg)
114 {
115   CldProcInfo proc = CpvAccess(CldProc);
116   CldToken tok;
117   tok = proc->sentinel->succ;
118   if (tok == proc->sentinel) {
119     *msg = 0; return;
120   }
121   tok->pred->succ = tok->succ;
122   tok->succ->pred = tok->pred;
123   proc->load --;
124   *msg = tok->msg;
125   tok->msg = 0;
126 }
127
128 void CldModuleGeneralInit()
129 {
130   CldToken sentinel = (CldToken)CmiAlloc(sizeof(struct CldToken_s));
131   CldProcInfo proc;
132
133   CpvInitialize(CldProcInfo, CldProc);
134   CpvInitialize(int, CldAvgLoad);
135   CpvAccess(CldProc) = (CldProcInfo)CmiAlloc(sizeof(struct CldProcInfo_s));
136   CpvAccess(CldAvgLoad) = 0;
137   proc = CpvAccess(CldProc);
138   proc->load = 0;
139   proc->tokenhandleridx = CmiRegisterHandler((CmiHandler)CldTokenHandler);
140   proc->sentinel = sentinel;
141   sentinel->succ = sentinel;
142   sentinel->pred = sentinel;
143 }