Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison VMS.c @ 26:668278fa7a63
Sequential -- just starting to add sequential version
| author | Me |
|---|---|
| date | Mon, 26 Jul 2010 15:25:53 -0700 |
| parents | c556193f7211 |
| children | 8b9e4c333fe6 |
comparison
equal
deleted
inserted
replaced
| 8:0aad63472e71 | 9:0cc3de1e9ce1 |
|---|---|
| 10 | 10 |
| 11 #include "VMS.h" | 11 #include "VMS.h" |
| 12 #include "Queue_impl/BlockingQueue.h" | 12 #include "Queue_impl/BlockingQueue.h" |
| 13 | 13 |
| 14 | 14 |
| 15 #define thdAttrs NULL | |
| 16 | |
| 15 //=========================================================================== | 17 //=========================================================================== |
| 16 void | 18 void |
| 17 shutdownFn( void *dummy, VirtProcr *dummy2 ); | 19 shutdownFn( void *dummy, VirtProcr *dummy2 ); |
| 18 | 20 |
| 19 void | 21 void |
| 20 create_sched_slots( MasterEnv *masterEnv ); | 22 create_sched_slots( MasterEnv *masterEnv ); |
| 23 | |
| 24 pthread_mutex_t suspendLock = PTHREAD_MUTEX_INITIALIZER; | |
| 25 pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER; | |
| 21 | 26 |
| 22 //=========================================================================== | 27 //=========================================================================== |
| 23 | 28 |
| 24 /*Setup has two phases: | 29 /*Setup has two phases: |
| 25 * 1) Semantic layer first calls init_VMS, which creates masterEnv, and puts | 30 * 1) Semantic layer first calls init_VMS, which creates masterEnv, and puts |
| 50 * layer. | 55 * layer. |
| 51 */ | 56 */ |
| 52 void | 57 void |
| 53 VMS__init() | 58 VMS__init() |
| 54 { MasterEnv *masterEnv; | 59 { MasterEnv *masterEnv; |
| 55 CASQueueStruc *workQ; | 60 VMSQueueStruc *workQ; |
| 56 | 61 |
| 57 //Make the central work-queue | 62 //Make the central work-queue |
| 58 _VMSWorkQ = makeCASQ(); | 63 _VMSWorkQ = makeVMSQ(); |
| 59 workQ = _VMSWorkQ; | 64 workQ = _VMSWorkQ; |
| 60 | 65 |
| 61 _VMSMasterEnv = malloc( sizeof(MasterEnv) ); | 66 _VMSMasterEnv = malloc( sizeof(MasterEnv) ); |
| 62 masterEnv = _VMSMasterEnv; | 67 masterEnv = _VMSMasterEnv; |
| 63 | 68 |
| 64 //create the master virtual processor | 69 //create the master virtual processor |
| 65 masterEnv->masterVirtPr = VMS__create_procr( &masterLoop, masterEnv ); | 70 masterEnv->masterVirtPr = VMS__create_procr( &masterLoop, masterEnv ); |
| 66 | 71 |
| 67 create_sched_slots( masterEnv ); | 72 create_sched_slots( masterEnv ); |
| 68 | 73 |
| 69 //Set slot 0 to be the master virt procr & set flags just in case | |
| 70 masterEnv->schedSlots[0]->needsProcrAssigned = FALSE; //says don't touch | |
| 71 masterEnv->schedSlots[0]->workIsDone = FALSE; //says don't touch | |
| 72 masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr; | |
| 73 masterEnv->masterVirtPr->schedSlot = masterEnv->schedSlots[0]; | |
| 74 masterEnv->stillRunning = FALSE; | 74 masterEnv->stillRunning = FALSE; |
| 75 masterEnv->numToPrecede = NUM_CORES; | |
| 75 | 76 |
| 76 //First core loop to start up gets this, which will schedule seed Pr | 77 //First core loop to start up gets this, which will schedule seed Pr |
| 77 //TODO: debug: check address of masterVirtPr | 78 //TODO: debug: check address of masterVirtPr |
| 78 writeCASQ( masterEnv->masterVirtPr, workQ ); | 79 writeVMSQ( masterEnv->masterVirtPr, workQ ); |
| 79 | 80 |
| 80 numProcrsCreated = 1; | 81 numProcrsCreated = 1; |
| 81 | 82 |
| 82 //======================================================================== | 83 //======================================================================== |
| 83 // Create the Threads | 84 // Create the Threads |
| 84 int coreIdx, retCode; | 85 int coreIdx, retCode; |
| 85 #define thdAttrs NULL | 86 |
| 86 | |
| 87 _VMSMasterEnv->setupComplete = 0; | |
| 88 _VMSMasterEnv->suspend_mutex = PTHREAD_MUTEX_INITIALIZER; | |
| 89 _VMSMasterEnv->suspend_cond = PTHREAD_COND_INITIALIZER; | |
| 90 | |
| 91 //Need the threads to be created suspended, and wait for a signal | 87 //Need the threads to be created suspended, and wait for a signal |
| 92 // before proceeding -- gives time after creating to initialize other | 88 // before proceeding -- gives time after creating to initialize other |
| 93 // stuff before the coreLoops set off. | 89 // stuff before the coreLoops set off. |
| 94 | 90 _VMSMasterEnv->setupComplete = 0; |
| 95 //Make params given to the win threads that animate the core loops | 91 |
| 92 //Make the threads that animate the core loops | |
| 96 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) | 93 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) |
| 97 { coreLoopThdParams[coreIdx] = malloc( sizeof(ThdParams) ); | 94 { coreLoopThdParams[coreIdx] = malloc( sizeof(ThdParams) ); |
| 98 coreLoopThdParams[coreIdx]->coreNum = coreIdx; | 95 coreLoopThdParams[coreIdx]->coreNum = coreIdx; |
| 99 | 96 |
| 100 retCode = | 97 retCode = |
| 101 pthread_create( &(coreLoopThdHandles[coreIdx]), | 98 pthread_create( &(coreLoopThdHandles[coreIdx]), |
| 102 thdAttrs, | 99 thdAttrs, |
| 103 &coreLoop, | 100 &coreLoop, |
| 104 (void *)(coreLoopThdParams[coreIdx]) ); | 101 (void *)(coreLoopThdParams[coreIdx]) ); |
| 105 if(!retCode){printf("ERROR creating thread: %d\n", retCode); exit();} | 102 if(retCode){printf("ERROR creating thread: %d\n", retCode); exit(0);} |
| 106 } | 103 } |
| 107 | |
| 108 | |
| 109 } | 104 } |
| 110 | 105 |
| 111 void | 106 void |
| 112 create_sched_slots( MasterEnv *masterEnv ) | 107 create_sched_slots( MasterEnv *masterEnv ) |
| 113 { SchedSlot **schedSlots, **filledSlots; | 108 { SchedSlot **schedSlots, **filledSlots; |
| 146 | 141 |
| 147 //tell the core loop threads that setup is complete | 142 //tell the core loop threads that setup is complete |
| 148 //get lock, to lock out any threads still starting up -- they'll see | 143 //get lock, to lock out any threads still starting up -- they'll see |
| 149 // that setupComplete is true before entering while loop, and so never | 144 // that setupComplete is true before entering while loop, and so never |
| 150 // wait on the condition | 145 // wait on the condition |
| 151 pthread_mutex_lock( _VMSMasterEnv->suspend_mutex ); | 146 pthread_mutex_lock( &suspendLock ); |
| 152 _VMSMasterEnv->setupComplete = 1; | 147 _VMSMasterEnv->setupComplete = 1; |
| 153 pthread_mutex_unlock( _VMSMasterEnv->suspend_mutex ); | 148 pthread_mutex_unlock( &suspendLock ); |
| 154 pthread_cond_broadcast( _VMSMasterEnv->suspend_cond ); | 149 pthread_cond_broadcast( &suspend_cond ); |
| 155 | 150 |
| 156 | 151 |
| 157 //wait for all to complete | 152 //wait for all to complete |
| 158 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) | 153 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) |
| 159 { | 154 { |
| 198 //fnPtr takes two params -- void *initData & void *animProcr | 193 //fnPtr takes two params -- void *initData & void *animProcr |
| 199 //alloc stack locations, make stackPtr be the highest addr minus room | 194 //alloc stack locations, make stackPtr be the highest addr minus room |
| 200 // for 2 params + return addr. Return addr (NULL) is in loc pointed to | 195 // for 2 params + return addr. Return addr (NULL) is in loc pointed to |
| 201 // by stackPtr, initData at stackPtr + 4 bytes, animatingPr just above | 196 // by stackPtr, initData at stackPtr + 4 bytes, animatingPr just above |
| 202 stackLocs = malloc( VIRT_PROCR_STACK_SIZE ); | 197 stackLocs = malloc( VIRT_PROCR_STACK_SIZE ); |
| 198 if(stackLocs == 0) | |
| 199 {perror("malloc stack"); exit(1);} | |
| 203 newPr->startOfStack = stackLocs; | 200 newPr->startOfStack = stackLocs; |
| 204 stackPtr = ( (char *)stackLocs + VIRT_PROCR_STACK_SIZE - 0x10 ); | 201 stackPtr = ( (char *)stackLocs + VIRT_PROCR_STACK_SIZE - 0x10 ); |
| 205 //setup __cdecl on stack -- coreloop will switch to stackPtr before jmp | 202 //setup __cdecl on stack -- coreloop will switch to stackPtr before jmp |
| 206 *( (int *)stackPtr + 2 ) = (int) newPr; //rightmost param -- 32bit pointer | 203 *( (int *)stackPtr + 2 ) = (int) newPr; //rightmost param -- 32bit pointer |
| 207 *( (int *)stackPtr + 1 ) = (int) initialData; //next param to left | 204 *( (int *)stackPtr + 1 ) = (int) initialData; //next param to left |
| 210 | 207 |
| 211 return newPr; | 208 return newPr; |
| 212 } | 209 } |
| 213 | 210 |
| 214 | 211 |
| 215 /*there is a label inside this function -- save the addr of this label in | 212 /*there is a label inside this function -- save the addr of this label in |
| 216 * the callingPr struc, as the pick-up point from which to start the next | 213 * the callingPr struc, as the pick-up point from which to start the next |
| 217 * work-unit for that procr. If turns out have to save registers, then | 214 * work-unit for that procr. If turns out have to save registers, then |
| 218 * save them in the procr struc too. Then do assembly jump to the CoreLoop's | 215 * save them in the procr struc too. Then do assembly jump to the CoreLoop's |
| 219 * "done with work-unit" label. The procr struc is in the request in the | 216 * "done with work-unit" label. The procr struc is in the request in the |
| 220 * slave that animated the just-ended work-unit, so all the state is saved | 217 * slave that animated the just-ended work-unit, so all the state is saved |
| 236 callingPr->schedSlot->workIsDone = TRUE; | 233 callingPr->schedSlot->workIsDone = TRUE; |
| 237 // coreIdx = callingPr->coreAnimatedBy; | 234 // coreIdx = callingPr->coreAnimatedBy; |
| 238 | 235 |
| 239 stackPtrAddr = &(callingPr->stackPtr); | 236 stackPtrAddr = &(callingPr->stackPtr); |
| 240 framePtrAddr = &(callingPr->framePtr); | 237 framePtrAddr = &(callingPr->framePtr); |
| 241 | 238 |
| 242 jmpPt = callingPr->coreLoopStartPt; | 239 jmpPt = callingPr->coreLoopStartPt; |
| 243 coreLoopFramePtr = callingPr->coreLoopFramePtr;//need this only | 240 coreLoopFramePtr = callingPr->coreLoopFramePtr;//need this only |
| 244 coreLoopStackPtr = callingPr->coreLoopStackPtr;//shouldn't need -- safety | 241 coreLoopStackPtr = callingPr->coreLoopStackPtr;//shouldn't need -- safety |
| 245 | 242 |
| 246 //Save the virt procr's stack and frame ptrs, restore coreloop's frame | 243 //Eclipse's compilation sequence complains -- so break into two |
| 247 // ptr, then jump back to "start" of core loop | 244 // separate in-line assembly pieces |
| 248 //Note, GCC compiles to assembly that saves esp and ebp in the stack | 245 //Save the virt procr's stack and frame ptrs, |
| 249 // frame -- so have to explicitly do assembly that saves to memory | |
| 250 asm volatile("movl %0, %%eax; \ | 246 asm volatile("movl %0, %%eax; \ |
| 251 movl %%esp, (%%eax); \ | 247 movl %%esp, (%%eax); \ |
| 252 movl %1, %%eax; \ | 248 movl %1, %%eax; \ |
| 253 movl %%ebp, (%%eax); \ | 249 movl %%ebp, (%%eax) "\ |
| 254 movl %2, %%eax; \ | 250 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr) \ |
| 255 movl %3, %%esp; \ | 251 /* inputs */ : \ |
| 256 movl %4, %%ebp; \ | 252 /* clobber */ : "%eax" \ |
| 253 ); | |
| 254 | |
| 255 //restore coreloop's frame ptr, then jump back to "start" of core loop | |
| 256 //Note, GCC compiles to assembly that saves esp and ebp in the stack | |
| 257 // frame -- so have to explicitly do assembly that saves to memory | |
| 258 asm volatile("movl %0, %%eax; \ | |
| 259 movl %1, %%esp; \ | |
| 260 movl %2, %%ebp; \ | |
| 257 jmp %%eax " \ | 261 jmp %%eax " \ |
| 258 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr) \ | 262 /* outputs */ : \ |
| 259 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\ | 263 /* inputs */ : "m" (jmpPt), "m"(coreLoopStackPtr), "m"(coreLoopFramePtr)\ |
| 260 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" \ | 264 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" \ |
| 261 ); //list everything as clobbered to force GCC to save all | 265 ); //list everything as clobbered to force GCC to save all |
| 262 // live vars that are in regs on stack before this | 266 // live vars that are in regs on stack before this |
| 263 // assembly, so that stack pointer is correct, before jmp | 267 // assembly, so that stack pointer is correct, before jmp |
| 264 | 268 |
| 354 | 358 |
| 355 | 359 |
| 356 //TODO: add a semantic-layer supplied "freer" for the semantic-data portion | 360 //TODO: add a semantic-layer supplied "freer" for the semantic-data portion |
| 357 // of a request -- IE call with both a virt procr and a fn-ptr to request | 361 // of a request -- IE call with both a virt procr and a fn-ptr to request |
| 358 // freer (also maybe put sem request freer as a field in virt procr?) | 362 // freer (also maybe put sem request freer as a field in virt procr?) |
| 363 //VMSHW relies right now on this only freeing VMS layer of request -- the | |
| 364 // semantic portion of request is alloc'd and freed by request handler | |
| 359 void | 365 void |
| 360 VMS__free_request( VMSReqst *req ) | 366 VMS__free_request( VMSReqst *req ) |
| 361 { | 367 { |
| 362 free( req ); | 368 free( req ); |
| 363 } | 369 } |
| 498 */ | 504 */ |
| 499 void | 505 void |
| 500 shutdownFn( void *dummy, VirtProcr *animatingPr ) | 506 shutdownFn( void *dummy, VirtProcr *animatingPr ) |
| 501 { int coreIdx; | 507 { int coreIdx; |
| 502 VirtProcr *shutDownPr; | 508 VirtProcr *shutDownPr; |
| 503 CASQueueStruc *workQ = _VMSWorkQ; | 509 VMSQueueStruc *workQ = _VMSWorkQ; |
| 504 | 510 |
| 505 //free all the locations owned within the VMS system | 511 //free all the locations owned within the VMS system |
| 506 //TODO: write VMS__malloc and free.. -- take the DKU malloc as starting pt | 512 //TODO: write VMS__malloc and free.. -- take the DKU malloc as starting pt |
| 507 | 513 |
| 508 //make the core loop shut-down processors and put them into the workQ | 514 //make the core loop shut-down processors and put them into the workQ |
| 509 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) | 515 for( coreIdx=0; coreIdx < NUM_CORES; coreIdx++ ) |
| 510 { | 516 { |
| 511 shutDownPr = VMS__create_procr( NULL, NULL ); | 517 shutDownPr = VMS__create_procr( NULL, NULL ); |
| 512 shutDownPr->nextInstrPt = _VMSMasterEnv->coreLoopShutDownPt; | 518 shutDownPr->nextInstrPt = _VMSMasterEnv->coreLoopShutDownPt; |
| 513 writeCASQ( shutDownPr, workQ ); | 519 writeVMSQ( shutDownPr, workQ ); |
| 514 } | 520 } |
| 515 | 521 |
| 516 //This is an issue: the animating processor of this function may not | 522 //This is an issue: the animating processor of this function may not |
| 517 // get its request handled before all the cores have shutdown. | 523 // get its request handled before all the cores have shutdown. |
| 518 //TODO: after all the threads stop, clean out the MasterEnv, the | 524 //TODO: after all the threads stop, clean out the MasterEnv, the |
