Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VSs_impls > VSs__MC_shared_impl
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 |
