annotate VSs.c @ 29:dd1efbf29ff9

Moved counter recordings to PR services, about to delete trans & singleton
author Sean Halle <seanhalle@yahoo.com>
date Thu, 07 Feb 2013 16:30:16 -0800
parents 91caa8a9d591
children a40859b8dc33
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