diff MasterLoop.c @ 4:ca61f77ed417

Compiles with assembly
author Me
date Mon, 31 May 2010 15:24:42 -0700
parents a5fe730dfc2e
children a87d02855dee
line diff
     1.1 --- a/MasterLoop.c	Mon May 31 15:01:08 2010 -0700
     1.2 +++ b/MasterLoop.c	Mon May 31 15:24:42 2010 -0700
     1.3 @@ -37,77 +37,129 @@
     1.4   *
     1.5   */
     1.6  
     1.7 -void masterLoop( void *data )
     1.8 +/*May 29, 2010 -- birth a Master during init so that first core loop to
     1.9 + * start running gets it and does all the stuff for a newly born
    1.10 + * from then on, will be doing continuation -- but do suspension self
    1.11 + * directly at end of master loop
    1.12 + *So VMS__init just births the master virtual processor same way it births
    1.13 + * all the others -- then does any extra setup needed and puts it into the
    1.14 + * work queue.
    1.15 + *However means have to make masterEnv a global static volatile the same way
    1.16 + * did with workQ in core loop.  -- for performance, put the
    1.17 + * jump to core loop directly in here, and have it directly jump back.
    1.18 + */
    1.19 +void masterLoop( void *initData, VirtProcr *masterPr )
    1.20   { bool8 success;
    1.21 -   int slaveIdx, numScheduled, numInFirstHalf, schedSlaveIdx;
    1.22 -   VMSProcr        currSlave, *virtSlaves;
    1.23 +   int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx;
    1.24 +   SchedSlot      *currSlot, **schedSlots, **filledSlots;
    1.25     MasterEnv      *masterEnv;
    1.26 +   QueueStruc     *workQ;
    1.27 +//   VirtProcr      *masterPr;
    1.28 +   void           *jmpPt;
    1.29 +   
    1.30     SlaveScheduler  slaveScheduler;
    1.31     RequestHandler  requestHandler;
    1.32  
    1.33 +      //this will run as the first virt processor in workQ, and will be a
    1.34 +      // new born -- so will do all the GCC-generated allocating space on
    1.35 +      // the stack owned by master virt procr -- and will run this last bit
    1.36 +      // of setup code..
    1.37 +   masterPr->nextInstrPt = &&masterLoopStartPt;
    1.38  
    1.39 -   masterEnv = (MasterEnv *)data;
    1.40 + 
    1.41 +   masterLoopStartPt:
    1.42  
    1.43 +      //if another reference to same Master VirtProcr still going, busy-wait
    1.44 +      //Could put this lower, but don't want to think about shared stack..
    1.45 +   while( masterEnv->stillRunning ) /*busy wait*/ ;
    1.46 +      //TODO: want to do busy-wait as assembly, to be sure stack not touched?
    1.47 +   
    1.48 +      //this is the only master running now, set flag again
    1.49 +   masterEnv->stillRunning = TRUE;
    1.50 +
    1.51 +      //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means
    1.52 +      // all these will be re-filled every time jump here..
    1.53 +   workQ            = _VMSWorkQ;
    1.54 +   masterEnv        = _VMSMasterEnv;
    1.55     requestHandler   = masterEnv->requestHandler;
    1.56     slaveScheduler   = masterEnv->slaveScheduler;
    1.57 -   virtSlaves       = masterEnv->virtSlaves;
    1.58 +   schedSlots       = masterEnv->schedSlots;
    1.59 +   filledSlots      = masterEnv->filledSlots;
    1.60 +   masterPr         = masterEnv->masterVirtPr;
    1.61     
    1.62 -      //if another continuation of Master still running, busy-wait
    1.63 -   while( masterEnv->stillRunning ) /*busy wait*/ ;
    1.64 -
    1.65 -      //this is the only master running now, set flag again
    1.66 -   masterEnv->stillRunning = 1;
    1.67  
    1.68        //prepare for scheduling
    1.69 -   masterEnv->numScheduled = 0;
    1.70 +   masterEnv->numFilled = 0;
    1.71  
    1.72 -      //Poll each slave structure's Done flag
    1.73 -   for( slaveIdx = 0; slaveIdx < NUM_SLAVES; slaveIdx++)
    1.74 +      //Poll each slot's Done flag -- slot 0 reseved for master, start at 1
    1.75 +   for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++)
    1.76      {
    1.77 -      currSlave = virtSlaves[ slaveIdx ];
    1.78 +      currSlot = schedSlots[ slotIdx ];
    1.79  
    1.80 -      if( currSlave->workIsDone )
    1.81 +      if( currSlot->workIsDone )
    1.82         {
    1.83 -         currSlave->workIsDone        = FALSE;
    1.84 -         currSlave->needsWorkAssigned = TRUE;
    1.85 +         currSlot->workIsDone         = FALSE;
    1.86 +         currSlot->needsProcrAssigned = TRUE;
    1.87  
    1.88              //process requests from slave to master
    1.89 -         (*requestHandler)( currSlave );
    1.90 +         (*requestHandler)( currSlot->procrAssignedToSlot->requests );
    1.91         }
    1.92 -      if( currSlave->needsWorkAssigned )
    1.93 -       {    //give slave a new work-unit
    1.94 +      if( currSlot->needsProcrAssigned )
    1.95 +       {    //give slot a new virt procr
    1.96           success =
    1.97 -         (*slaveScheduler)( currSlave, masterEnv );
    1.98 +         (*slaveScheduler)( currSlot, masterEnv->semanticEnv );
    1.99           
   1.100           if( success )
   1.101 -          { addToVect( currSlave, &(masterEnv->scheduledSlaves),
   1.102 -                                  &(masterEnv->numScheduled) );
   1.103 -            currSlave->needsWorkAssigned = FALSE;
   1.104 +          { int numFilled = masterEnv->numFilled;
   1.105 +
   1.106 +            filledSlots[numFilled] = currSlot;
   1.107 +            masterEnv->numFilled += 1;
   1.108 +
   1.109 +            currSlot->needsProcrAssigned = FALSE;
   1.110            }
   1.111         }
   1.112      }
   1.113  
   1.114 -      //put half scheduled slaves in, then continuation, then other half
   1.115 -   VMSProcr **scheduledSlaves;
   1.116 -   numInFirstHalf = masterEnv->numScheduled / 2;
   1.117 -   scheduledSlaves = masterEnv->scheduledSlaves;
   1.118 -   for( schedSlaveIdx = 0; schedSlaveIdx < numInFirstHalf; schedSlaveIdx++)
   1.119 +      //put some scheduled slaves in, then continuation, then rest
   1.120 +   numInFirstChunk = masterEnv->numFilled / 2;  //tweak this from experiments
   1.121 +   for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++)
   1.122      {
   1.123 -      writeQ( scheduledSlaves[ schedSlaveIdx ], workQ );
   1.124 +      writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ );
   1.125      }
   1.126  
   1.127        //enqueue continuation of this loop
   1.128        // note that After this enqueue, continuation might sneak through
   1.129 -   writeQ( masterEnv->masterWorkUnit, workQ );
   1.130 -   for( schedSlaveIdx = numInFirstHalf; 
   1.131 -        schedSlaveIdx < numScheduled;
   1.132 -        schedSlaveIdx++)
   1.133 +   writeQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0
   1.134 +   for( filledSlotIdx = numInFirstChunk;
   1.135 +        filledSlotIdx < numScheduled;
   1.136 +        filledSlotIdx++)
   1.137      {
   1.138 -      writeQ( scheduledSlaves[ schedSlaveIdx ]->workUnitToDo, workQ );
   1.139 +      writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ );
   1.140      }
   1.141  
   1.142 -      //all done, so okay for continuation to proceed
   1.143 -   masterEnv->stillRunning = 0;
   1.144 +   masterEnv->numFilled = 0;
   1.145 +   
   1.146 +      //Don't want code above to try to look at requests in masterVirtPr,
   1.147 +      // so leave workDone at FALSE, but do want it to schedule into
   1.148 +      // the slot, so set needs procr assigned to TRUE.
   1.149 +   masterPr->schedSlot->needsProcrAssigned = TRUE;
   1.150 +
   1.151 +      //Save stack ptr and frame -- don't need to, take out later, but safe
   1.152 +      // Also, wait to set stillRunning to FALSE until just before jump, to
   1.153 +      // protect stack might need to jmp directly to asm busy-wait to be
   1.154 +      // sure stack not touched
   1.155 +      //TODO: gdb check that busy-wait doesn't touch stack, so this is safe
   1.156 +      //don't need any regs to be valid when come back, so clobber list empty
   1.157 +      //TODO: gdb the jmp -- make sure it jumps through register or mem
   1.158 +   asm volatile("movl %%esp, %0; \
   1.159 +                 movl %%ebp, %1; \
   1.160 +                 movl  $0x0, %2; \
   1.161 +                 jmp     %3      "
   1.162 +   /* outputs */ : "=m" (masterPr->stackPtr), "=m" (masterPr->framePtr),
   1.163 +                   "=m" (masterEnv->stillRunning)
   1.164 +   /* inputs  */ : "r"  (masterPr->coreLoopStartPt)
   1.165 +   /* clobber */ 
   1.166 +                );
   1.167   }
   1.168  
   1.169