# HG changeset patch # User Me # Date 1275340274 25200 # Node ID cf5007e51b96e04a5718b50ef61e9dde0b3567ee # Parent a5fe730dfc2ec53fc99b446f7ee59fa54e248cea In flux -- has PThread startup -- about to change to winblows threads diff -r a5fe730dfc2e -r cf5007e51b96 VMS.c --- a/VMS.c Sat May 22 19:37:58 2010 -0700 +++ b/VMS.c Mon May 31 14:11:14 2010 -0700 @@ -41,60 +41,79 @@ */ //Global vars are all inside VMS.h MasterEnv * -init_VMS( ) - { +VMS__init( ) + { MasterEnv *masterEnv; + QueueStruc *workQ; + //Make the central work-queue - workQ = makeQ(); + _VMSWorkQ = makeQ(); + workQ = _VMSWorkQ; - masterEnv = malloc( sizeof(MasterEnv) ); + _VMSMasterEnv = malloc( sizeof(MasterEnv) ); + masterEnv = _VMSMasterEnv; create_master( masterEnv ); - create_slaves( masterEnv ); + create_sched_slots( masterEnv ); - //When coreLoops start up, the first thing - writeQ( masterEnv->masterWorkUnit, workQ ); + masterEnv->schedSlots[0]->needsProcrAssigned = FALSE; //never checked + masterEnv->schedSlots[0]->workIsDone = FALSE; //never checked + masterEnv->schedSlots[0]->procrAssignedToSlot = masterEnv->masterVirtPr; + + //First core loop to start up gets this, which will schedule seed Pr + //TODO: debug: check address of masterVirtPr + writeQ( &(masterEnv->masterVirtPr), workQ ); } -/*Fill up the virtual master data structure, which is already alloc'd in the - * masterEnv. - *The virtual Master is the same structure as a virtual slave, but it - * isn't in the array of virtual slaves. - * The reason it's the same structure is so that the coreLoop doesn't - * have to differentiate -- all work units are assigned to a VMSProcr, and - * the core loop treats them all the same way, whether it's the virtual - * master continuation or a slave's work-unit. - *Note: masterLoop is jumped into an back out of, so have to be careful with - * register usage and saving all persistent-across-calls state to masterEnv +/*Fill up the master VirtProcr data structure, which is already alloc'd + * in the masterEnv. + * The coreLoop treats master virt pr same as the slave virt processors + * + *The first time it runs, will jump to the function ptr so have to, in here, + * create the stack, which will be used by the plug-in functions, and set + * up __cdecl just like do for the other virtual processors. */ void create_master( MasterEnv *masterEnv ) - { VMSProcr virtMaster; + { VirtProcr masterPr; + char * stackLocs, stackPtr; - virtMaster = &(masterEnv->virtMaster); - virtMaster->workUnitToDo = malloc( sizeof( WorkUnit ) ); - virtMaster->workUnitToDo->workData = masterEnv; - //TODO: figure out call structure: what GCC will do with regs - // will jump to the masterLoop from the coreLoop -- what regs need - // saving, from before jump to after -- and what reg to put masterEnv - // pointer in when jump to masterLoop - virtMaster->workUnitToDo->addrToJumpTo = &masterLoop; - virtMaster->workUnitToDo->slaveAssignedTo = virtMaster; + //TODO: debug this to be sure got addr of struct in masterEnv correctly + masterPr = &(masterEnv->masterVirtPr); + masterPr->initialData = masterEnv; + + masterPr->nextInstrPt = &masterLoop; + + //alloc stack locations, make stackPtr be the last addr in the locs, + // minus room for the two parameters. Put initData at stackPtr, + // animatingPr just above + stackLocs = malloc( 0x100000 ); //1 meg stack -- default Win thread's size + stackPtr = ( (char *)stackLocs + 0x100000 - 0x8 ); + masterPr->stackPtr = stackPtr; + masterPr->framePtr = stackPtr; + asm volatile("movl %0, %%esp; + movl %1, (%%esp); + movl %2, $0x4(%%esp); + movl %%esp, %%ebp; " /*framePtr in ebp never used*/ + /* outputs */ : + /* inputs */ : "g" (stackPtr), "g" (initData), "g" (animPr) + /* clobber */ : + ); } void -create_slaves( MasterEnv *masterEnv ) - { VMSProcr *virtSlaves; +create_sched_slots( MasterEnv *masterEnv ) + { SchedSlot *slots; int i; - virtSlaves = masterEnv->virtSlaves; //TODO: make sure this is right - for( i = 0; i < NUM_SLAVES; i++ ) + slots = masterEnv->schedSlots; //TODO: make sure this is right + for( i = 0; i < NUM_SCHED_SLOTS; i++ ) { - //Set state to mean "everything done, schedule work to slave" - virtSlaves[i].workIsDone = FALSE; - virtSlaves[i].needsWorkAssigned = TRUE; + //Set state to mean "handling requests done, slot needs filling" + slots[i].workIsDone = FALSE; + slots[i].needsProcrAssigned = TRUE; } } @@ -113,7 +132,7 @@ for( coreIdx=0; coreIdx < NUM_WORKERS; coreIdx++ ) { thdParams[coreIdx] = (ThdParams *)malloc( sizeof(ThdParams) ); - thdParams[coreIdx]->workQ = workQ; + thdParams[coreIdx]->workQ = _VMSWorkQ; thdParams[coreIdx]->id = coreIdx; //Now make and start thd.. the coreLoopThds entry @@ -143,22 +162,56 @@ * there, and will get passed along, inside the request handler, to the * next work-unit for that procr. */ -VMS__save_ret_and_jump_to_CoreLoop( callingPr ) - { - //TODO: figure out how to save the addr of a label into a mem loc - //NOTE: because resume pt is inside the VMS fn, it's always the same, no - // matter what the semantic layer is, no matter what semantic libr called. - callingPr->resumePt = &resumeNextWorkUnitPt; - save_processor_state_in( callingPr ); //save x86 regs, if GCC needs it to - coreLoopRetPt = callingPr->coreLoopRetPt; - //TODO: figure out how to do jump correctly -- target addr is constant - asm( jmp coreLoopRetPt ); +VMS__suspend_processor( VirtProcr *callingPr ) + { void *jmpPt; -resumeNextWorkUnitPt: + callingPr->nextInstrPt = &&ResumePt; + + //return ownership of the virt procr and sched slot to Master virt pr + callingPr->schedSlot->workIsDone = TRUE; + + jmpPt = callingPr->coreLoopStartPt; + + //put all regs in the clobber list to make sure GCC has saved all + // so safe to jump to core loop, where they *will* get clobbered + asm volatile("movl %%esp, %0; + movl %%ebp, %1; + jmp %2 " + /* outputs */ : "=m" (currPr->stackPtr), "=m" (currPr->framePtr) + /* inputs */ : "g" (jmpPt) + /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi","%esi" + ); + +ResumePt: return; } +/*Create stack, then create __cdecl structure on it and put initialData and + * pointer to the new structure instance into the parameter positions on + * the stack + *Then put function pointer into nextInstrPt -- the stack is setup in std + * call structure, so jumping to function ptr is same as a GCC generated + * function call + *No need to save registers on old stack frame, because there's no old + * animator state to return to -- + * + */ +VirtProcr * +VMS__create_procr( VirtProcrFnPtr fnPtr, void *initialData ) + { VirtProcr newPr; + + newPr = malloc( sizeof(VirtProcr) ); + newPr->nextInstrPt = fnPtr; + newPr->initialData = initialData; + newPr->stackPtr = createNewStack(); + newPr->framePtr = newPr->stackPtr; + put params onto stack and setup __cdecl call structure + + return newPr; + } + + /*The semantic virt procr is available in the request sent from the slave * * The request handler has to add the work-unit created to the semantic @@ -166,10 +219,11 @@ * work-unit -- means the procr data struc is available in the request sent * from the slave, from which the new work-unit is generated.. */ -VMS__add_request_to_slave( SlaveReqst req, VMSProcr callingPr ) - { VMSProcr slave; - slave = callingPr->workUnit->currSlave - req->nextRequest = callingPr->workUnit->currSlave->requests = req; +inline void +VMS__add_request_to_slave( SlaveReqst req, VirtProcr callingPr ) + { + req->nextRequest = callingPr->requests; + callingPr->requests = req; }