| rev |
line source |
|
seanhalle@0
|
1 /*
|
|
seanhalle@0
|
2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
|
|
seanhalle@0
|
3 *
|
|
seanhalle@0
|
4 * Licensed under BSD
|
|
seanhalle@0
|
5 */
|
|
seanhalle@0
|
6
|
|
seanhalle@0
|
7 #include <stdio.h>
|
|
seanhalle@0
|
8 #include <stdlib.h>
|
|
seanhalle@0
|
9 #include <malloc.h>
|
|
seanhalle@0
|
10
|
|
seanhalle@0
|
11 #include "Queue_impl/PrivateQueue.h"
|
|
seanhalle@0
|
12 #include "Hash_impl/PrivateHash.h"
|
|
seanhalle@0
|
13
|
|
seanhalle@2
|
14 #include "VSs.h"
|
|
seanhalle@3
|
15 #include "Measurement/VSs_Counter_Recording.h"
|
|
seanhalle@0
|
16
|
|
seanhalle@0
|
17 //==========================================================================
|
|
seanhalle@27
|
18 void
|
|
seanhalle@27
|
19 VSs__init_Helper();
|
|
seanhalle@27
|
20
|
|
seanhalle@27
|
21 SlaveVP *
|
|
seanhalle@27
|
22 VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@27
|
23 int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd );
|
|
seanhalle@0
|
24
|
|
seanhalle@0
|
25 //==========================================================================
|
|
seanhalle@0
|
26
|
|
seanhalle@0
|
27
|
|
seanhalle@0
|
28
|
|
seanhalle@0
|
29 //===========================================================================
|
|
seanhalle@0
|
30
|
|
seanhalle@0
|
31
|
|
seanhalle@0
|
32 /*These are the library functions *called in the application*
|
|
seanhalle@0
|
33 *
|
|
seanhalle@0
|
34 *There's a pattern for the outside sequential code to interact with the
|
|
seanhalle@26
|
35 * PR_HW code.
|
|
seanhalle@26
|
36 *The PR_HW system is inside a boundary.. every VSs system is in its
|
|
seanhalle@0
|
37 * own directory that contains the functions for each of the processor types.
|
|
seanhalle@0
|
38 * One of the processor types is the "seed" processor that starts the
|
|
seanhalle@0
|
39 * cascade of creating all the processors that do the work.
|
|
seanhalle@0
|
40 *So, in the directory is a file called "EntryPoint.c" that contains the
|
|
seanhalle@0
|
41 * function, named appropriately to the work performed, that the outside
|
|
seanhalle@0
|
42 * sequential code calls. This function follows a pattern:
|
|
seanhalle@2
|
43 *1) it calls VSs__init()
|
|
seanhalle@0
|
44 *2) it creates the initial data for the seed processor, which is passed
|
|
seanhalle@0
|
45 * in to the function
|
|
seanhalle@2
|
46 *3) it creates the seed VSs processor, with the data to start it with.
|
|
seanhalle@2
|
47 *4) it calls startVSsThenWaitUntilWorkDone
|
|
seanhalle@0
|
48 *5) it gets the returnValue from the transfer struc and returns that
|
|
seanhalle@0
|
49 * from the function
|
|
seanhalle@0
|
50 *
|
|
seanhalle@2
|
51 *For now, a new VSs system has to be created via VSs__init every
|
|
seanhalle@0
|
52 * time an entry point function is called -- later, might add letting the
|
|
seanhalle@2
|
53 * VSs system be created once, and let all the entry points just reuse
|
|
seanhalle@0
|
54 * it -- want to be as simple as possible now, and see by using what makes
|
|
seanhalle@0
|
55 * sense for later..
|
|
seanhalle@0
|
56 */
|
|
seanhalle@0
|
57
|
|
seanhalle@0
|
58
|
|
seanhalle@0
|
59
|
|
seanhalle@0
|
60 //===========================================================================
|
|
seanhalle@0
|
61
|
|
seanhalle@0
|
62 int32
|
|
seanhalle@2
|
63 VSs__giveMinWorkUnitCycles( float32 percentOverhead )
|
|
seanhalle@0
|
64 {
|
|
seanhalle@0
|
65 return MIN_WORK_UNIT_CYCLES;
|
|
seanhalle@0
|
66 }
|
|
seanhalle@0
|
67
|
|
seanhalle@0
|
68 int32
|
|
seanhalle@2
|
69 VSs__giveIdealNumWorkUnits()
|
|
seanhalle@0
|
70 {
|
|
seanhalle@0
|
71 return NUM_ANIM_SLOTS * NUM_CORES;
|
|
seanhalle@0
|
72 }
|
|
seanhalle@0
|
73
|
|
seanhalle@0
|
74 int32
|
|
seanhalle@2
|
75 VSs__give_number_of_cores_to_schedule_onto()
|
|
seanhalle@0
|
76 {
|
|
seanhalle@0
|
77 return NUM_CORES;
|
|
seanhalle@0
|
78 }
|
|
seanhalle@0
|
79
|
|
seanhalle@0
|
80 /*For now, use TSC -- later, make these two macros with assembly that first
|
|
seanhalle@0
|
81 * saves jump point, and second jumps back several times to get reliable time
|
|
seanhalle@0
|
82 */
|
|
seanhalle@0
|
83 void
|
|
seanhalle@27
|
84 VSs__begin_primitive( SlaveVP *animSlv )
|
|
seanhalle@27
|
85 { VSsLangData *langData;
|
|
seanhalle@26
|
86
|
|
seanhalle@27
|
87 langData = (VSsLangData *)PR_WL__give_lang_data( animSlv, VSs_MAGIC_NUMBER);
|
|
seanhalle@26
|
88
|
|
seanhalle@27
|
89 saveLowTimeStampCountInto( langData->primitiveStartTime );
|
|
seanhalle@0
|
90 }
|
|
seanhalle@0
|
91
|
|
seanhalle@0
|
92 /*Just quick and dirty for now -- make reliable later
|
|
seanhalle@0
|
93 * will want this to jump back several times -- to be sure cache is warm
|
|
seanhalle@0
|
94 * because don't want comm time included in calc-time measurement -- and
|
|
seanhalle@0
|
95 * also to throw out any "weird" values due to OS interrupt or TSC rollover
|
|
seanhalle@0
|
96 */
|
|
seanhalle@0
|
97 int32
|
|
seanhalle@27
|
98 VSs__end_primitive_and_give_cycles( SlaveVP *animSlv )
|
|
seanhalle@0
|
99 { int32 endTime, startTime;
|
|
seanhalle@27
|
100 VSsLangData *langData;
|
|
seanhalle@26
|
101
|
|
seanhalle@0
|
102 //TODO: fix by repeating time-measurement
|
|
seanhalle@0
|
103 saveLowTimeStampCountInto( endTime );
|
|
seanhalle@27
|
104 langData = (VSsLangData *)PR_WL__give_lang_data( animSlv, VSs_MAGIC_NUMBER);
|
|
seanhalle@27
|
105 startTime = langData->primitiveStartTime;
|
|
seanhalle@0
|
106 return (endTime - startTime);
|
|
seanhalle@0
|
107 }
|
|
seanhalle@0
|
108
|
|
seanhalle@26
|
109
|
|
seanhalle@0
|
110
|
|
seanhalle@0
|
111 //===========================================================================
|
|
seanhalle@0
|
112
|
|
seanhalle@2
|
113 SlaveVP *
|
|
seanhalle@7
|
114 VSs__create_thread( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@7
|
115 SlaveVP *creatingThd )
|
|
seanhalle@26
|
116 {
|
|
seanhalle@26
|
117 return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, NO_ID,
|
|
seanhalle@26
|
118 ANY_CORE, creatingThd );
|
|
seanhalle@26
|
119 }
|
|
seanhalle@26
|
120
|
|
seanhalle@26
|
121 SlaveVP *
|
|
seanhalle@26
|
122 VSs__create_thread_w_ID( TopLevelFnPtr fnPtr, void *initData, int32 *thdID,
|
|
seanhalle@26
|
123 SlaveVP *creatingThd )
|
|
seanhalle@26
|
124 {
|
|
seanhalle@26
|
125 return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, thdID,
|
|
seanhalle@26
|
126 ANY_CORE, creatingThd );
|
|
seanhalle@26
|
127 }
|
|
seanhalle@26
|
128
|
|
seanhalle@27
|
129 /* old version -- looks safe to delete
|
|
seanhalle@27
|
130 SlaveVP *
|
|
seanhalle@27
|
131 VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@27
|
132 SlaveVP *creatingSlv, int32 coreToAssignOnto )
|
|
seanhalle@27
|
133 { VSsLangReq reqData;
|
|
seanhalle@27
|
134
|
|
seanhalle@27
|
135 //the lang request data is on the stack and disappears when this
|
|
seanhalle@27
|
136 // call returns -- it's guaranteed to remain in the VP's stack for as
|
|
seanhalle@27
|
137 // long as the VP is suspended.
|
|
seanhalle@27
|
138 reqData.reqType = create_slave_w_aff; //not used, May 2012
|
|
seanhalle@27
|
139 reqData.coreToAssignOnto = coreToAssignOnto;
|
|
seanhalle@27
|
140 reqData.fnPtr = fnPtr;
|
|
seanhalle@27
|
141 reqData.initData = initData;
|
|
seanhalle@27
|
142 reqData.callingSlv = creatingSlv;
|
|
seanhalle@27
|
143
|
|
seanhalle@27
|
144 PR_WL__send_create_slaveVP_req( &reqData, creatingSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@27
|
145
|
|
seanhalle@27
|
146 return creatingSlv->dataRetFromReq;
|
|
seanhalle@27
|
147 }
|
|
seanhalle@27
|
148 */
|
|
seanhalle@27
|
149
|
|
seanhalle@26
|
150
|
|
seanhalle@26
|
151 SlaveVP *
|
|
seanhalle@26
|
152 VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@26
|
153 int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd )
|
|
seanhalle@27
|
154 { VSsLangReq reqData;
|
|
seanhalle@0
|
155
|
|
seanhalle@27
|
156 //the lang request data is on the stack and disappears when this
|
|
seanhalle@0
|
157 // call returns -- it's guaranteed to remain in the VP's stack for as
|
|
seanhalle@0
|
158 // long as the VP is suspended.
|
|
seanhalle@27
|
159 reqData.reqType = create_slave; //know type because in a PR create req
|
|
seanhalle@27
|
160 reqData.coreToAssignOnto = coreToAssignOnto;
|
|
seanhalle@27
|
161 reqData.fnPtr = fnPtr;
|
|
seanhalle@27
|
162 reqData.initData = initData;
|
|
seanhalle@26
|
163
|
|
seanhalle@27
|
164 PR_WL__send_create_slaveVP_req( &reqData, thdID, &handleCreateThd,
|
|
seanhalle@26
|
165 creatingThd, VSs_MAGIC_NUMBER );
|
|
seanhalle@27
|
166 return (SlaveVP *)creatingThd->dataRetFromReq;
|
|
seanhalle@0
|
167 }
|
|
seanhalle@0
|
168
|
|
seanhalle@10
|
169 /*This is always the last thing done in the code animated by a thread VP.
|
|
seanhalle@7
|
170 * Normally, this would be the last line of the thread's top level function.
|
|
seanhalle@7
|
171 * But, if the thread exits from any point, it has to do so by calling
|
|
seanhalle@7
|
172 * this.
|
|
seanhalle@10
|
173 *
|
|
seanhalle@10
|
174 *It simply sends a dissipate request, which handles all the state cleanup.
|
|
seanhalle@7
|
175 */
|
|
seanhalle@2
|
176 void
|
|
seanhalle@7
|
177 VSs__end_thread( SlaveVP *thdToEnd )
|
|
seanhalle@26
|
178 {
|
|
seanhalle@27
|
179 //the lang request is null for VSs version of end slave
|
|
seanhalle@27
|
180 PR_WL__send_end_slave_req( NULL, &handleDissipate, thdToEnd, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
181 }
|
|
seanhalle@0
|
182
|
|
seanhalle@0
|
183
|
|
seanhalle@10
|
184
|
|
seanhalle@0
|
185 //===========================================================================
|
|
seanhalle@0
|
186
|
|
seanhalle@0
|
187
|
|
seanhalle@4
|
188 //======================= task submit and end ==============================
|
|
seanhalle@4
|
189 /*
|
|
seanhalle@2
|
190 */
|
|
seanhalle@4
|
191 void
|
|
seanhalle@2
|
192 VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv)
|
|
seanhalle@27
|
193 { VSsLangReq reqData;
|
|
seanhalle@0
|
194
|
|
seanhalle@2
|
195 reqData.reqType = submit_task;
|
|
seanhalle@4
|
196
|
|
seanhalle@2
|
197 reqData.taskType = taskType;
|
|
seanhalle@2
|
198 reqData.args = args;
|
|
seanhalle@4
|
199 reqData.callingSlv = animSlv;
|
|
seanhalle@4
|
200
|
|
seanhalle@26
|
201 //Create task is a special form, so have to pass as parameters, the
|
|
seanhalle@26
|
202 // top-level-fn of task and the data for that fn, plus lang's req,
|
|
seanhalle@26
|
203 // animating slave, and lang's magic number
|
|
seanhalle@27
|
204 PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID,
|
|
seanhalle@27
|
205 &handleSubmitTask, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
206 }
|
|
seanhalle@4
|
207
|
|
seanhalle@4
|
208 void
|
|
seanhalle@4
|
209 VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID,
|
|
seanhalle@27
|
210 SlaveVP *animSlv )
|
|
seanhalle@27
|
211 { VSsLangReq reqData;
|
|
seanhalle@26
|
212
|
|
seanhalle@4
|
213 reqData.reqType = submit_task;
|
|
seanhalle@4
|
214
|
|
seanhalle@4
|
215 reqData.taskType = taskType;
|
|
seanhalle@4
|
216 reqData.args = args;
|
|
seanhalle@4
|
217 reqData.callingSlv = animSlv;
|
|
seanhalle@4
|
218
|
|
seanhalle@27
|
219 PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID,
|
|
seanhalle@27
|
220 &handleSubmitTask, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
221 }
|
|
seanhalle@4
|
222
|
|
seanhalle@4
|
223
|
|
seanhalle@4
|
224 /*This call is the last to happen in every task. It causes the slave to
|
|
seanhalle@2
|
225 * suspend and get the next task out of the task-queue. Notice there is no
|
|
seanhalle@2
|
226 * assigner here.. only one slave, no slave ReadyQ, and so on..
|
|
seanhalle@2
|
227 *Can either make the assigner take the next task out of the taskQ, or can
|
|
seanhalle@2
|
228 * leave all as it is, and make task-end take the next task.
|
|
seanhalle@26
|
229 *Note: this fits the case in the new PR for no-context tasks, so will use
|
|
seanhalle@26
|
230 * the built-in taskQ of new PR, and should be local and much faster.
|
|
seanhalle@2
|
231 *
|
|
seanhalle@2
|
232 *The task-stub is saved in the animSlv, so the request handler will get it
|
|
seanhalle@2
|
233 * from there, along with the task-type which has arg types, and so on..
|
|
seanhalle@4
|
234 *
|
|
seanhalle@4
|
235 * NOTE: if want, don't need to send the animating SlaveVP around..
|
|
seanhalle@4
|
236 * instead, can make a single slave per core, and coreCtrlr looks up the
|
|
seanhalle@4
|
237 * slave from having the core number.
|
|
seanhalle@4
|
238 *
|
|
seanhalle@26
|
239 *But, to stay compatible with all the other PR languages, leave it in..
|
|
seanhalle@0
|
240 */
|
|
seanhalle@0
|
241 void
|
|
seanhalle@2
|
242 VSs__end_task( SlaveVP *animSlv )
|
|
seanhalle@27
|
243 { VSsLangReq reqData;
|
|
seanhalle@2
|
244
|
|
seanhalle@27
|
245 //VSs has nothing extra to communicate to end task handler, so lang req is NULL
|
|
seanhalle@27
|
246 PR_WL__send_end_task_request( NULL, &handleEndTask, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
247 }
|
|
seanhalle@0
|
248
|
|
seanhalle@4
|
249
|
|
seanhalle@26
|
250 /*Waits for all tasks that are direct children to end, then resumes calling
|
|
seanhalle@26
|
251 * task or thread
|
|
seanhalle@26
|
252 */
|
|
nengel@5
|
253 void
|
|
nengel@5
|
254 VSs__taskwait(SlaveVP *animSlv)
|
|
seanhalle@26
|
255 {
|
|
seanhalle@27
|
256 VSsLangReq reqData;
|
|
nengel@5
|
257
|
|
nengel@5
|
258 reqData.reqType = taskwait;
|
|
nengel@5
|
259 reqData.callingSlv = animSlv;
|
|
nengel@5
|
260
|
|
seanhalle@27
|
261 PR_WL__send_lang_request( &reqData, &handleTaskwait, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@26
|
262 }
|
|
nengel@5
|
263
|
|
nengel@5
|
264
|
|
nengel@5
|
265
|
|
seanhalle@4
|
266 //========================== send and receive ============================
|
|
seanhalle@4
|
267 //
|
|
seanhalle@4
|
268
|
|
seanhalle@4
|
269 inline int32 *
|
|
seanhalle@4
|
270 VSs__give_self_taskID( SlaveVP *animSlv )
|
|
seanhalle@4
|
271 {
|
|
seanhalle@27
|
272 return PR__give_ID_from_slave( animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
273 }
|
|
seanhalle@4
|
274
|
|
seanhalle@4
|
275 //================================ send ===================================
|
|
seanhalle@4
|
276
|
|
seanhalle@4
|
277 void
|
|
seanhalle@4
|
278 VSs__send_of_type_to( void *msg, const int32 type, int32 *receiverID,
|
|
seanhalle@4
|
279 SlaveVP *senderSlv )
|
|
seanhalle@27
|
280 { VSsLangReq reqData;
|
|
seanhalle@4
|
281
|
|
seanhalle@4
|
282 reqData.reqType = send_type_to;
|
|
seanhalle@4
|
283
|
|
seanhalle@4
|
284 reqData.msg = msg;
|
|
seanhalle@4
|
285 reqData.msgType = type;
|
|
seanhalle@4
|
286 reqData.receiverID = receiverID;
|
|
seanhalle@4
|
287 reqData.senderSlv = senderSlv;
|
|
seanhalle@4
|
288
|
|
seanhalle@4
|
289 reqData.nextReqInHashEntry = NULL;
|
|
seanhalle@4
|
290
|
|
seanhalle@27
|
291 PR_WL__send_lang_request( &reqData, &handleSendTypeTo, senderSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
292
|
|
seanhalle@4
|
293 //When come back from suspend, no longer own data reachable from msg
|
|
seanhalle@4
|
294 }
|
|
seanhalle@4
|
295
|
|
seanhalle@4
|
296 void
|
|
seanhalle@4
|
297 VSs__send_from_to( void *msg, int32 *senderID, int32 *receiverID, SlaveVP *senderSlv )
|
|
seanhalle@27
|
298 { VSsLangReq reqData;
|
|
seanhalle@4
|
299
|
|
seanhalle@4
|
300 reqData.reqType = send_from_to;
|
|
seanhalle@4
|
301
|
|
seanhalle@4
|
302 reqData.msg = msg;
|
|
seanhalle@4
|
303 reqData.senderID = senderID;
|
|
seanhalle@4
|
304 reqData.receiverID = receiverID;
|
|
seanhalle@4
|
305 reqData.senderSlv = senderSlv;
|
|
seanhalle@4
|
306
|
|
seanhalle@4
|
307 reqData.nextReqInHashEntry = NULL;
|
|
seanhalle@4
|
308
|
|
seanhalle@27
|
309 PR_WL__send_lang_request( &reqData, &handleSendFromTo, senderSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
310 }
|
|
seanhalle@4
|
311
|
|
seanhalle@4
|
312
|
|
seanhalle@4
|
313 //================================ receive ================================
|
|
seanhalle@4
|
314
|
|
seanhalle@4
|
315 /*The "type" version of send and receive creates a many-to-one relationship.
|
|
seanhalle@4
|
316 * The sender is anonymous, and many sends can stack up, waiting to be
|
|
seanhalle@4
|
317 * received. The same receiver can also have send from-to's
|
|
seanhalle@4
|
318 * waiting for it, and those will be kept separate from the "type"
|
|
seanhalle@4
|
319 * messages.
|
|
seanhalle@4
|
320 */
|
|
seanhalle@4
|
321 void *
|
|
seanhalle@4
|
322 VSs__receive_type_to( const int32 type, int32* receiverID, SlaveVP *receiverSlv )
|
|
seanhalle@4
|
323 { DEBUG__printf1(dbgRqstHdlr,"WL: receive type to %d",receiverID[1] );
|
|
seanhalle@27
|
324 VSsLangReq reqData;
|
|
seanhalle@4
|
325
|
|
seanhalle@4
|
326 reqData.reqType = receive_type_to;
|
|
seanhalle@4
|
327
|
|
seanhalle@4
|
328 reqData.msgType = type;
|
|
seanhalle@4
|
329 reqData.receiverID = receiverID;
|
|
seanhalle@4
|
330 reqData.receiverSlv = receiverSlv;
|
|
seanhalle@4
|
331
|
|
seanhalle@4
|
332 reqData.nextReqInHashEntry = NULL;
|
|
seanhalle@4
|
333
|
|
seanhalle@27
|
334 PR_WL__send_lang_request( &reqData, &handleReceiveTypeTo, receiverSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
335
|
|
seanhalle@4
|
336 return receiverSlv->dataRetFromReq;
|
|
seanhalle@4
|
337 }
|
|
seanhalle@4
|
338
|
|
seanhalle@4
|
339
|
|
seanhalle@4
|
340
|
|
seanhalle@4
|
341 /*Call this at the point a receiving task wants in-coming data.
|
|
seanhalle@4
|
342 * Use this from-to form when know senderID -- it makes a direct channel
|
|
seanhalle@4
|
343 * between sender and receiver.
|
|
seanhalle@4
|
344 */
|
|
seanhalle@4
|
345 void *
|
|
seanhalle@4
|
346 VSs__receive_from_to( int32 *senderID, int32 *receiverID, SlaveVP *receiverSlv )
|
|
seanhalle@4
|
347 {
|
|
seanhalle@27
|
348 VSsLangReq reqData;
|
|
seanhalle@4
|
349
|
|
seanhalle@4
|
350 reqData.reqType = receive_from_to;
|
|
seanhalle@4
|
351
|
|
seanhalle@4
|
352 reqData.senderID = senderID;
|
|
seanhalle@4
|
353 reqData.receiverID = receiverID;
|
|
seanhalle@4
|
354 reqData.receiverSlv = receiverSlv;
|
|
seanhalle@4
|
355
|
|
seanhalle@4
|
356 reqData.nextReqInHashEntry = NULL;
|
|
seanhalle@4
|
357 DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]);
|
|
seanhalle@4
|
358
|
|
seanhalle@27
|
359 PR_WL__send_lang_request( &reqData, &handleReceiveFromTo, receiverSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@4
|
360
|
|
seanhalle@4
|
361 return receiverSlv->dataRetFromReq;
|
|
seanhalle@4
|
362 }
|
|
seanhalle@4
|
363
|
|
seanhalle@4
|
364
|
|
seanhalle@4
|
365
|
|
seanhalle@4
|
366
|
|
seanhalle@2
|
367 //==========================================================================
|
|
seanhalle@0
|
368 //
|
|
seanhalle@0
|
369 /*A function singleton is a function whose body executes exactly once, on a
|
|
seanhalle@0
|
370 * single core, no matter how many times the fuction is called and no
|
|
seanhalle@0
|
371 * matter how many cores or the timing of cores calling it.
|
|
seanhalle@0
|
372 *
|
|
seanhalle@0
|
373 *A data singleton is a ticket attached to data. That ticket can be used
|
|
seanhalle@0
|
374 * to get the data through the function exactly once, no matter how many
|
|
seanhalle@0
|
375 * times the data is given to the function, and no matter the timing of
|
|
seanhalle@0
|
376 * trying to get the data through from different cores.
|
|
seanhalle@0
|
377 */
|
|
seanhalle@0
|
378
|
|
seanhalle@0
|
379 /*asm function declarations*/
|
|
seanhalle@2
|
380 void asm_save_ret_to_singleton(VSsSingleton *singletonPtrAddr);
|
|
seanhalle@2
|
381 void asm_write_ret_from_singleton(VSsSingleton *singletonPtrAddr);
|
|
seanhalle@0
|
382
|
|
seanhalle@0
|
383 /*Fn singleton uses ID as index into array of singleton structs held in the
|
|
seanhalle@27
|
384 * language environment.
|
|
seanhalle@0
|
385 */
|
|
seanhalle@0
|
386 void
|
|
seanhalle@3
|
387 VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv )
|
|
seanhalle@0
|
388 {
|
|
seanhalle@27
|
389 VSsLangReq reqData;
|
|
seanhalle@0
|
390
|
|
seanhalle@0
|
391 //
|
|
seanhalle@0
|
392 reqData.reqType = singleton_fn_start;
|
|
seanhalle@0
|
393 reqData.singletonID = singletonID;
|
|
seanhalle@0
|
394
|
|
seanhalle@27
|
395 PR_WL__send_lang_request( &reqData, &handleStartFnSingleton, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@3
|
396 if( animSlv->dataRetFromReq ) //will be 0 or addr of label in end singleton
|
|
seanhalle@0
|
397 {
|
|
seanhalle@27
|
398 VSsLangEnv *langEnv =
|
|
seanhalle@27
|
399 PR_int__give_lang_env_for_slave__ML( animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@27
|
400 asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID]));
|
|
seanhalle@0
|
401 }
|
|
seanhalle@0
|
402 }
|
|
seanhalle@0
|
403
|
|
seanhalle@0
|
404 /*Data singleton hands addr of loc holding a pointer to a singleton struct.
|
|
seanhalle@0
|
405 * The start_data_singleton makes the structure and puts its addr into the
|
|
seanhalle@0
|
406 * location.
|
|
seanhalle@0
|
407 */
|
|
seanhalle@0
|
408 void
|
|
seanhalle@3
|
409 VSs__start_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv )
|
|
seanhalle@0
|
410 {
|
|
seanhalle@27
|
411 VSsLangReq reqData;
|
|
seanhalle@0
|
412
|
|
seanhalle@0
|
413 if( *singletonAddr && (*singletonAddr)->hasFinished )
|
|
seanhalle@0
|
414 goto JmpToEndSingleton;
|
|
seanhalle@0
|
415
|
|
seanhalle@0
|
416 reqData.reqType = singleton_data_start;
|
|
seanhalle@0
|
417 reqData.singletonPtrAddr = singletonAddr;
|
|
seanhalle@0
|
418
|
|
seanhalle@27
|
419 PR_WL__send_lang_request( &reqData, &handleStartDataSingleton, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@3
|
420 if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr
|
|
seanhalle@0
|
421 { //Assembly code changes the return addr on the stack to the one
|
|
seanhalle@0
|
422 // saved into the singleton by the end-singleton-fn
|
|
seanhalle@0
|
423 //The return addr is at 0x4(%%ebp)
|
|
seanhalle@0
|
424 JmpToEndSingleton:
|
|
seanhalle@0
|
425 asm_write_ret_from_singleton(*singletonAddr);
|
|
seanhalle@0
|
426 }
|
|
seanhalle@0
|
427 //now, simply return
|
|
seanhalle@0
|
428 //will exit either from the start singleton call or the end-singleton call
|
|
seanhalle@0
|
429 }
|
|
seanhalle@0
|
430
|
|
seanhalle@0
|
431 /*Uses ID as index into array of flags. If flag already set, resumes from
|
|
seanhalle@0
|
432 * end-label. Else, sets flag and resumes normally.
|
|
seanhalle@0
|
433 *
|
|
seanhalle@0
|
434 *Note, this call cannot be inlined because the instr addr at the label
|
|
seanhalle@0
|
435 * inside is shared by all invocations of a given singleton ID.
|
|
seanhalle@0
|
436 */
|
|
seanhalle@0
|
437 void
|
|
seanhalle@3
|
438 VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv )
|
|
seanhalle@0
|
439 {
|
|
seanhalle@27
|
440 VSsLangReq reqData;
|
|
seanhalle@0
|
441
|
|
seanhalle@0
|
442 //don't need this addr until after at least one singleton has reached
|
|
seanhalle@0
|
443 // this function
|
|
seanhalle@27
|
444 VSsLangEnv *
|
|
seanhalle@27
|
445 langEnv = PR_int__give_lang_env_for_slave__ML( animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@27
|
446
|
|
seanhalle@27
|
447 asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID]));
|
|
seanhalle@0
|
448
|
|
seanhalle@0
|
449 reqData.reqType = singleton_fn_end;
|
|
seanhalle@0
|
450 reqData.singletonID = singletonID;
|
|
seanhalle@0
|
451
|
|
seanhalle@27
|
452 PR_WL__send_lang_request( &reqData, &handleEndFnSingleton, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
453
|
|
seanhalle@0
|
454 EndSingletonInstrAddr:
|
|
seanhalle@0
|
455 return;
|
|
seanhalle@0
|
456 }
|
|
seanhalle@0
|
457
|
|
seanhalle@0
|
458 void
|
|
seanhalle@3
|
459 VSs__end_data_singleton( VSsSingleton **singletonPtrAddr, SlaveVP *animSlv )
|
|
seanhalle@0
|
460 {
|
|
seanhalle@27
|
461 VSsLangReq reqData;
|
|
seanhalle@0
|
462
|
|
seanhalle@0
|
463 //don't need this addr until after singleton struct has reached
|
|
seanhalle@0
|
464 // this function for first time
|
|
seanhalle@0
|
465 //do assembly that saves the return addr of this fn call into the
|
|
seanhalle@0
|
466 // data singleton -- that data-singleton can only be given to exactly
|
|
seanhalle@0
|
467 // one instance in the code of this function. However, can use this
|
|
seanhalle@0
|
468 // function in different places for different data-singletons.
|
|
seanhalle@0
|
469 asm_save_ret_to_singleton(*singletonPtrAddr);
|
|
seanhalle@0
|
470
|
|
seanhalle@0
|
471 reqData.reqType = singleton_data_end;
|
|
seanhalle@0
|
472 reqData.singletonPtrAddr = singletonPtrAddr;
|
|
seanhalle@0
|
473
|
|
seanhalle@27
|
474 PR_WL__send_lang_request( &reqData, &handleEndDataSingleton, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
475 }
|
|
seanhalle@0
|
476
|
|
seanhalle@0
|
477 /*This executes the function in the masterVP, so it executes in isolation
|
|
seanhalle@0
|
478 * from any other copies -- only one copy of the function can ever execute
|
|
seanhalle@0
|
479 * at a time.
|
|
seanhalle@0
|
480 *
|
|
seanhalle@0
|
481 *It suspends to the master, and the request handler takes the function
|
|
seanhalle@0
|
482 * pointer out of the request and calls it, then resumes the VP.
|
|
seanhalle@0
|
483 *Only very short functions should be called this way -- for longer-running
|
|
seanhalle@0
|
484 * isolation, use transaction-start and transaction-end, which run the code
|
|
seanhalle@0
|
485 * between as work-code.
|
|
seanhalle@0
|
486 */
|
|
seanhalle@0
|
487 void
|
|
seanhalle@2
|
488 VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
|
|
seanhalle@3
|
489 void *data, SlaveVP *animSlv )
|
|
seanhalle@0
|
490 {
|
|
seanhalle@27
|
491 VSsLangReq reqData;
|
|
seanhalle@0
|
492
|
|
seanhalle@0
|
493 //
|
|
seanhalle@0
|
494 reqData.reqType = atomic;
|
|
seanhalle@0
|
495 reqData.fnToExecInMaster = ptrToFnToExecInMaster;
|
|
seanhalle@0
|
496 reqData.dataForFn = data;
|
|
seanhalle@0
|
497
|
|
seanhalle@27
|
498 PR_WL__send_lang_request( &reqData, &handleAtomic, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
499 }
|
|
seanhalle@0
|
500
|
|
seanhalle@0
|
501
|
|
seanhalle@0
|
502 /*This suspends to the master.
|
|
seanhalle@0
|
503 *First, it looks at the VP's data, to see the highest transactionID that VP
|
|
seanhalle@0
|
504 * already has entered. If the current ID is not larger, it throws an
|
|
seanhalle@0
|
505 * exception stating a bug in the code. Otherwise it puts the current ID
|
|
seanhalle@0
|
506 * there, and adds the ID to a linked list of IDs entered -- the list is
|
|
seanhalle@0
|
507 * used to check that exits are properly ordered.
|
|
seanhalle@0
|
508 *Next it is uses transactionID as index into an array of transaction
|
|
seanhalle@0
|
509 * structures.
|
|
seanhalle@0
|
510 *If the "VP_currently_executing" field is non-null, then put requesting VP
|
|
seanhalle@0
|
511 * into queue in the struct. (At some point a holder will request
|
|
seanhalle@0
|
512 * end-transaction, which will take this VP from the queue and resume it.)
|
|
seanhalle@0
|
513 *If NULL, then write requesting into the field and resume.
|
|
seanhalle@0
|
514 */
|
|
seanhalle@0
|
515 void
|
|
seanhalle@3
|
516 VSs__start_transaction( int32 transactionID, SlaveVP *animSlv )
|
|
seanhalle@0
|
517 {
|
|
seanhalle@27
|
518 VSsLangReq reqData;
|
|
seanhalle@0
|
519
|
|
seanhalle@0
|
520 //
|
|
seanhalle@26
|
521 reqData.callingSlv = animSlv;
|
|
seanhalle@0
|
522 reqData.reqType = trans_start;
|
|
seanhalle@0
|
523 reqData.transID = transactionID;
|
|
seanhalle@0
|
524
|
|
seanhalle@27
|
525 PR_WL__send_lang_request( &reqData, &handleTransStart, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
526 }
|
|
seanhalle@0
|
527
|
|
seanhalle@0
|
528 /*This suspends to the master, then uses transactionID as index into an
|
|
seanhalle@0
|
529 * array of transaction structures.
|
|
seanhalle@0
|
530 *It looks at VP_currently_executing to be sure it's same as requesting VP.
|
|
seanhalle@0
|
531 * If different, throws an exception, stating there's a bug in the code.
|
|
seanhalle@0
|
532 *Next it looks at the queue in the structure.
|
|
seanhalle@0
|
533 *If it's empty, it sets VP_currently_executing field to NULL and resumes.
|
|
seanhalle@0
|
534 *If something in, gets it, sets VP_currently_executing to that VP, then
|
|
seanhalle@0
|
535 * resumes both.
|
|
seanhalle@0
|
536 */
|
|
seanhalle@0
|
537 void
|
|
seanhalle@3
|
538 VSs__end_transaction( int32 transactionID, SlaveVP *animSlv )
|
|
seanhalle@0
|
539 {
|
|
seanhalle@27
|
540 VSsLangReq reqData;
|
|
seanhalle@0
|
541
|
|
seanhalle@0
|
542 //
|
|
seanhalle@3
|
543 reqData.callingSlv = animSlv;
|
|
seanhalle@0
|
544 reqData.reqType = trans_end;
|
|
seanhalle@0
|
545 reqData.transID = transactionID;
|
|
seanhalle@0
|
546
|
|
seanhalle@27
|
547 PR_WL__send_lang_request( &reqData, &handleTransEnd, animSlv, VSs_MAGIC_NUMBER );
|
|
seanhalle@0
|
548 }
|
|
seanhalle@7
|
549
|
|
seanhalle@7
|
550 //======================== Internal ==================================
|
|
seanhalle@7
|
551
|