annotate VSs.c @ 27:3b30da4643d1

Update2.. in middle of changes.. made request handler ptr be sent w/req struct
author Sean Halle <seanhalle@yahoo.com>
date Sat, 12 Jan 2013 11:31:51 -0800
parents a60399b62614
children 91caa8a9d591
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