changeset 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 02d5a446d506
files VMS.c
diffstat 1 files changed, 104 insertions(+), 50 deletions(-) [+]
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