annotate CoreController.c @ 286:b02b34681414

VReo V2 -- saves checker and doer fn with the port, where triggered
author Sean Halle <seanhalle@yahoo.com>
date Wed, 10 Jul 2013 14:49:04 -0700
parents 1d7ea1b0f176
children
rev   line source
seanhalle@222 1 /*
seanhalle@268 2 * Copyright 2010 OpenSourceResearchInstitute
seanhalle@222 3 *
seanhalle@222 4 * Licensed under BSD
seanhalle@222 5 */
seanhalle@222 6
seanhalle@222 7
seanhalle@260 8 #include "PR.h"
seanhalle@222 9
seanhalle@222 10 #include <stdlib.h>
seanhalle@222 11 #include <stdio.h>
seanhalle@222 12 #include <time.h>
seanhalle@222 13
seanhalle@222 14 #include <pthread.h>
seanhalle@222 15 #include <sched.h>
seanhalle@222 16
seanhalle@222 17 //===================== Functions local to this file =======================
seanhalle@222 18 void *terminateCoreController(SlaveVP *currSlv);
seanhalle@230 19
seanhalle@222 20 inline void
seanhalle@222 21 doBackoff_for_TooLongToGetLock( int32 numTriesToGetLock, uint32 *seed1,
seanhalle@222 22 uint32 *seed2 );
seanhalle@222 23 inline void
seanhalle@222 24 doBackoff_for_TooLongWithNoWork( int32 numRepsWithNoWork, uint32 *seed1,
seanhalle@222 25 uint32 *seed2 );
seanhalle@222 26
seanhalle@222 27 //===========================================================================
seanhalle@222 28
seanhalle@222 29
seanhalle@222 30 /*The Core Controller is logically "beneath" the masterVP and slave VPs. Its
seanhalle@222 31 * job is to control which of those VPs the core animates. Any time one of
seanhalle@222 32 * those VPs suspends, the suspend-primitive switches the core over to
seanhalle@222 33 * animating the core controller. The core controller then follows a very
seanhalle@222 34 * basic pattern to choose which VP will get animated next, then switches
seanhalle@222 35 * the core over to animating that VP. So, all VPs switch the core to
seanhalle@222 36 * core controller, which then chooses which VP the core animates next.
seanhalle@222 37 *
seanhalle@222 38 *The way the core controller decides which VP to switch the core to next is:
seanhalle@230 39 * 1) There are a number of "animation slots", which the master VP fills up
seanhalle@222 40 * with slave VPs that are ready to be animated. So, the core controller
seanhalle@230 41 * just iterates through the animation slots. When the next slot has a
seanhalle@222 42 * slave VP in it, the core controller switches the core over to animate
seanhalle@222 43 * that slave.
seanhalle@230 44 * 2) When the core controller checks a animation slot, and it's empty,
seanhalle@222 45 * then the controller switches the core over to animating the master VP,
seanhalle@222 46 * whose job is to find more slave VPs ready, and assign those to
seanhalle@230 47 * animation slots.
seanhalle@222 48 *
seanhalle@230 49 *So, in effect, a animation slot functions as another layer of virtual
seanhalle@222 50 * processor. A slot has the logical meaning of being an animator that
seanhalle@222 51 * animates the slave assigned to it. However, the core controller sits
seanhalle@222 52 * below the slots, and sequences down them, assigning the actual physical
seanhalle@222 53 * core to each slot, in turn.
seanhalle@230 54 *The reason for having the animation slots and core controller is to
seanhalle@222 55 * amortize the overhead of switching to the master VP and running it. With
seanhalle@230 56 * multiple animation slots, the time to switch-to-master and the code in
seanhalle@232 57 * the animation master is divided by the number of animation slots.
seanhalle@260 58 *The core controller and animation slots are not fundamental parts of PR,
seanhalle@222 59 * but rather optimizations put into the shared-semantic-state version of
seanhalle@260 60 * PR. Other versions of PR will not have a core controller nor scheduling
seanhalle@222 61 * slots.
seanhalle@222 62 *
seanhalle@222 63 *The core controller "owns" the physical core, in effect, and is the
seanhalle@230 64 * function given to the pthread's creation call. Hence, it contains code
seanhalle@222 65 * related to pthread startup, synchronizing the controllers to all start
seanhalle@222 66 * at the same time-point, and pinning the pthreads to physical cores.
seanhalle@222 67 *
seanhalle@222 68 */
seanhalle@222 69 void *
seanhalle@222 70 coreController( void *paramsIn )
seanhalle@222 71 {
seanhalle@222 72 int32 thisCoresIdx;
seanhalle@222 73 int32 numRepetitionsWithNoWork;
seanhalle@269 74 bool32 foundWork;
seanhalle@269 75 AnimSlot *animSlot;
seanhalle@222 76 volatile int32 *addrOfMasterLock; //thing pointed to is volatile, not ptr
seanhalle@273 77 // SlaveVP *thisCoresMasterVP;
seanhalle@222 78 //Variables used for pthread related things
nengel@238 79 ThdParams *thisCoresThdParams;
seanhalle@222 80 cpu_set_t coreMask; //used during pinning pthread to CPU core
seanhalle@222 81 int32 errorCode;
seanhalle@270 82 //Variables used during measurements (inside macro!)
seanhalle@222 83 TSCountLowHigh endSusp;
seanhalle@222 84 //Variables used in random-backoff, for master-lock and waiting for work
seanhalle@230 85 uint32_t seed1 = rand()%1000; // init random number generator for backoffs
seanhalle@222 86 uint32_t seed2 = rand()%1000;
seanhalle@222 87
seanhalle@222 88
seanhalle@222 89 //=============== Initializations ===================
nengel@238 90 thisCoresThdParams = (ThdParams *)paramsIn;
nengel@238 91 thisCoresIdx = thisCoresThdParams->coreNum;
seanhalle@222 92
seanhalle@272 93 //Assembly that saves addr of label of return instr -- addr used in assmbly
seanhalle@261 94 recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt));
seanhalle@222 95
seanhalle@270 96 //TODO: DEBUG: check get correct pointer here
seanhalle@270 97 animSlot = _PRTopEnv->allAnimSlots[ thisCoresIdx ][0];
seanhalle@273 98 animSlot->slaveAssignedToSlot = _PRTopEnv->idleSlv[thisCoresIdx][ZERO];
seanhalle@273 99
seanhalle@222 100 numRepetitionsWithNoWork = 0;
seanhalle@261 101 addrOfMasterLock = &(_PRTopEnv->masterLock);
seanhalle@273 102 // thisCoresMasterVP = _PRTopEnv->masterVPs[ thisCoresIdx ];
seanhalle@222 103
seanhalle@222 104 //==================== pthread related stuff ======================
seanhalle@225 105 //pin the pthread to the core -- takes away Linux control
seanhalle@222 106 //Linux requires pinning to be done inside the thread-function
seanhalle@222 107 //Designate a core by a 1 in bit-position corresponding to the core
seanhalle@222 108 CPU_ZERO(&coreMask); //initialize mask bits to zero
nengel@238 109 CPU_SET(thisCoresThdParams->coreNum,&coreMask); //set bit repr the coreNum
seanhalle@222 110 pthread_t selfThd = pthread_self();
seanhalle@222 111 errorCode =
seanhalle@222 112 pthread_setaffinity_np( selfThd, sizeof(coreMask), &coreMask);
seanhalle@222 113 if(errorCode){ printf("\n pinning thd to core failed \n"); exit(0); }
seanhalle@222 114
seanhalle@222 115 //make sure the controllers all start at same time, by making them wait
seanhalle@227 116 pthread_mutex_lock( &suspendLock );
seanhalle@268 117 while( !(_PRTopEnv->firstProcessReady) )
seanhalle@222 118 { pthread_cond_wait( &suspendCond, &suspendLock );
seanhalle@222 119 }
seanhalle@222 120 pthread_mutex_unlock( &suspendLock );
seanhalle@235 121
seanhalle@268 122 HOLISTIC__CoreCtrl_Setup;
nengel@238 123
seanhalle@278 124 DEBUG__printf1(TRUE, "started coreCtrlr %d", thisCoresIdx );
nengel@238 125
seanhalle@222 126 //====================== The Core Controller ======================
seanhalle@270 127 while(1)
seanhalle@222 128 { //Assembly code switches the core between animating a VP and
seanhalle@222 129 // animating this core controller. The switch is done by
seanhalle@222 130 // changing the stack-pointer and frame-pointer and then doing
seanhalle@222 131 // an assembly jmp. When reading this code, the effect is
seanhalle@222 132 // that the "switchToSlv()" at the end of the loop is sort of a
seanhalle@222 133 // "warp in time" -- the core disappears inside this, jmps to
seanhalle@222 134 // animating a VP, and when that VP suspends, the suspend
seanhalle@222 135 // jmps back. This has the effect of "returning" from the
seanhalle@222 136 // switchToSlv() call. Then control loops back to here.
seanhalle@222 137 //Alternatively, the VP suspend primitive could just not bother
seanhalle@222 138 // returning from switchToSlv, and instead jmp directly to here.
seanhalle@227 139
seanhalle@273 140 if(animSlot->slaveAssignedToSlot->typeOfVP == IdleVP)
seanhalle@269 141 { //The Holistic stuff turns on idle slaves.. but can also be in mode
seanhalle@269 142 // where have no idle slaves.. so, this IF statement can only be true
seanhalle@269 143 // executed when HOLISTIC is turned on..
seanhalle@269 144 numRepetitionsWithNoWork ++;
seanhalle@269 145 HOLISTIC__Record_last_work;
seanhalle@269 146 }
seanhalle@269 147
seanhalle@222 148
seanhalle@269 149
seanhalle@269 150 HOLISTIC__Record_AppResponderInvocation_start;
seanhalle@269 151 MEAS__Capture_Pre_Master_Lock_Point;
seanhalle@269 152
seanhalle@269 153 int numTriesToGetLock = 0; int gotLock = 0;
seanhalle@270 154 while( gotLock == FALSE ) //keep going until get master lock
seanhalle@269 155 {
seanhalle@270 156 //want to
seanhalle@269 157 // reduce lock contention from cores with no work, so first
seanhalle@269 158 // check if this is a core with no work, and busy wait if so.
seanhalle@269 159 //Then, if it's been way too long without work, yield pthread
seanhalle@269 160 if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_BACKOFF)
seanhalle@269 161 doBackoff_for_TooLongWithNoWork( numRepetitionsWithNoWork, &seed1, &seed2 );
seanhalle@269 162 if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_YIELD )
seanhalle@269 163 { numRepetitionsWithNoWork = 0; pthread_yield(); }
seanhalle@269 164
seanhalle@269 165
seanhalle@270 166 //Try to get the lock
seanhalle@269 167 gotLock = __sync_bool_compare_and_swap( addrOfMasterLock,
seanhalle@269 168 UNLOCKED, LOCKED );
seanhalle@269 169 if( gotLock )
seanhalle@269 170 { //At this point, have successfully gotten master lock.
seanhalle@269 171 //So, break out of get-lock loop.
seanhalle@270 172 break;
seanhalle@267 173 }
seanhalle@270 174 //Get here only when failed to get lock -- check in should do backoff
seanhalle@222 175
seanhalle@269 176 numTriesToGetLock++; //if too many, means too much contention
seanhalle@269 177 if( numTriesToGetLock > NUM_TRIES_BEFORE_DO_BACKOFF )
seanhalle@269 178 doBackoff_for_TooLongToGetLock( numTriesToGetLock, &seed1, &seed2 );
seanhalle@269 179 if( numTriesToGetLock > MASTERLOCK_RETRIES_BEFORE_YIELD )
seanhalle@269 180 { numTriesToGetLock = 0; pthread_yield(); }
seanhalle@269 181 } //while( currVP == NULL )
seanhalle@269 182 MEAS__Capture_Post_Master_Lock_Point;
seanhalle@269 183 //have master lock, perform master function, which manages request
seanhalle@269 184 // handling and assigning work to this core's slot
seanhalle@269 185 foundWork =
seanhalle@270 186
seanhalle@269 187 masterFunction( animSlot );
seanhalle@270 188
seanhalle@270 189 PR_int__release_master_lock();
seanhalle@270 190
seanhalle@269 191 if( foundWork )
seanhalle@269 192 numRepetitionsWithNoWork = 0;
seanhalle@269 193 else
seanhalle@269 194 numRepetitionsWithNoWork += 1;
seanhalle@222 195
seanhalle@270 196 //now that master is done, have work in the slot, so switch to it
seanhalle@269 197 HOLISTIC__Record_Work_start;
seanhalle@222 198
seanhalle@270 199 switchToSlv(animSlot->slaveAssignedToSlot); //Slave suspend makes core "return" from this call
seanhalle@222 200 flushRegisters(); //prevent GCC optimization from doing bad things
seanhalle@222 201
seanhalle@222 202 MEAS__Capture_End_Susp_in_CoreCtlr_ForSys;
seanhalle@269 203 HOLISTIC__Record_Work_end;
seanhalle@222 204 }//while(1)
seanhalle@222 205 }
seanhalle@222 206
seanhalle@260 207 /*Shutdown of PR involves several steps, of which this is the last. This
seanhalle@230 208 * function is jumped to from the asmTerminateCoreCtrl, which is in turn
seanhalle@230 209 * called from endOSThreadFn, which is the top-level-fn of the shutdown
seanhalle@230 210 * slaves.
seanhalle@230 211 */
seanhalle@222 212 void *
seanhalle@222 213 terminateCoreCtlr(SlaveVP *currSlv)
seanhalle@222 214 {
seanhalle@230 215 //first, free shutdown Slv that jumped here, then end the pthread
seanhalle@278 216 // PR_int__free_slaveVP( currSlv );
seanhalle@222 217 pthread_exit( NULL );
seanhalle@222 218 }
seanhalle@222 219
seanhalle@246 220 inline uint32_t
seanhalle@246 221 randomNumber()
seanhalle@246 222 {
seanhalle@261 223 _PRTopEnv->seed1 = (uint32)(36969 * (_PRTopEnv->seed1 & 65535) +
seanhalle@261 224 (_PRTopEnv->seed1 >> 16) );
seanhalle@261 225 _PRTopEnv->seed2 = (uint32)(18000 * (_PRTopEnv->seed2 & 65535) +
seanhalle@261 226 (_PRTopEnv->seed2 >> 16) );
seanhalle@261 227 return (_PRTopEnv->seed1 << 16) + _PRTopEnv->seed2;
seanhalle@246 228 }
seanhalle@246 229
seanhalle@246 230
seanhalle@222 231
seanhalle@222 232 /*Busy-wait for a random number of cycles -- chooses number of cycles
seanhalle@222 233 * differently than for the too-many-tries-to-get-lock backoff
seanhalle@222 234 */
seanhalle@222 235 inline void
seanhalle@222 236 doBackoff_for_TooLongWithNoWork( int32 numRepsWithNoWork, uint32 *seed1,
seanhalle@222 237 uint32 *seed2 )
seanhalle@222 238 { int32 i, waitIterations;
seanhalle@222 239 volatile double fakeWorkVar; //busy-wait fake work
seanhalle@222 240
seanhalle@230 241 //Get a random number of iterations to busy-wait. The % is a simple
seanhalle@230 242 // way to set the maximum value that can be generated.
seanhalle@222 243 waitIterations =
seanhalle@222 244 randomNumber(seed1, seed2) %
seanhalle@222 245 (numRepsWithNoWork * numRepsWithNoWork * NUM_CORES);
seanhalle@222 246 for( i = 0; i < waitIterations; i++ )
seanhalle@222 247 { fakeWorkVar += (fakeWorkVar + 32.0) / 2.0; //busy-wait
seanhalle@222 248 }
seanhalle@222 249 }
seanhalle@222 250
seanhalle@222 251 /*Busy-waits for a random number of cycles -- chooses number of cycles
seanhalle@222 252 * differently than for the no-work backoff
seanhalle@222 253 */
seanhalle@222 254 inline void
seanhalle@222 255 doBackoff_for_TooLongToGetLock( int32 numTriesToGetLock, uint32 *seed1,
seanhalle@222 256 uint32 *seed2 )
seanhalle@222 257 { int32 i, waitIterations;
seanhalle@222 258 volatile double fakeWorkVar; //busy-wait fake work
seanhalle@222 259
seanhalle@222 260 waitIterations =
seanhalle@222 261 randomNumber(seed1, seed2) %
seanhalle@245 262 (numTriesToGetLock * GET_LOCK_BACKOFF_WEIGHT);
seanhalle@222 263 //addToHist( wait_iterations, coreLoopThdParams->wait_iterations_hist );
seanhalle@222 264 for( i = 0; i < waitIterations; i++ )
seanhalle@222 265 { fakeWorkVar += (fakeWorkVar + 32.0) / 2.0; //busy-wait
seanhalle@222 266 }
seanhalle@222 267 }
seanhalle@222 268
seanhalle@222 269
seanhalle@222 270 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
seanhalle@222 271
seanhalle@222 272 //===========================================================================
seanhalle@222 273 /*This sequential version does the same as threaded, except doesn't do the
seanhalle@222 274 * pin-threads part, nor the wait until setup complete and acquire master
seanhalle@222 275 * lock parts.
seanhalle@222 276 */
seanhalle@222 277 void *
seanhalle@222 278 coreCtlr_Seq( void *paramsIn )
seanhalle@273 279 {
seanhalle@222 280 int32 thisCoresIdx;
seanhalle@222 281 int32 numRepetitionsWithNoWork;
seanhalle@273 282 bool32 foundWork;
seanhalle@273 283 AnimSlot *animSlot;
seanhalle@273 284 volatile int32 *addrOfMasterLock; //thing pointed to is volatile, not ptr
seanhalle@273 285 //Variables used for pthread related things
seanhalle@273 286 ThdParams *thisCoresThdParams;
seanhalle@273 287 cpu_set_t coreMask; //used during pinning pthread to CPU core
seanhalle@273 288 int32 errorCode;
seanhalle@273 289 //Variables used during measurements (inside macro!)
seanhalle@273 290 TSCountLowHigh endSusp;
seanhalle@273 291 //Variables used in random-backoff, for master-lock and waiting for work
seanhalle@273 292 uint32_t seed1 = rand()%1000; // init random number generator for backoffs
seanhalle@273 293 uint32_t seed2 = rand()%1000;
seanhalle@273 294
seanhalle@222 295
seanhalle@222 296 //=============== Initializations ===================
seanhalle@273 297 // thisCoresThdParams = (ThdParams *)paramsIn;
seanhalle@273 298 // thisCoresIdx = thisCoresThdParams->coreNum;
seanhalle@273 299 thisCoresIdx = 0;
seanhalle@273 300
seanhalle@273 301 //Assembly that saves addr of label of return instr -- addr used in assmbly
seanhalle@273 302 recordCoreCtlrReturnLabelAddr((void**)&(_PRTopEnv->coreCtlrReturnPt));
seanhalle@273 303
seanhalle@273 304 //TODO: DEBUG: check get correct pointer here
seanhalle@273 305 animSlot = _PRTopEnv->allAnimSlots[ thisCoresIdx ][0];
seanhalle@273 306 animSlot->slaveAssignedToSlot = _PRTopEnv->idleSlv[thisCoresIdx][ZERO];
seanhalle@273 307
seanhalle@222 308 numRepetitionsWithNoWork = 0;
seanhalle@261 309 addrOfMasterLock = &(_PRTopEnv->masterLock);
seanhalle@222 310
seanhalle@273 311 //==================== pthread related stuff ======================
seanhalle@273 312 //pin the pthread to the core -- takes away Linux control
seanhalle@273 313 //Linux requires pinning to be done inside the thread-function
seanhalle@273 314 //Designate a core by a 1 in bit-position corresponding to the core
seanhalle@273 315 /*
seanhalle@273 316 CPU_ZERO(&coreMask); //initialize mask bits to zero
seanhalle@273 317 CPU_SET(thisCoresThdParams->coreNum,&coreMask); //set bit repr the coreNum
seanhalle@273 318 pthread_t selfThd = pthread_self();
seanhalle@273 319 errorCode =
seanhalle@273 320 pthread_setaffinity_np( selfThd, sizeof(coreMask), &coreMask);
seanhalle@273 321 if(errorCode){ printf("\n pinning thd to core failed \n"); exit(0); }
seanhalle@222 322
seanhalle@273 323 //make sure the controllers all start at same time, by making them wait
seanhalle@273 324 pthread_mutex_lock( &suspendLock );
seanhalle@273 325 while( !(_PRTopEnv->firstProcessReady) )
seanhalle@273 326 { pthread_cond_wait( &suspendCond, &suspendLock );
seanhalle@273 327 }
seanhalle@273 328 pthread_mutex_unlock( &suspendLock );
seanhalle@222 329
seanhalle@273 330 HOLISTIC__CoreCtrl_Setup;
seanhalle@273 331
seanhalle@273 332 DEBUG__printf1(TRUE, "started coreCtrlr", thisCoresIdx );
seanhalle@273 333 */
seanhalle@222 334 //====================== The Core Controller ======================
seanhalle@273 335 while(1)
seanhalle@273 336 { //Assembly code switches the core between animating a VP and
seanhalle@273 337 // animating this core controller. The switch is done by
seanhalle@273 338 // changing the stack-pointer and frame-pointer and then doing
seanhalle@273 339 // an assembly jmp. When reading this code, the effect is
seanhalle@273 340 // that the "switchToSlv()" at the end of the loop is sort of a
seanhalle@273 341 // "warp in time" -- the core disappears inside this, jmps to
seanhalle@273 342 // animating a VP, and when that VP suspends, the suspend
seanhalle@273 343 // jmps back. This has the effect of "returning" from the
seanhalle@273 344 // switchToSlv() call. Then control loops back to here.
seanhalle@273 345 //Alternatively, the VP suspend primitive could just not bother
seanhalle@273 346 // returning from switchToSlv, and instead jmp directly to here.
seanhalle@273 347 //core controller top of loop
seanhalle@273 348 if(animSlot->slaveAssignedToSlot->typeOfVP == IdleVP)
seanhalle@273 349 { //The Holistic stuff turns on idle slaves.. but can also be in mode
seanhalle@273 350 // where have no idle slaves.. so, this IF statement can only be true
seanhalle@273 351 // executed when HOLISTIC is turned on..
seanhalle@273 352 numRepetitionsWithNoWork ++;
seanhalle@273 353 HOLISTIC__Record_last_work;
seanhalle@273 354 }
seanhalle@273 355
seanhalle@222 356
seanhalle@273 357
seanhalle@273 358 HOLISTIC__Record_AppResponderInvocation_start;
seanhalle@273 359 MEAS__Capture_Pre_Master_Lock_Point;
seanhalle@273 360
seanhalle@273 361 int numTriesToGetLock = 0; int gotLock = 0;
seanhalle@273 362 while( gotLock == FALSE ) //keep going until get master lock
seanhalle@273 363 {
seanhalle@273 364 //want to
seanhalle@273 365 // reduce lock contention from cores with no work, so first
seanhalle@273 366 // check if this is a core with no work, and busy wait if so.
seanhalle@273 367 //Then, if it's been way too long without work, yield pthread
seanhalle@273 368 if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_BACKOFF)
seanhalle@273 369 doBackoff_for_TooLongWithNoWork( numRepetitionsWithNoWork, &seed1, &seed2 );
seanhalle@273 370 if( numRepetitionsWithNoWork > NUM_REPS_W_NO_WORK_BEFORE_YIELD )
seanhalle@276 371 { //This is sequential mode.. just return
seanhalle@276 372 return;
seanhalle@276 373 }
seanhalle@273 374
seanhalle@273 375
seanhalle@273 376 //Try to get the lock
seanhalle@273 377 gotLock = __sync_bool_compare_and_swap( addrOfMasterLock,
seanhalle@273 378 UNLOCKED, LOCKED );
seanhalle@273 379 if( gotLock )
seanhalle@273 380 { //At this point, have successfully gotten master lock.
seanhalle@273 381 //So, break out of get-lock loop.
seanhalle@273 382 break;
seanhalle@273 383 }
seanhalle@273 384 //Get here only when failed to get lock -- check in should do backoff
seanhalle@273 385
seanhalle@273 386 numTriesToGetLock++; //if too many, means too much contention
seanhalle@273 387 if( numTriesToGetLock > NUM_TRIES_BEFORE_DO_BACKOFF )
seanhalle@273 388 doBackoff_for_TooLongToGetLock( numTriesToGetLock, &seed1, &seed2 );
seanhalle@273 389 if( numTriesToGetLock > MASTERLOCK_RETRIES_BEFORE_YIELD )
seanhalle@273 390 { numTriesToGetLock = 0; pthread_yield(); }
seanhalle@273 391 } //while( currVP == NULL )
seanhalle@273 392 MEAS__Capture_Post_Master_Lock_Point;
seanhalle@273 393
seanhalle@273 394 //have master lock, perform master function, which manages request
seanhalle@273 395 // handling and assigning work to this core's slot
seanhalle@273 396 foundWork =
seanhalle@222 397
seanhalle@273 398 masterFunction( animSlot );
seanhalle@273 399
seanhalle@273 400 PR_int__release_master_lock();
seanhalle@273 401
seanhalle@273 402 if( foundWork )
seanhalle@273 403 numRepetitionsWithNoWork = 0;
seanhalle@273 404 else
seanhalle@222 405 numRepetitionsWithNoWork += 1;
seanhalle@222 406
seanhalle@273 407 //now that master is done, have work in the slot, so switch to it
seanhalle@273 408 HOLISTIC__Record_Work_start;
seanhalle@273 409
seanhalle@273 410 switchToSlv(animSlot->slaveAssignedToSlot); //Slave suspend makes core "return" from this call
seanhalle@222 411 flushRegisters(); //prevent GCC optimization from doing bad things
seanhalle@222 412
seanhalle@222 413 MEAS__Capture_End_Susp_in_CoreCtlr_ForSys;
seanhalle@273 414 HOLISTIC__Record_Work_end;
seanhalle@273 415 }//while(1)
seanhalle@222 416 }
seanhalle@273 417
seanhalle@222 418 #endif