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