Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VSs_impls > VSs__MC_shared_impl
view VSs.c @ 30:a40859b8dc33
ML_dev -- compiles and runs, may still have shutdown issues
| author | Sean Halle <seanhalle@yahoo.com> |
|---|---|
| date | Sat, 02 Mar 2013 10:07:58 -0800 |
| parents | dd1efbf29ff9 |
| children | 0162554f6ef5 |
line source
1 /*
2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
3 *
4 * Licensed under BSD
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <malloc.h>
11 #include "Queue_impl/PrivateQueue.h"
12 #include "Hash_impl/PrivateHash.h"
14 #include "VSs.h"
15 #include "PR_impl/Services_Offered_by_PR/Measurement_and_Stats/PR_MEAS__Counter_Recording.h"
16 //==========================================================================
17 void
18 VSs__init_Helper();
20 SlaveVP *
21 VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData,
22 int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd );
24 //==========================================================================
28 //===========================================================================
31 /*These are the library functions *called in the application*
32 *
33 *There's a pattern for the outside sequential code to interact with the
34 * PR_HW code.
35 *The PR_HW system is inside a boundary.. every VSs system is in its
36 * own directory that contains the functions for each of the processor types.
37 * One of the processor types is the "seed" processor that starts the
38 * cascade of creating all the processors that do the work.
39 *So, in the directory is a file called "EntryPoint.c" that contains the
40 * function, named appropriately to the work performed, that the outside
41 * sequential code calls. This function follows a pattern:
42 *1) it calls VSs__init()
43 *2) it creates the initial data for the seed processor, which is passed
44 * in to the function
45 *3) it creates the seed VSs processor, with the data to start it with.
46 *4) it calls startVSsThenWaitUntilWorkDone
47 *5) it gets the returnValue from the transfer struc and returns that
48 * from the function
49 *
50 *For now, a new VSs system has to be created via VSs__init every
51 * time an entry point function is called -- later, might add letting the
52 * VSs system be created once, and let all the entry points just reuse
53 * it -- want to be as simple as possible now, and see by using what makes
54 * sense for later..
55 */
59 //===========================================================================
61 int32
62 VSs__giveMinWorkUnitCycles( float32 percentOverhead )
63 {
64 return MIN_WORK_UNIT_CYCLES;
65 }
67 int32
68 VSs__giveIdealNumWorkUnits()
69 {
70 return NUM_ANIM_SLOTS * NUM_CORES;
71 }
73 int32
74 VSs__give_number_of_cores_to_schedule_onto()
75 {
76 return NUM_CORES;
77 }
79 /*For now, use TSC -- later, make these two macros with assembly that first
80 * saves jump point, and second jumps back several times to get reliable time
81 */
82 void
83 VSs__begin_primitive( SlaveVP *animSlv )
84 { VSsLangData *langData;
86 langData = (VSsLangData *)PR_WL__give_lang_data( animSlv, VSs_MAGIC_NUMBER);
88 saveLowTimeStampCountInto( langData->primitiveStartTime );
89 }
91 /*Just quick and dirty for now -- make reliable later
92 * will want this to jump back several times -- to be sure cache is warm
93 * because don't want comm time included in calc-time measurement -- and
94 * also to throw out any "weird" values due to OS interrupt or TSC rollover
95 */
96 int32
97 VSs__end_primitive_and_give_cycles( SlaveVP *animSlv )
98 { int32 endTime, startTime;
99 VSsLangData *langData;
101 //TODO: fix by repeating time-measurement
102 saveLowTimeStampCountInto( endTime );
103 langData = (VSsLangData *)PR_WL__give_lang_data( animSlv, VSs_MAGIC_NUMBER);
104 startTime = langData->primitiveStartTime;
105 return (endTime - startTime);
106 }
110 //===========================================================================
112 SlaveVP *
113 VSs__create_thread( TopLevelFnPtr fnPtr, void *initData,
114 SlaveVP *creatingThd )
115 {
116 return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, NO_ID,
117 ANY_CORE, creatingThd );
118 }
120 SlaveVP *
121 VSs__create_thread_w_ID( TopLevelFnPtr fnPtr, void *initData, int32 *thdID,
122 SlaveVP *creatingThd )
123 {
124 return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, thdID,
125 ANY_CORE, creatingThd );
126 }
130 SlaveVP *
131 VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData,
132 int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd )
133 { VSsLangReq reqData;
135 //the lang request data is on the stack and disappears when this
136 // call returns -- it's guaranteed to remain in the VP's stack for as
137 // long as the VP is suspended.
138 reqData.reqType = create_slave; //know type because in a PR create req
139 reqData.coreToAssignOnto = coreToAssignOnto;
140 reqData.fnPtr = fnPtr;
141 reqData.initData = initData;
143 PR_WL__send_create_slaveVP_req( &reqData, thdID, (CreateHandler)&VSs__handleCreateThd,
144 creatingThd, VSs_MAGIC_NUMBER );
145 return (SlaveVP *)creatingThd->dataRetFromReq;
146 }
148 /*This is always the last thing done in the code animated by a thread VP.
149 * Normally, this would be the last line of the thread's top level function.
150 * But, if the thread exits from any point, it has to do so by calling
151 * this.
152 *
153 *It simply sends a dissipate request, which handles all the state cleanup.
154 */
155 void
156 VSs__end_thread( SlaveVP *thdToEnd )
157 {
158 //the lang request is null for VSs version of end slave
159 PR_WL__send_end_slave_req( NULL, (RequestHandler)&VSs__handleDissipate, thdToEnd,
160 VSs_MAGIC_NUMBER );
161 }
165 //===========================================================================
168 //======================= task submit and end ==============================
169 /*
170 */
171 void
172 VSs__submit_task( VSsTaskType *taskType, void *args, SlaveVP *animSlv)
173 { VSsLangReq reqData;
175 reqData.reqType = submit_task;
177 reqData.taskType = taskType;
178 reqData.args = args;
179 reqData.callingSlv = animSlv;
181 //Create task is a special form, so have to pass as parameters, the
182 // top-level-fn of task and the data for that fn, plus lang's req,
183 // animating slave, and lang's magic number
184 PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID,
185 &VSs__handleSubmitTask, animSlv, VSs_MAGIC_NUMBER );
186 }
188 void
189 VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID,
190 SlaveVP *animSlv )
191 { VSsLangReq reqData;
193 reqData.reqType = submit_task;
195 reqData.taskType = taskType; //VSs info about args, dependencies, etc
196 reqData.args = args;
197 reqData.callingSlv = animSlv;
199 PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID,
200 &VSs__handleSubmitTask, animSlv, VSs_MAGIC_NUMBER );
201 }
204 /*This call is the last to happen in every task. It causes the slave to
205 * suspend and get the next task out of the task-queue. Notice there is no
206 * assigner here.. only one slave, no slave ReadyQ, and so on..
207 *Can either make the assigner take the next task out of the taskQ, or can
208 * leave all as it is, and make task-end take the next task.
209 *Note: this fits the case in the new PR for no-context tasks, so will use
210 * the built-in taskQ of new PR, and should be local and much faster.
211 *
212 *The task-stub is saved in the animSlv, so the request handler will get it
213 * from there, along with the task-type which has arg types, and so on..
214 *
215 * NOTE: if want, don't need to send the animating SlaveVP around..
216 * instead, can make a single slave per core, and coreCtrlr looks up the
217 * slave from having the core number.
218 *
219 *But, to stay compatible with all the other PR languages, leave it in..
220 */
221 void
222 VSs__end_task( SlaveVP *animSlv )
223 { VSsLangReq reqData;
225 //VSs has nothing extra to communicate to end task handler, so lang req is NULL
226 PR_WL__send_end_task_request( NULL, &VSs__handleEndTask, animSlv, VSs_MAGIC_NUMBER );
227 }
230 /*Waits for all tasks that are direct children to end, then resumes calling
231 * task or thread
232 */
233 void
234 VSs__taskwait(SlaveVP *animSlv)
235 {
236 VSsLangReq reqData;
238 reqData.reqType = taskwait;
239 reqData.callingSlv = animSlv;
241 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleTaskwait, animSlv,
242 VSs_MAGIC_NUMBER );
243 }
245 void
246 VSs__wait_for_all_VSs_created_work_to_end( SlaveVP *seedSlv )
247 {
248 VSsLangReq reqData;
250 reqData.reqType = activity_cease_wait;
251 reqData.callingSlv = seedSlv;
253 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleWaitForVSsWorkToEnd, seedSlv,
254 VSs_MAGIC_NUMBER );
255 }
259 /*This is called by the application -- normally the seed slave. It causes a
260 * request to be sent that frees the VSs lang env and all its contents.
261 *The seed slave resumes from the built-in PRServ langlet's environment. It
262 * will be PRServ that causes return from this call.
263 */
264 void
265 VSs__shutdown( SlaveVP *seedSlv )
266 {
267 PR_WL__send_lang_shutdown_request( seedSlv, VSs_MAGIC_NUMBER );
268 }
270 //========================== send and receive ============================
271 //
273 inline
274 int32 *
275 VSs__give_self_taskID( SlaveVP *animSlv )
276 { void *metaTask;
277 metaTask = PR_WL__give_lang_meta_task_from_slave( animSlv, VSs_MAGIC_NUMBER );
278 return PR__give_ID_from_lang_meta_task( metaTask );
279 }
281 //================================ send ===================================
283 void
284 VSs__send_of_type_to( void *msg, const int32 type, int32 *receiverID,
285 SlaveVP *senderSlv )
286 { VSsLangReq reqData;
288 reqData.reqType = send_type_to;
290 reqData.msg = msg;
291 reqData.msgType = type;
292 reqData.receiverID = receiverID;
293 reqData.senderSlv = senderSlv;
295 reqData.nextReqInHashEntry = NULL;
297 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleSendTypeTo,
298 senderSlv, VSs_MAGIC_NUMBER );
300 //When come back from suspend, no longer own data reachable from msg
301 }
303 void
304 VSs__send_from_to( void *msg, int32 *senderID, int32 *receiverID, SlaveVP *senderSlv )
305 { VSsLangReq reqData;
307 reqData.reqType = send_from_to;
309 reqData.msg = msg;
310 reqData.senderID = senderID;
311 reqData.receiverID = receiverID;
312 reqData.senderSlv = senderSlv;
314 reqData.nextReqInHashEntry = NULL;
316 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleSendFromTo,
317 senderSlv, VSs_MAGIC_NUMBER );
318 }
321 //================================ receive ================================
323 /*The "type" version of send and receive creates a many-to-one relationship.
324 * The sender is anonymous, and many sends can stack up, waiting to be
325 * received. The same receiver can also have send from-to's
326 * waiting for it, and those will be kept separate from the "type"
327 * messages.
328 */
329 void *
330 VSs__receive_type_to( const int32 type, int32* receiverID, SlaveVP *receiverSlv )
331 { DEBUG__printf1(dbgRqstHdlr,"WL: receive type to %d",receiverID[1] );
332 VSsLangReq reqData;
334 reqData.reqType = receive_type_to;
336 reqData.msgType = type;
337 reqData.receiverID = receiverID;
338 reqData.receiverSlv = receiverSlv;
340 reqData.nextReqInHashEntry = NULL;
342 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleReceiveTypeTo,
343 receiverSlv, VSs_MAGIC_NUMBER );
345 return receiverSlv->dataRetFromReq;
346 }
350 /*Call this at the point a receiving task wants in-coming data.
351 * Use this from-to form when know senderID -- it makes a direct channel
352 * between sender and receiver.
353 */
354 void *
355 VSs__receive_from_to( int32 *senderID, int32 *receiverID, SlaveVP *receiverSlv )
356 {
357 VSsLangReq reqData;
359 reqData.reqType = receive_from_to;
361 reqData.senderID = senderID;
362 reqData.receiverID = receiverID;
363 reqData.receiverSlv = receiverSlv;
365 reqData.nextReqInHashEntry = NULL;
366 DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]);
368 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleReceiveFromTo,
369 receiverSlv, VSs_MAGIC_NUMBER );
371 return receiverSlv->dataRetFromReq;
372 }
