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