Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
comparison VMS.c @ 1:cf5007e51b96
In flux -- has PThread startup -- about to change to winblows threads
| author | Me |
|---|---|
| date | Mon, 31 May 2010 14:11:14 -0700 |
| parents | a5fe730dfc2e |
| children | 9a1b7de19e39 |
comparison
equal
deleted
inserted
replaced
| 0:45391308a69a | 1:c3d3af1bdd18 |
|---|---|
| 39 * and master environment, and returns the master environment to the semantic | 39 * and master environment, and returns the master environment to the semantic |
| 40 * layer. | 40 * layer. |
| 41 */ | 41 */ |
| 42 //Global vars are all inside VMS.h | 42 //Global vars are all inside VMS.h |
| 43 MasterEnv * | 43 MasterEnv * |
| 44 init_VMS( ) | 44 VMS__init( ) |
| 45 { | 45 { MasterEnv *masterEnv; |
| 46 QueueStruc *workQ; | |
| 47 | |
| 46 //Make the central work-queue | 48 //Make the central work-queue |
| 47 workQ = makeQ(); | 49 _VMSWorkQ = makeQ(); |
| 48 | 50 workQ = _VMSWorkQ; |
| 49 masterEnv = malloc( sizeof(MasterEnv) ); | 51 |
| 52 _VMSMasterEnv = malloc( sizeof(MasterEnv) ); | |
| 53 masterEnv = _VMSMasterEnv; | |
| 50 | 54 |
| 51 create_master( masterEnv ); | 55 create_master( masterEnv ); |
| 52 | 56 |
| 53 create_slaves( masterEnv ); | 57 create_sched_slots( masterEnv ); |
| 54 | 58 |
| 55 //When coreLoops start up, the first thing | 59 masterEnv->schedSlots[0]->needsProcrAssigned = FALSE; //never checked |
| 56 writeQ( masterEnv->masterWorkUnit, workQ ); | 60 masterEnv->schedSlots[0]->workIsDone = FALSE; //never checked |
| 57 } | 61 masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr; |
| 58 | 62 |
| 59 | 63 //First core loop to start up gets this, which will schedule seed Pr |
| 60 | 64 //TODO: debug: check address of masterVirtPr |
| 61 /*Fill up the virtual master data structure, which is already alloc'd in the | 65 writeQ( &(masterEnv->masterVirtPr), workQ ); |
| 62 * masterEnv. | 66 } |
| 63 *The virtual Master is the same structure as a virtual slave, but it | 67 |
| 64 * isn't in the array of virtual slaves. | 68 |
| 65 * The reason it's the same structure is so that the coreLoop doesn't | 69 |
| 66 * have to differentiate -- all work units are assigned to a VMSProcr, and | 70 /*Fill up the master VirtProcr data structure, which is already alloc'd |
| 67 * the core loop treats them all the same way, whether it's the virtual | 71 * in the masterEnv. |
| 68 * master continuation or a slave's work-unit. | 72 * The coreLoop treats master virt pr same as the slave virt processors |
| 69 *Note: masterLoop is jumped into an back out of, so have to be careful with | 73 * |
| 70 * register usage and saving all persistent-across-calls state to masterEnv | 74 *The first time it runs, will jump to the function ptr so have to, in here, |
| 75 * create the stack, which will be used by the plug-in functions, and set | |
| 76 * up __cdecl just like do for the other virtual processors. | |
| 71 */ | 77 */ |
| 72 void | 78 void |
| 73 create_master( MasterEnv *masterEnv ) | 79 create_master( MasterEnv *masterEnv ) |
| 74 { VMSProcr virtMaster; | 80 { VirtProcr masterPr; |
| 75 | 81 char * stackLocs, stackPtr; |
| 76 virtMaster = &(masterEnv->virtMaster); | 82 |
| 77 virtMaster->workUnitToDo = malloc( sizeof( WorkUnit ) ); | 83 //TODO: debug this to be sure got addr of struct in masterEnv correctly |
| 78 virtMaster->workUnitToDo->workData = masterEnv; | 84 masterPr = &(masterEnv->masterVirtPr); |
| 79 //TODO: figure out call structure: what GCC will do with regs | 85 masterPr->initialData = masterEnv; |
| 80 // will jump to the masterLoop from the coreLoop -- what regs need | 86 |
| 81 // saving, from before jump to after -- and what reg to put masterEnv | 87 masterPr->nextInstrPt = &masterLoop; |
| 82 // pointer in when jump to masterLoop | 88 |
| 83 virtMaster->workUnitToDo->addrToJumpTo = &masterLoop; | 89 //alloc stack locations, make stackPtr be the last addr in the locs, |
| 84 virtMaster->workUnitToDo->slaveAssignedTo = virtMaster; | 90 // minus room for the two parameters. Put initData at stackPtr, |
| 91 // animatingPr just above | |
| 92 stackLocs = malloc( 0x100000 ); //1 meg stack -- default Win thread's size | |
| 93 stackPtr = ( (char *)stackLocs + 0x100000 - 0x8 ); | |
| 94 masterPr->stackPtr = stackPtr; | |
| 95 masterPr->framePtr = stackPtr; | |
| 96 asm volatile("movl %0, %%esp; | |
| 97 movl %1, (%%esp); | |
| 98 movl %2, $0x4(%%esp); | |
| 99 movl %%esp, %%ebp; " /*framePtr in ebp never used*/ | |
| 100 /* outputs */ : | |
| 101 /* inputs */ : "g" (stackPtr), "g" (initData), "g" (animPr) | |
| 102 /* clobber */ : | |
| 103 ); | |
| 85 } | 104 } |
| 86 | 105 |
| 87 void | 106 void |
| 88 create_slaves( MasterEnv *masterEnv ) | 107 create_sched_slots( MasterEnv *masterEnv ) |
| 89 { VMSProcr *virtSlaves; | 108 { SchedSlot *slots; |
| 90 int i; | 109 int i; |
| 91 | 110 |
| 92 virtSlaves = masterEnv->virtSlaves; //TODO: make sure this is right | 111 slots = masterEnv->schedSlots; //TODO: make sure this is right |
| 93 for( i = 0; i < NUM_SLAVES; i++ ) | 112 for( i = 0; i < NUM_SCHED_SLOTS; i++ ) |
| 94 { | 113 { |
| 95 //Set state to mean "everything done, schedule work to slave" | 114 //Set state to mean "handling requests done, slot needs filling" |
| 96 virtSlaves[i].workIsDone = FALSE; | 115 slots[i].workIsDone = FALSE; |
| 97 virtSlaves[i].needsWorkAssigned = TRUE; | 116 slots[i].needsProcrAssigned = TRUE; |
| 98 } | 117 } |
| 99 } | 118 } |
| 100 | 119 |
| 101 /*Semantic layer calls this when it want the system to start running.. | 120 /*Semantic layer calls this when it want the system to start running.. |
| 102 * | 121 * |
| 111 | 130 |
| 112 //Create the PThread loops that take from work-queue, and start them | 131 //Create the PThread loops that take from work-queue, and start them |
| 113 for( coreIdx=0; coreIdx < NUM_WORKERS; coreIdx++ ) | 132 for( coreIdx=0; coreIdx < NUM_WORKERS; coreIdx++ ) |
| 114 { | 133 { |
| 115 thdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) ); | 134 thdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) ); |
| 116 thdParams[coreIdx]->workQ = workQ; | 135 thdParams[coreIdx]->workQ = _VMSWorkQ; |
| 117 thdParams[coreIdx]->id = coreIdx; | 136 thdParams[coreIdx]->id = coreIdx; |
| 118 | 137 |
| 119 //Now make and start thd.. the coreLoopThds entry | 138 //Now make and start thd.. the coreLoopThds entry |
| 120 // has all the info needed to later stop the thread. | 139 // has all the info needed to later stop the thread. |
| 121 retCode = | 140 retCode = |
| 141 * "done with work-unit" label. The procr struc is in the request in the | 160 * "done with work-unit" label. The procr struc is in the request in the |
| 142 * slave that animated the just-ended work-unit, so all the state is saved | 161 * slave that animated the just-ended work-unit, so all the state is saved |
| 143 * there, and will get passed along, inside the request handler, to the | 162 * there, and will get passed along, inside the request handler, to the |
| 144 * next work-unit for that procr. | 163 * next work-unit for that procr. |
| 145 */ | 164 */ |
| 146 VMS__save_ret_and_jump_to_CoreLoop( callingPr ) | 165 VMS__suspend_processor( VirtProcr *callingPr ) |
| 147 { | 166 { void *jmpPt; |
| 148 //TODO: figure out how to save the addr of a label into a mem loc | 167 |
| 149 //NOTE: because resume pt is inside the VMS fn, it's always the same, no | 168 callingPr->nextInstrPt = &&ResumePt; |
| 150 // matter what the semantic layer is, no matter what semantic libr called. | 169 |
| 151 callingPr->resumePt = &resumeNextWorkUnitPt; | 170 //return ownership of the virt procr and sched slot to Master virt pr |
| 152 save_processor_state_in( callingPr ); //save x86 regs, if GCC needs it to | 171 callingPr->schedSlot->workIsDone = TRUE; |
| 153 coreLoopRetPt = callingPr->coreLoopRetPt; | 172 |
| 154 //TODO: figure out how to do jump correctly -- target addr is constant | 173 jmpPt = callingPr->coreLoopStartPt; |
| 155 asm( jmp coreLoopRetPt ); | 174 |
| 156 | 175 //put all regs in the clobber list to make sure GCC has saved all |
| 157 resumeNextWorkUnitPt: | 176 // so safe to jump to core loop, where they *will* get clobbered |
| 177 asm volatile("movl %%esp, %0; | |
| 178 movl %%ebp, %1; | |
| 179 jmp %2 " | |
| 180 /* outputs */ : "=m" (currPr->stackPtr), "=m" (currPr->framePtr) | |
| 181 /* inputs */ : "g" (jmpPt) | |
| 182 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" | |
| 183 ); | |
| 184 | |
| 185 ResumePt: | |
| 158 return; | 186 return; |
| 187 } | |
| 188 | |
| 189 | |
| 190 /*Create stack, then create __cdecl structure on it and put initialData and | |
| 191 * pointer to the new structure instance into the parameter positions on | |
| 192 * the stack | |
| 193 *Then put function pointer into nextInstrPt -- the stack is setup in std | |
| 194 * call structure, so jumping to function ptr is same as a GCC generated | |
| 195 * function call | |
| 196 *No need to save registers on old stack frame, because there's no old | |
| 197 * animator state to return to -- | |
| 198 * | |
| 199 */ | |
| 200 VirtProcr * | |
| 201 VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ) | |
| 202 { VirtProcr newPr; | |
| 203 | |
| 204 newPr = malloc( sizeof(VirtProcr) ); | |
| 205 newPr->nextInstrPt = fnPtr; | |
| 206 newPr->initialData = initialData; | |
| 207 newPr->stackPtr = createNewStack(); | |
| 208 newPr->framePtr = newPr->stackPtr; | |
| 209 put params onto stack and setup __cdecl call structure | |
| 210 | |
| 211 return newPr; | |
| 159 } | 212 } |
| 160 | 213 |
| 161 | 214 |
| 162 /*The semantic virt procr is available in the request sent from the slave | 215 /*The semantic virt procr is available in the request sent from the slave |
| 163 * | 216 * |
| 164 * The request handler has to add the work-unit created to the semantic | 217 * The request handler has to add the work-unit created to the semantic |
| 165 * virtual processor the work-unit is a section of its time-line -- does this when create the | 218 * virtual processor the work-unit is a section of its time-line -- does this when create the |
| 166 * work-unit -- means the procr data struc is available in the request sent | 219 * work-unit -- means the procr data struc is available in the request sent |
| 167 * from the slave, from which the new work-unit is generated.. | 220 * from the slave, from which the new work-unit is generated.. |
| 168 */ | 221 */ |
| 169 VMS__add_request_to_slave( SlaveReqst req, VMSProcr callingPr ) | 222 inline void |
| 170 { VMSProcr slave; | 223 VMS__add_request_to_slave( SlaveReqst req, VirtProcr callingPr ) |
| 171 slave = callingPr->workUnit->currSlave | 224 { |
| 172 req->nextRequest = callingPr->workUnit->currSlave->requests = req; | 225 req->nextRequest = callingPr->requests; |
| 173 } | 226 callingPr->requests = req; |
| 174 | 227 } |
| 175 | 228 |
| 176 | 229 |
| 230 |
