comparison 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
comparison
equal deleted inserted replaced
24:210b8fcbd03f 25:e987f33b9210
123 { 123 {
124 return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, thdID, 124 return VSs__create_thread_w_ID_and_affinity( fnPtr, initData, thdID,
125 ANY_CORE, creatingThd ); 125 ANY_CORE, creatingThd );
126 } 126 }
127 127
128 /* old version -- looks safe to delete
129 SlaveVP *
130 VSs__create_slave_with_affinity( TopLevelFnPtr fnPtr, void *initData,
131 SlaveVP *creatingSlv, int32 coreToAssignOnto )
132 { VSsLangReq reqData;
133
134 //the lang request data is on the stack and disappears when this
135 // call returns -- it's guaranteed to remain in the VP's stack for as
136 // long as the VP is suspended.
137 reqData.reqType = create_slave_w_aff; //not used, May 2012
138 reqData.coreToAssignOnto = coreToAssignOnto;
139 reqData.fnPtr = fnPtr;
140 reqData.initData = initData;
141 reqData.callingSlv = creatingSlv;
142
143 PR_WL__send_create_slaveVP_req( &reqData, creatingSlv, VSs_MAGIC_NUMBER );
144
145 return creatingSlv->dataRetFromReq;
146 }
147 */
148 128
149 129
150 SlaveVP * 130 SlaveVP *
151 VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData, 131 VSs__create_thread_w_ID_and_affinity( TopLevelFnPtr fnPtr, void *initData,
152 int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd ) 132 int32 *thdID, int32 coreToAssignOnto, SlaveVP *creatingThd )
158 reqData.reqType = create_slave; //know type because in a PR create req 138 reqData.reqType = create_slave; //know type because in a PR create req
159 reqData.coreToAssignOnto = coreToAssignOnto; 139 reqData.coreToAssignOnto = coreToAssignOnto;
160 reqData.fnPtr = fnPtr; 140 reqData.fnPtr = fnPtr;
161 reqData.initData = initData; 141 reqData.initData = initData;
162 142
163 PR_WL__send_create_slaveVP_req( &reqData, thdID, (CreateHandler)&handleCreateThd, 143 PR_WL__send_create_slaveVP_req( &reqData, thdID, (CreateHandler)&VSs__handleCreateThd,
164 creatingThd, VSs_MAGIC_NUMBER ); 144 creatingThd, VSs_MAGIC_NUMBER );
165 return (SlaveVP *)creatingThd->dataRetFromReq; 145 return (SlaveVP *)creatingThd->dataRetFromReq;
166 } 146 }
167 147
168 /*This is always the last thing done in the code animated by a thread VP. 148 /*This is always the last thing done in the code animated by a thread VP.
174 */ 154 */
175 void 155 void
176 VSs__end_thread( SlaveVP *thdToEnd ) 156 VSs__end_thread( SlaveVP *thdToEnd )
177 { 157 {
178 //the lang request is null for VSs version of end slave 158 //the lang request is null for VSs version of end slave
179 PR_WL__send_end_slave_req( NULL, (RequestHandler)&handleDissipate, thdToEnd, 159 PR_WL__send_end_slave_req( NULL, (RequestHandler)&VSs__handleDissipate, thdToEnd,
180 VSs_MAGIC_NUMBER ); 160 VSs_MAGIC_NUMBER );
181 } 161 }
182 162
183 163
184 164
200 180
201 //Create task is a special form, so have to pass as parameters, the 181 //Create task is a special form, so have to pass as parameters, the
202 // top-level-fn of task and the data for that fn, plus lang's req, 182 // top-level-fn of task and the data for that fn, plus lang's req,
203 // animating slave, and lang's magic number 183 // animating slave, and lang's magic number
204 PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID, 184 PR_WL__send_create_task_req( taskType->fn, args, &reqData, NO_ID,
205 &handleSubmitTask, animSlv, VSs_MAGIC_NUMBER ); 185 &VSs__handleSubmitTask, animSlv, VSs_MAGIC_NUMBER );
206 } 186 }
207 187
208 void 188 void
209 VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID, 189 VSs__submit_task_with_ID( VSsTaskType *taskType, void *args, int32 *taskID,
210 SlaveVP *animSlv ) 190 SlaveVP *animSlv )
211 { VSsLangReq reqData; 191 { VSsLangReq reqData;
212 192
213 reqData.reqType = submit_task; 193 reqData.reqType = submit_task;
214 194
215 reqData.taskType = taskType; 195 reqData.taskType = taskType; //VSs info about args, dependencies, etc
216 reqData.args = args; 196 reqData.args = args;
217 reqData.callingSlv = animSlv; 197 reqData.callingSlv = animSlv;
218 198
219 PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID, 199 PR_WL__send_create_task_req( taskType->fn, args, &reqData, taskID,
220 &handleSubmitTask, animSlv, VSs_MAGIC_NUMBER ); 200 &VSs__handleSubmitTask, animSlv, VSs_MAGIC_NUMBER );
221 } 201 }
222 202
223 203
224 /*This call is the last to happen in every task. It causes the slave to 204 /*This call is the last to happen in every task. It causes the slave to
225 * suspend and get the next task out of the task-queue. Notice there is no 205 * suspend and get the next task out of the task-queue. Notice there is no
241 void 221 void
242 VSs__end_task( SlaveVP *animSlv ) 222 VSs__end_task( SlaveVP *animSlv )
243 { VSsLangReq reqData; 223 { VSsLangReq reqData;
244 224
245 //VSs has nothing extra to communicate to end task handler, so lang req is NULL 225 //VSs has nothing extra to communicate to end task handler, so lang req is NULL
246 PR_WL__send_end_task_request( NULL, &handleEndTask, animSlv, VSs_MAGIC_NUMBER ); 226 PR_WL__send_end_task_request( NULL, &VSs__handleEndTask, animSlv, VSs_MAGIC_NUMBER );
247 } 227 }
248 228
249 229
250 /*Waits for all tasks that are direct children to end, then resumes calling 230 /*Waits for all tasks that are direct children to end, then resumes calling
251 * task or thread 231 * task or thread
256 VSsLangReq reqData; 236 VSsLangReq reqData;
257 237
258 reqData.reqType = taskwait; 238 reqData.reqType = taskwait;
259 reqData.callingSlv = animSlv; 239 reqData.callingSlv = animSlv;
260 240
261 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleTaskwait, animSlv, 241 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleTaskwait, animSlv,
262 VSs_MAGIC_NUMBER ); 242 VSs_MAGIC_NUMBER );
263 } 243 }
264 244
265 245 void
246 VSs__wait_for_all_VSs_created_work_to_end( SlaveVP *seedSlv )
247 {
248 VSsLangReq reqData;
249
250 reqData.reqType = activity_cease_wait;
251 reqData.callingSlv = seedSlv;
252
253 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleWaitForVSsWorkToEnd, seedSlv,
254 VSs_MAGIC_NUMBER );
255 }
256
257
258
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 }
266 269
267 //========================== send and receive ============================ 270 //========================== send and receive ============================
268 // 271 //
269 272
270 inline 273 inline
271 int32 * 274 int32 *
272 VSs__give_self_taskID( SlaveVP *animSlv ) 275 VSs__give_self_taskID( SlaveVP *animSlv )
273 { 276 { void *metaTask;
274 return PR__give_ID_from_slave( animSlv, VSs_MAGIC_NUMBER ); 277 metaTask = PR_WL__give_lang_meta_task_from_slave( animSlv, VSs_MAGIC_NUMBER );
278 return PR__give_ID_from_lang_meta_task( metaTask );
275 } 279 }
276 280
277 //================================ send =================================== 281 //================================ send ===================================
278 282
279 void 283 void
288 reqData.receiverID = receiverID; 292 reqData.receiverID = receiverID;
289 reqData.senderSlv = senderSlv; 293 reqData.senderSlv = senderSlv;
290 294
291 reqData.nextReqInHashEntry = NULL; 295 reqData.nextReqInHashEntry = NULL;
292 296
293 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleSendTypeTo, 297 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleSendTypeTo,
294 senderSlv, VSs_MAGIC_NUMBER ); 298 senderSlv, VSs_MAGIC_NUMBER );
295 299
296 //When come back from suspend, no longer own data reachable from msg 300 //When come back from suspend, no longer own data reachable from msg
297 } 301 }
298 302
307 reqData.receiverID = receiverID; 311 reqData.receiverID = receiverID;
308 reqData.senderSlv = senderSlv; 312 reqData.senderSlv = senderSlv;
309 313
310 reqData.nextReqInHashEntry = NULL; 314 reqData.nextReqInHashEntry = NULL;
311 315
312 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleSendFromTo, 316 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleSendFromTo,
313 senderSlv, VSs_MAGIC_NUMBER ); 317 senderSlv, VSs_MAGIC_NUMBER );
314 } 318 }
315 319
316 320
317 //================================ receive ================================ 321 //================================ receive ================================
333 reqData.receiverID = receiverID; 337 reqData.receiverID = receiverID;
334 reqData.receiverSlv = receiverSlv; 338 reqData.receiverSlv = receiverSlv;
335 339
336 reqData.nextReqInHashEntry = NULL; 340 reqData.nextReqInHashEntry = NULL;
337 341
338 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleReceiveTypeTo, 342 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleReceiveTypeTo,
339 receiverSlv, VSs_MAGIC_NUMBER ); 343 receiverSlv, VSs_MAGIC_NUMBER );
340 344
341 return receiverSlv->dataRetFromReq; 345 return receiverSlv->dataRetFromReq;
342 } 346 }
343 347
359 reqData.receiverSlv = receiverSlv; 363 reqData.receiverSlv = receiverSlv;
360 364
361 reqData.nextReqInHashEntry = NULL; 365 reqData.nextReqInHashEntry = NULL;
362 DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]); 366 DEBUG__printf2(dbgRqstHdlr,"WL: receive from %d to: %d", reqData.senderID[1], reqData.receiverID[1]);
363 367
364 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleReceiveFromTo, 368 PR_WL__send_lang_request( &reqData, (RequestHandler)&VSs__handleReceiveFromTo,
365 receiverSlv, VSs_MAGIC_NUMBER ); 369 receiverSlv, VSs_MAGIC_NUMBER );
366 370
367 return receiverSlv->dataRetFromReq; 371 return receiverSlv->dataRetFromReq;
368 } 372 }
369 373
370 374
371 375
372 376
373 //========================================================================== 377
374 //
375 /*A function singleton is a function whose body executes exactly once, on a
376 * single core, no matter how many times the fuction is called and no
377 * matter how many cores or the timing of cores calling it.
378 *
379 *A data singleton is a ticket attached to data. That ticket can be used
380 * to get the data through the function exactly once, no matter how many
381 * times the data is given to the function, and no matter the timing of
382 * trying to get the data through from different cores.
383 */
384
385 /*asm function declarations*/
386 void asm_save_ret_to_singleton(VSsSingleton *singletonPtrAddr);
387 void asm_write_ret_from_singleton(VSsSingleton *singletonPtrAddr);
388
389 /*Fn singleton uses ID as index into array of singleton structs held in the
390 * language environment.
391 */
392 void
393 VSs__start_fn_singleton( int32 singletonID, SlaveVP *animSlv )
394 {
395 VSsLangReq reqData;
396
397 //
398 reqData.reqType = singleton_fn_start;
399 reqData.singletonID = singletonID;
400
401 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleStartFnSingleton,
402 animSlv, VSs_MAGIC_NUMBER );
403 if( animSlv->dataRetFromReq ) //will be 0 or addr of label in end singleton
404 {
405 VSsLangEnv *langEnv =
406 PR_int__give_lang_env_for_slave( animSlv, VSs_MAGIC_NUMBER );
407 asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID]));
408 }
409 }
410
411 /*Data singleton hands addr of loc holding a pointer to a singleton struct.
412 * The start_data_singleton makes the structure and puts its addr into the
413 * location.
414 */
415 void
416 VSs__start_data_singleton( VSsSingleton **singletonAddr, SlaveVP *animSlv )
417 {
418 VSsLangReq reqData;
419
420 if( *singletonAddr && (*singletonAddr)->hasFinished )
421 goto JmpToEndSingleton;
422
423 reqData.reqType = singleton_data_start;
424 reqData.singletonPtrAddr = singletonAddr;
425
426 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleStartDataSingleton,
427 animSlv, VSs_MAGIC_NUMBER );
428 if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr
429 { //Assembly code changes the return addr on the stack to the one
430 // saved into the singleton by the end-singleton-fn
431 //The return addr is at 0x4(%%ebp)
432 JmpToEndSingleton:
433 asm_write_ret_from_singleton(*singletonAddr);
434 }
435 //now, simply return
436 //will exit either from the start singleton call or the end-singleton call
437 }
438
439 /*Uses ID as index into array of flags. If flag already set, resumes from
440 * end-label. Else, sets flag and resumes normally.
441 *
442 *Note, this call cannot be inlined because the instr addr at the label
443 * inside is shared by all invocations of a given singleton ID.
444 */
445 void
446 VSs__end_fn_singleton( int32 singletonID, SlaveVP *animSlv )
447 {
448 VSsLangReq reqData;
449
450 //don't need this addr until after at least one singleton has reached
451 // this function
452 VSsLangEnv *
453 langEnv = PR_int__give_lang_env_for_slave( animSlv, VSs_MAGIC_NUMBER );
454
455 asm_write_ret_from_singleton(&(langEnv->fnSingletons[ singletonID]));
456
457 reqData.reqType = singleton_fn_end;
458 reqData.singletonID = singletonID;
459
460 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleEndFnSingleton,
461 animSlv, VSs_MAGIC_NUMBER );
462
463 EndSingletonInstrAddr:
464 return;
465 }
466
467 void
468 VSs__end_data_singleton( VSsSingleton **singletonPtrAddr, SlaveVP *animSlv )
469 {
470 VSsLangReq reqData;
471
472 //don't need this addr until after singleton struct has reached
473 // this function for first time
474 //do assembly that saves the return addr of this fn call into the
475 // data singleton -- that data-singleton can only be given to exactly
476 // one instance in the code of this function. However, can use this
477 // function in different places for different data-singletons.
478 asm_save_ret_to_singleton(*singletonPtrAddr);
479
480 reqData.reqType = singleton_data_end;
481 reqData.singletonPtrAddr = singletonPtrAddr;
482
483 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleEndDataSingleton,
484 animSlv, VSs_MAGIC_NUMBER );
485 }
486
487 /*This executes the function in the masterVP, so it executes in isolation
488 * from any other copies -- only one copy of the function can ever execute
489 * at a time.
490 *
491 *It suspends to the master, and the request handler takes the function
492 * pointer out of the request and calls it, then resumes the VP.
493 *Only very short functions should be called this way -- for longer-running
494 * isolation, use transaction-start and transaction-end, which run the code
495 * between as work-code.
496 */
497 void
498 VSs__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
499 void *data, SlaveVP *animSlv )
500 {
501 VSsLangReq reqData;
502
503 //
504 reqData.reqType = atomic;
505 reqData.fnToExecInMaster = ptrToFnToExecInMaster;
506 reqData.dataForFn = data;
507
508 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleAtomic,
509 animSlv, VSs_MAGIC_NUMBER );
510 }
511
512
513 /*This suspends to the master.
514 *First, it looks at the VP's data, to see the highest transactionID that VP
515 * already has entered. If the current ID is not larger, it throws an
516 * exception stating a bug in the code. Otherwise it puts the current ID
517 * there, and adds the ID to a linked list of IDs entered -- the list is
518 * used to check that exits are properly ordered.
519 *Next it is uses transactionID as index into an array of transaction
520 * structures.
521 *If the "VP_currently_executing" field is non-null, then put requesting VP
522 * into queue in the struct. (At some point a holder will request
523 * end-transaction, which will take this VP from the queue and resume it.)
524 *If NULL, then write requesting into the field and resume.
525 */
526 void
527 VSs__start_transaction( int32 transactionID, SlaveVP *animSlv )
528 {
529 VSsLangReq reqData;
530
531 //
532 reqData.callingSlv = animSlv;
533 reqData.reqType = trans_start;
534 reqData.transID = transactionID;
535
536 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleTransStart,
537 animSlv, VSs_MAGIC_NUMBER );
538 }
539
540 /*This suspends to the master, then uses transactionID as index into an
541 * array of transaction structures.
542 *It looks at VP_currently_executing to be sure it's same as requesting VP.
543 * If different, throws an exception, stating there's a bug in the code.
544 *Next it looks at the queue in the structure.
545 *If it's empty, it sets VP_currently_executing field to NULL and resumes.
546 *If something in, gets it, sets VP_currently_executing to that VP, then
547 * resumes both.
548 */
549 void
550 VSs__end_transaction( int32 transactionID, SlaveVP *animSlv )
551 {
552 VSsLangReq reqData;
553
554 //
555 reqData.callingSlv = animSlv;
556 reqData.reqType = trans_end;
557 reqData.transID = transactionID;
558
559 PR_WL__send_lang_request( &reqData, (RequestHandler)&handleTransEnd,
560 animSlv, VSs_MAGIC_NUMBER );
561 }
562
563 //======================== Internal ==================================
564