Mercurial > cgi-bin > hgwebdir.cgi > VMS > VMS_Implementations > VMS_impls > VMS__MC_shared_impl
diff 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 |
line diff
1.1 --- a/VMS.c Sat May 22 19:37:58 2010 -0700 1.2 +++ b/VMS.c Mon May 31 14:11:14 2010 -0700 1.3 @@ -41,60 +41,79 @@ 1.4 */ 1.5 //Global vars are all inside VMS.h 1.6 MasterEnv * 1.7 -init_VMS( ) 1.8 - { 1.9 +VMS__init( ) 1.10 + { MasterEnv *masterEnv; 1.11 + QueueStruc *workQ; 1.12 + 1.13 //Make the central work-queue 1.14 - workQ = makeQ(); 1.15 + _VMSWorkQ = makeQ(); 1.16 + workQ = _VMSWorkQ; 1.17 1.18 - masterEnv = malloc( sizeof(MasterEnv) ); 1.19 + _VMSMasterEnv = malloc( sizeof(MasterEnv) ); 1.20 + masterEnv = _VMSMasterEnv; 1.21 1.22 create_master( masterEnv ); 1.23 1.24 - create_slaves( masterEnv ); 1.25 + create_sched_slots( masterEnv ); 1.26 1.27 - //When coreLoops start up, the first thing 1.28 - writeQ( masterEnv->masterWorkUnit, workQ ); 1.29 + masterEnv->schedSlots[0]->needsProcrAssigned = FALSE; //never checked 1.30 + masterEnv->schedSlots[0]->workIsDone = FALSE; //never checked 1.31 + masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr; 1.32 + 1.33 + //First core loop to start up gets this, which will schedule seed Pr 1.34 + //TODO: debug: check address of masterVirtPr 1.35 + writeQ( &(masterEnv->masterVirtPr), workQ ); 1.36 } 1.37 1.38 1.39 1.40 -/*Fill up the virtual master data structure, which is already alloc'd in the 1.41 - * masterEnv. 1.42 - *The virtual Master is the same structure as a virtual slave, but it 1.43 - * isn't in the array of virtual slaves. 1.44 - * The reason it's the same structure is so that the coreLoop doesn't 1.45 - * have to differentiate -- all work units are assigned to a VMSProcr, and 1.46 - * the core loop treats them all the same way, whether it's the virtual 1.47 - * master continuation or a slave's work-unit. 1.48 - *Note: masterLoop is jumped into an back out of, so have to be careful with 1.49 - * register usage and saving all persistent-across-calls state to masterEnv 1.50 +/*Fill up the master VirtProcr data structure, which is already alloc'd 1.51 + * in the masterEnv. 1.52 + * The coreLoop treats master virt pr same as the slave virt processors 1.53 + * 1.54 + *The first time it runs, will jump to the function ptr so have to, in here, 1.55 + * create the stack, which will be used by the plug-in functions, and set 1.56 + * up __cdecl just like do for the other virtual processors. 1.57 */ 1.58 void 1.59 create_master( MasterEnv *masterEnv ) 1.60 - { VMSProcr virtMaster; 1.61 + { VirtProcr masterPr; 1.62 + char * stackLocs, stackPtr; 1.63 1.64 - virtMaster = &(masterEnv->virtMaster); 1.65 - virtMaster->workUnitToDo = malloc( sizeof( WorkUnit ) ); 1.66 - virtMaster->workUnitToDo->workData = masterEnv; 1.67 - //TODO: figure out call structure: what GCC will do with regs 1.68 - // will jump to the masterLoop from the coreLoop -- what regs need 1.69 - // saving, from before jump to after -- and what reg to put masterEnv 1.70 - // pointer in when jump to masterLoop 1.71 - virtMaster->workUnitToDo->addrToJumpTo = &masterLoop; 1.72 - virtMaster->workUnitToDo->slaveAssignedTo = virtMaster; 1.73 + //TODO: debug this to be sure got addr of struct in masterEnv correctly 1.74 + masterPr = &(masterEnv->masterVirtPr); 1.75 + masterPr->initialData = masterEnv; 1.76 + 1.77 + masterPr->nextInstrPt = &masterLoop; 1.78 + 1.79 + //alloc stack locations, make stackPtr be the last addr in the locs, 1.80 + // minus room for the two parameters. Put initData at stackPtr, 1.81 + // animatingPr just above 1.82 + stackLocs = malloc( 0x100000 ); //1 meg stack -- default Win thread's size 1.83 + stackPtr = ( (char *)stackLocs + 0x100000 - 0x8 ); 1.84 + masterPr->stackPtr = stackPtr; 1.85 + masterPr->framePtr = stackPtr; 1.86 + asm volatile("movl %0, %%esp; 1.87 + movl %1, (%%esp); 1.88 + movl %2, $0x4(%%esp); 1.89 + movl %%esp, %%ebp; " /*framePtr in ebp never used*/ 1.90 + /* outputs */ : 1.91 + /* inputs */ : "g" (stackPtr), "g" (initData), "g" (animPr) 1.92 + /* clobber */ : 1.93 + ); 1.94 } 1.95 1.96 void 1.97 -create_slaves( MasterEnv *masterEnv ) 1.98 - { VMSProcr *virtSlaves; 1.99 +create_sched_slots( MasterEnv *masterEnv ) 1.100 + { SchedSlot *slots; 1.101 int i; 1.102 1.103 - virtSlaves = masterEnv->virtSlaves; //TODO: make sure this is right 1.104 - for( i = 0; i < NUM_SLAVES; i++ ) 1.105 + slots = masterEnv->schedSlots; //TODO: make sure this is right 1.106 + for( i = 0; i < NUM_SCHED_SLOTS; i++ ) 1.107 { 1.108 - //Set state to mean "everything done, schedule work to slave" 1.109 - virtSlaves[i].workIsDone = FALSE; 1.110 - virtSlaves[i].needsWorkAssigned = TRUE; 1.111 + //Set state to mean "handling requests done, slot needs filling" 1.112 + slots[i].workIsDone = FALSE; 1.113 + slots[i].needsProcrAssigned = TRUE; 1.114 } 1.115 } 1.116 1.117 @@ -113,7 +132,7 @@ 1.118 for( coreIdx=0; coreIdx < NUM_WORKERS; coreIdx++ ) 1.119 { 1.120 thdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) ); 1.121 - thdParams[coreIdx]->workQ = workQ; 1.122 + thdParams[coreIdx]->workQ = _VMSWorkQ; 1.123 thdParams[coreIdx]->id = coreIdx; 1.124 1.125 //Now make and start thd.. the coreLoopThds entry 1.126 @@ -143,22 +162,56 @@ 1.127 * there, and will get passed along, inside the request handler, to the 1.128 * next work-unit for that procr. 1.129 */ 1.130 -VMS__save_ret_and_jump_to_CoreLoop( callingPr ) 1.131 - { 1.132 - //TODO: figure out how to save the addr of a label into a mem loc 1.133 - //NOTE: because resume pt is inside the VMS fn, it's always the same, no 1.134 - // matter what the semantic layer is, no matter what semantic libr called. 1.135 - callingPr->resumePt = &resumeNextWorkUnitPt; 1.136 - save_processor_state_in( callingPr ); //save x86 regs, if GCC needs it to 1.137 - coreLoopRetPt = callingPr->coreLoopRetPt; 1.138 - //TODO: figure out how to do jump correctly -- target addr is constant 1.139 - asm( jmp coreLoopRetPt ); 1.140 +VMS__suspend_processor( VirtProcr *callingPr ) 1.141 + { void *jmpPt; 1.142 1.143 -resumeNextWorkUnitPt: 1.144 + callingPr->nextInstrPt = &&ResumePt; 1.145 + 1.146 + //return ownership of the virt procr and sched slot to Master virt pr 1.147 + callingPr->schedSlot->workIsDone = TRUE; 1.148 + 1.149 + jmpPt = callingPr->coreLoopStartPt; 1.150 + 1.151 + //put all regs in the clobber list to make sure GCC has saved all 1.152 + // so safe to jump to core loop, where they *will* get clobbered 1.153 + asm volatile("movl %%esp, %0; 1.154 + movl %%ebp, %1; 1.155 + jmp %2 " 1.156 + /* outputs */ : "=m" (currPr->stackPtr), "=m" (currPr->framePtr) 1.157 + /* inputs */ : "g" (jmpPt) 1.158 + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" 1.159 + ); 1.160 + 1.161 +ResumePt: 1.162 return; 1.163 } 1.164 1.165 1.166 +/*Create stack, then create __cdecl structure on it and put initialData and 1.167 + * pointer to the new structure instance into the parameter positions on 1.168 + * the stack 1.169 + *Then put function pointer into nextInstrPt -- the stack is setup in std 1.170 + * call structure, so jumping to function ptr is same as a GCC generated 1.171 + * function call 1.172 + *No need to save registers on old stack frame, because there's no old 1.173 + * animator state to return to -- 1.174 + * 1.175 + */ 1.176 +VirtProcr * 1.177 +VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ) 1.178 + { VirtProcr newPr; 1.179 + 1.180 + newPr = malloc( sizeof(VirtProcr) ); 1.181 + newPr->nextInstrPt = fnPtr; 1.182 + newPr->initialData = initialData; 1.183 + newPr->stackPtr = createNewStack(); 1.184 + newPr->framePtr = newPr->stackPtr; 1.185 + put params onto stack and setup __cdecl call structure 1.186 + 1.187 + return newPr; 1.188 + } 1.189 + 1.190 + 1.191 /*The semantic virt procr is available in the request sent from the slave 1.192 * 1.193 * The request handler has to add the work-unit created to the semantic 1.194 @@ -166,10 +219,11 @@ 1.195 * work-unit -- means the procr data struc is available in the request sent 1.196 * from the slave, from which the new work-unit is generated.. 1.197 */ 1.198 -VMS__add_request_to_slave( SlaveReqst req, VMSProcr callingPr ) 1.199 - { VMSProcr slave; 1.200 - slave = callingPr->workUnit->currSlave 1.201 - req->nextRequest = callingPr->workUnit->currSlave->requests = req; 1.202 +inline void 1.203 +VMS__add_request_to_slave( SlaveReqst req, VirtProcr callingPr ) 1.204 + { 1.205 + req->nextRequest = callingPr->requests; 1.206 + callingPr->requests = req; 1.207 } 1.208 1.209
