move to common gemini arch directory
[charm.git] / src / arch / uth / machine.c
1 /** @file
2  * User-level threads machine layer
3  * @ingroup Machine
4  * @{
5  */
6
7 #include <stdio.h>
8 #include <math.h>
9 #include "converse.h"
10
11 /***********************************************************************
12  *
13  * Abort function:
14  *
15  ************************************************************************/
16
17 void CmiAbort(const char *message)
18 {
19   CmiError(message);
20   exit(1);
21 }
22
23 /*****************************************************************************
24  *
25  * Module variables
26  * 
27  ****************************************************************************/
28
29 int        _Cmi_mype;
30 int        _Cmi_myrank;
31 int        _Cmi_numpes;
32 int        Cmi_nodesize;
33 int        Cmi_stacksize = 64000;
34 char     **CmiArgv;
35 CmiStartFn CmiStart;
36 int        CmiUsched;
37 CthThread *CmiThreads;
38 void*      *CmiQueues;
39 int       *CmiBarred;
40 int        CmiNumBarred=0;
41
42 CpvDeclare(void*, CmiLocalQueue);
43
44 /*****************************************************************************
45  *
46  * Comm handles are nonexistent in uth version
47  *
48  *****************************************************************************/
49
50 int CmiAsyncMsgSent(c)
51 CmiCommHandle c ;
52 {
53   return 1;
54 }
55
56 void CmiReleaseCommHandle(c)
57 CmiCommHandle c ;
58 {
59 }
60
61 /********************* CONTEXT-SWITCHING FUNCTIONS ******************/
62
63 static void CmiNext()
64 {
65   CthThread t; int index; int orig;
66   index = (CmiMyPe()+1) % CmiNumPes();
67   orig = index;
68   while (1) {
69     t = CmiThreads[index];
70     if ((t)&&(!CmiBarred[index])) break;
71     index = (index+1) % CmiNumPes();
72     if (index == orig) exit(0);
73   }
74   _Cmi_mype = index;
75   CthResume(t);
76 }
77
78 void CmiExit()
79 {
80   CmiThreads[CmiMyPe()] = 0;
81   CmiFree(CthSelf());
82   CmiNext();
83 }
84
85 void *CmiGetNonLocal()
86 {
87   CmiThreads[CmiMyPe()] = CthSelf();
88   CmiNext();
89   return 0;
90 }
91
92 void CmiNotifyIdle()
93 {
94   CmiThreads[CmiMyPe()] = CthSelf();
95   CmiNext();
96 }
97
98 void CmiNodeBarrier()
99 {
100   int i;
101   CmiNumBarred++;
102   CmiBarred[CmiMyPe()] = 1;
103   if (CmiNumBarred == CmiNumPes()) {
104     for (i=0; i<CmiNumPes(); i++) CmiBarred[i]=0;
105     CmiNumBarred=0;
106   }
107   CmiGetNonLocal();
108 }
109
110 void CmiNodeAllBarrier()
111 {
112   int i;
113   CmiNumBarred++;
114   CmiBarred[CmiMyPe()] = 1;
115   if (CmiNumBarred == CmiNumPes()) {
116     for (i=0; i<CmiNumPes(); i++) CmiBarred[i]=0;
117     CmiNumBarred=0;
118   }
119   CmiGetNonLocal();
120 }
121
122 CmiNodeLock CmiCreateLock()
123 {
124   CmiNodeLock lk = (CmiNodeLock)malloc(sizeof(int));
125   *lk = 0;
126   return lk;
127 }
128
129 void CmiLock(CmiNodeLock lk)
130 {
131   while (*lk) CmiGetNonLocal();
132   *lk = 1;
133 }
134
135 void CmiUnlock(CmiNodeLock lk)
136 {
137   if (*lk==0) {
138     CmiError("CmiNodeLock not locked, can't unlock.");
139     exit(1);
140   }
141   *lk = 0;
142 }
143
144 int CmiTryLock(CmiNodeLock lk)
145 {
146   if (*lk==0) { *lk=1; return 0; }
147   return -1;
148 }
149
150 void CmiDestroyLock(CmiNodeLock lk)
151 {
152   free(lk);
153 }
154
155
156
157 /********************* MESSAGE SEND FUNCTIONS ******************/
158
159 void CmiSyncSendFn(destPE, size, msg)
160 int destPE;
161 int size;
162 char * msg;
163 {
164   char *buf = (char *)CmiAlloc(size);
165   memcpy(buf,msg,size);
166   CdsFifo_Enqueue(CmiQueues[destPE],buf);
167   CQdCreate(CpvAccess(cQdState), 1);
168 }
169
170 CmiCommHandle CmiAsyncSendFn(destPE, size, msg) 
171 int destPE;
172 int size;
173 char * msg;
174 {
175   char *buf = (char *)CmiAlloc(size);
176   memcpy(buf,msg,size);
177   CdsFifo_Enqueue(CmiQueues[destPE],buf);
178   CQdCreate(CpvAccess(cQdState), 1);
179   return 0;
180 }
181
182 void CmiFreeSendFn(destPE, size, msg)
183 int destPE;
184 int size;
185 char * msg;
186 {
187   CdsFifo_Enqueue(CmiQueues[destPE], msg);
188   CQdCreate(CpvAccess(cQdState), 1);
189 }
190
191 void CmiSyncBroadcastFn(size, msg)
192 int size;
193 char * msg;
194 {
195   int i;
196   for(i=0; i<CmiNumPes(); i++)
197     if (i != CmiMyPe()) CmiSyncSendFn(i,size,msg);
198 }
199
200 CmiCommHandle CmiAsyncBroadcastFn(size, msg)
201 int size;
202 char * msg;
203 {
204   CmiSyncBroadcastFn(size, msg);
205   return 0;
206 }
207
208 void CmiFreeBroadcastFn(size, msg)
209 int size;
210 char * msg;
211 {
212   CmiSyncBroadcastFn(size, msg);
213   CmiFree(msg);
214 }
215
216 void CmiSyncBroadcastAllFn(size, msg)
217 int size;
218 char * msg;
219 {
220   int i;
221   for(i=0; i<CmiNumPes(); i++)
222     CmiSyncSendFn(i,size,msg);
223 }
224
225 CmiCommHandle CmiAsyncBroadcastAllFn(size, msg)
226 int size;
227 char * msg;
228 {
229   CmiSyncBroadcastAllFn(size,msg);
230   return 0 ;
231 }
232
233 void CmiFreeBroadcastAllFn(size, msg)
234 int size;
235 char * msg;
236 {
237   int i;
238   for(i=0; i<CmiNumPes(); i++)
239     if (i!=CmiMyPe()) CmiSyncSendFn(i,size,msg);
240   CdsFifo_Enqueue(CpvAccess(CmiLocalQueue),msg);
241   CQdCreate(CpvAccess(cQdState), 1);
242 }
243
244
245 int CmiBarrier()
246 {
247   return -1;
248 }
249
250 int CmiBarrierZero()
251 {
252   return -1;
253 }
254
255 /************************** SETUP ***********************************/
256
257 static void CmiParseArgs(argv)
258 char **argv;
259 {
260   CmiGetArgInt(argv,"++stacksize",&Cmi_stacksize);
261   _Cmi_numpes=1;
262   CmiGetArgInt(argv,"+p",&_Cmi_numpes);
263   if (CmiNumPes()<1) {
264     printf("Error: must specify number of processors to simulate with +pXXX\n",CmiNumPes());
265     exit(1);
266   }
267 }
268
269 char **CmiInitPE()
270 {
271   int argc; char **argv;
272   argv = CmiCopyArgs(CmiArgv);
273   CpvAccess(CmiLocalQueue) = CmiQueues[CmiMyPe()];
274   CmiTimerInit(argv);
275   ConverseCommonInit(argv);
276   CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,CmiNotifyIdle,NULL);
277   return argv;
278 }
279
280 void CmiCallMain()
281 {
282   char **argv;
283   argv = CmiInitPE();
284   CmiStart(CmiGetArgc(argv), argv);
285   if (CmiUsched==0) CsdScheduler(-1);
286   ConverseExit();
287 }
288
289 void ConverseExit()
290 {
291   ConverseCommonExit();
292   CmiThreads[CmiMyPe()] = 0;
293   CmiNext();
294 }
295
296 #if CMK_CONDS_USE_SPECIAL_CODE
297 static int CmiSwitchToPEFn(int newpe)
298 {
299   int oldpe = _Cmi_mype;
300   if (newpe == CcdIGNOREPE) return CcdIGNOREPE;
301   _Cmi_mype = newpe;
302   return oldpe;
303 }
304 #endif
305
306
307 void ConverseInit(argc,argv,fn,usched,initret)
308 int argc;
309 char **argv;
310 CmiStartFn fn;
311 int usched, initret;
312 {
313   CthThread t; int stacksize, i;
314   
315 #if CMK_USE_HP_MAIN_FIX
316 #if FOR_CPLUS
317   _main(argc,argv);
318 #endif
319 #endif
320   
321   CmiSwitchToPE = CmiSwitchToPEFn;
322
323   CmiArgv = CmiCopyArgs(argv);
324   CmiStart = fn;
325   CmiUsched = usched;
326   CmiParseArgs(CmiArgv);
327   CthInit(CmiArgv);
328   CpvInitialize(void*, CmiLocalQueue);
329   CmiThreads = (CthThread *)CmiAlloc(CmiNumPes()*sizeof(CthThread));
330   CmiBarred  = (int       *)CmiAlloc(CmiNumPes()*sizeof(int));
331   CmiQueues  = (void**)CmiAlloc(CmiNumPes()*sizeof(void*));
332   
333   _smp_mutex = CmiCreateLock();
334
335   /* Create threads for all PE except PE 0 */
336   for(i=0; i<CmiNumPes(); i++) {
337     t = (i==0) ? CthSelf() : CthCreate(CmiCallMain, 0, Cmi_stacksize);
338     CmiThreads[i] = t;
339     CmiBarred[i] = 0;
340     CmiQueues[i] = CdsFifo_Create();
341   }
342   _Cmi_mype = 0;
343   argv = CmiInitPE();
344   if (initret==0) {
345     fn(CmiGetArgc(argv), argv);
346     if (usched==0) CsdScheduler(-1);
347     ConverseExit();
348   }
349 }
350
351 /*@}*/