Removed almost all warnings on origin2000.
[charm.git] / src / conv-core / conv-conds.c
1 #include <stdio.h>
2
3 #include "converse.h"
4
5 static void InsertInHeap(double Time, CcdVoidFn fnp, void *arg);
6 static void RemoveFromHeap(int index);
7 static void SwapHeapEntries(int index1, int index2);
8
9 typedef struct fn_arg {
10   CcdVoidFn fn;
11   void *arg;
12   struct fn_arg *next;
13 } FN_ARG;
14
15 /* We have a fixed number of these elements .. */
16 typedef struct {
17   FN_ARG *fn_arg_list;
18 } CONDS;
19
20 typedef struct {
21     double timeVal;     /* the actual time value we sort on           */
22     CcdVoidFn fn; 
23     void *arg; 
24 } HeapIndexType;
25
26 #define MAXTIMERHEAPENTRIES       512
27 #define MAXCONDCHKARRAYELTS       512
28
29 /** Note : The heap is only stored in elements 
30     timerHeap[0] to timerHeap[numHeapEntries] */
31
32 CpvStaticDeclare(HeapIndexType*, timerHeap); 
33 CpvStaticDeclare(CONDS*, CondArr);   
34 CpvStaticDeclare(FN_ARG*, PeriodicCalls);
35 CpvStaticDeclare(int, numHeapEntries);
36
37 CpvDeclare(int, CcdNumChecks);
38
39 extern double CmiWallTimer(void);
40
41 void CcdModuleInit(void)
42 {
43    int i;
44
45    CpvInitialize(HeapIndexType*, timerHeap);
46    CpvInitialize(CONDS*, CondArr);
47    CpvInitialize(FN_ARG*, PeriodicCalls);
48    CpvInitialize(int, numHeapEntries);
49    CpvInitialize(int, CcdNumChecks);
50
51    CpvAccess(timerHeap) = 
52      (HeapIndexType*) malloc(sizeof(HeapIndexType)*(MAXTIMERHEAPENTRIES + 1));
53    CpvAccess(CondArr) = (CONDS*) malloc(sizeof(CONDS)*(MAXCONDCHKARRAYELTS));
54    CpvAccess(CcdNumChecks) = 0;
55    CpvAccess(numHeapEntries) = 0;
56    CpvAccess(PeriodicCalls) = (FN_ARG *) 0;
57    for(i=0; i<MAXCONDCHKARRAYELTS; i++)
58      CpvAccess(CondArr)[i].fn_arg_list = 0;
59 }
60
61
62
63 /*****************************************************************************
64   Add a function that will be called when a particular condition is raised
65  *****************************************************************************/
66 void CcdCallOnCondition(int condnum,CcdVoidFn fnp,void *arg)
67 {
68   FN_ARG *newEntry = (FN_ARG *) malloc(sizeof(FN_ARG)); 
69   newEntry->fn = fnp;  
70   newEntry->arg  = arg;
71   newEntry->next = CpvAccess(CondArr)[condnum].fn_arg_list;
72   CpvAccess(CondArr)[condnum].fn_arg_list =  newEntry;
73
74
75 /*****************************************************************************
76   Add a function that will be called during next call to PeriodicChecks
77  *****************************************************************************/
78 void CcdPeriodicallyCall(CcdVoidFn fnp, void *arg)
79 {
80   FN_ARG *temp = (FN_ARG *) malloc(sizeof(FN_ARG)); 
81   temp->fn = fnp;
82   temp->arg = arg;
83   temp->next = CpvAccess(PeriodicCalls);
84   CpvAccess(PeriodicCalls) = temp;
85   CpvAccess(CcdNumChecks)++;
86 }
87
88 /*****************************************************************************
89   Call all the functions that are waiting for this condition to be raised
90  *****************************************************************************/
91 void CcdRaiseCondition(int condNum)
92 {
93   FN_ARG *temp, *del;
94   temp = CpvAccess(CondArr)[condNum].fn_arg_list;
95   CpvAccess(CondArr)[condNum].fn_arg_list = 0;
96   while(temp) {
97     (*(temp->fn))(temp->arg);
98     del = temp;
99     temp = temp->next;
100     free(del);
101   }
102 }
103
104 /*****************************************************************************
105   Call the function with the provided argument after a minimum delay of deltaT
106  *****************************************************************************/
107 void CcdCallFnAfter(CcdVoidFn fnp, void *arg, unsigned int deltaT)
108 {
109   double tPrime, currT;
110   currT  = CmiWallTimer();                /* get current time */
111   tPrime = currT + (double)deltaT/1000.0; /* add delta to determine what time
112                                             to actually execute fn */
113   InsertInHeap(tPrime, fnp, arg); /* insert into tmr hp */
114
115
116 /*****************************************************************************
117   If any of the CallFnAfter functions can now be called, call them 
118   ****************************************************************************/
119 void CcdCallBacks()
120 {
121   double currTime;
122   FN_ARG *temp, *next;
123   
124   if ( CpvAccess(numHeapEntries) > 0 ) {
125     currTime = CmiWallTimer();
126     while ((CpvAccess(numHeapEntries) > 0) && 
127            CpvAccess(timerHeap)[1].timeVal < currTime)
128     {
129       (*(CpvAccess(timerHeap)[1].fn))(CpvAccess(timerHeap)[1].arg);
130       RemoveFromHeap(1);
131     }
132   }
133
134   temp = CpvAccess(PeriodicCalls); 
135   CpvAccess(PeriodicCalls) = 0 ;
136   for(; temp; temp = next) {
137     CpvAccess(CcdNumChecks)--;
138     (*(temp->fn))(temp->arg);
139     next = temp->next ;
140     free(temp) ;
141   }
142
143
144 /*****************************************************************************
145   These are internal functions
146   ****************************************************************************/
147
148 static void InsertInHeap(double theTime, CcdVoidFn fnp, void *arg)
149 {
150   int child, parent;
151   
152   if(CpvAccess(numHeapEntries) > MAXTIMERHEAPENTRIES) 
153     {
154       CmiPrintf("Heap overflow (InsertInHeap), exiting...\n");
155       exit(1);
156     }
157   else 
158     {
159       CpvAccess(CcdNumChecks)++;
160       CpvAccess(numHeapEntries)++;
161       CpvAccess(timerHeap)[CpvAccess(numHeapEntries)].timeVal    = theTime;
162       CpvAccess(timerHeap)[CpvAccess(numHeapEntries)].fn = fnp;
163       CpvAccess(timerHeap)[CpvAccess(numHeapEntries)].arg = arg;
164       child  = CpvAccess(numHeapEntries);    
165       parent = child / 2;
166       while((parent>0) && (CpvAccess(timerHeap)[child].timeVal<CpvAccess(timerHeap)[parent].timeVal))
167         {
168           SwapHeapEntries(child,parent);
169           child  = parent;
170           parent = parent / 2;
171         }
172     }
173
174
175 static void RemoveFromHeap(int index)
176 {
177   int parent,child;
178   
179   parent = index;
180   if(!CpvAccess(numHeapEntries) || (index != 1)) 
181     {
182       CmiPrintf("Internal inconsistency (RemoveFromHeap), exiting ...\n");
183       exit(1);
184     } 
185   else 
186     {
187       CpvAccess(timerHeap)[index].arg = 0;
188       SwapHeapEntries(index,CpvAccess(numHeapEntries)); /* put deleted value at end 
189                                                 of heap */
190       CpvAccess(numHeapEntries)--;
191       CpvAccess(CcdNumChecks)--;
192       if(CpvAccess(numHeapEntries)) 
193         {             /* if any left, then bubble up values */
194           child = 2 * parent;
195           while(child <= CpvAccess(numHeapEntries)) 
196             {
197               if(((child + 1) <= CpvAccess(numHeapEntries))  &&
198                  (CpvAccess(timerHeap)[child].timeVal > CpvAccess(timerHeap)[child + 1].timeVal))
199                 child++;              /* use the smaller of the two */
200               if(CpvAccess(timerHeap)[parent].timeVal <= CpvAccess(timerHeap)[child].timeVal) 
201                 break;
202               SwapHeapEntries(parent,child);
203               parent  = child;      /* go down the tree one more step */
204               child  = 2 * child;
205             }
206         }
207     } 
208
209
210 static void SwapHeapEntries(int index1, int index2)
211 {
212   HeapIndexType temp;
213   
214   temp              = CpvAccess(timerHeap)[index1];
215   CpvAccess(timerHeap)[index1] = CpvAccess(timerHeap)[index2];
216   CpvAccess(timerHeap)[index2] = temp;
217
218
219
220
221
222