annotate MasterLoop.c @ 9:a87d02855dee

Compiles -- with win thds -- still debugging assembly
author Me
date Tue, 01 Jun 2010 05:33:40 -0700
parents ca61f77ed417
children e2de204909bf
rev   line source
Me@0 1 /*
Me@0 2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
Me@0 3 *
Me@0 4 * Licensed under BSD
Me@0 5 */
Me@0 6
Me@0 7
Me@0 8
Me@9 9 #include <windows.h>
Me@0 10 #include <stdio.h>
Me@0 11 #include <malloc.h>
Me@9 12 #include <stddef.h>
Me@0 13
Me@0 14 #include "VMS.h"
Me@0 15
Me@0 16
Me@0 17
Me@0 18 /*This code is animated by the virtual Master processor.
Me@0 19 *Note, it is animated on a different level in virtual processor hierarchy
Me@0 20 * than the CoreLoop -- this is the code pointed to in a work-unit that the
Me@0 21 * coreLoop jumps to
Me@0 22 *
Me@0 23 *Polls each virtual slave exactly once, hands any requests made by the slave
Me@0 24 * to the "request handler" plug-in function
Me@0 25 *
Me@0 26 *Any slaves that have no work-unit assigned are given to the "schedule"
Me@0 27 * plug-in function, which tries to assign a work-unit to it.
Me@0 28 *
Me@0 29 *When all slaves that need work-units have been given to the schedule plug-in,
Me@0 30 * half of the ones that were successfully scheduled are put into the work
Me@0 31 * queue, then a continuation of this function is put in, then the rest of the
Me@0 32 * slaves that were successfully scheduled.
Me@0 33 *
Me@0 34 *The first thing this function does is busy-wait until the previous work-unit
Me@0 35 * running this function is done. This ensures it doesn't overlap with
Me@0 36 * tail-end of previous -- IE, continuation may sneak through queue before
Me@0 37 * previous done putting second half of scheduled slaves in. This is the only
Me@0 38 * race condition.
Me@0 39 *
Me@0 40 */
Me@0 41
Me@4 42 /*May 29, 2010 -- birth a Master during init so that first core loop to
Me@4 43 * start running gets it and does all the stuff for a newly born
Me@4 44 * from then on, will be doing continuation -- but do suspension self
Me@4 45 * directly at end of master loop
Me@4 46 *So VMS__init just births the master virtual processor same way it births
Me@4 47 * all the others -- then does any extra setup needed and puts it into the
Me@4 48 * work queue.
Me@4 49 *However means have to make masterEnv a global static volatile the same way
Me@4 50 * did with workQ in core loop. -- for performance, put the
Me@4 51 * jump to core loop directly in here, and have it directly jump back.
Me@4 52 */
Me@4 53 void masterLoop( void *initData, VirtProcr *masterPr )
Me@0 54 { bool8 success;
Me@4 55 int slotIdx, numScheduled, numInFirstChunk, filledSlotIdx;
Me@4 56 SchedSlot *currSlot, **schedSlots, **filledSlots;
Me@0 57 MasterEnv *masterEnv;
Me@4 58 QueueStruc *workQ;
Me@4 59 // VirtProcr *masterPr;
Me@4 60 void *jmpPt;
Me@4 61
Me@0 62 SlaveScheduler slaveScheduler;
Me@0 63 RequestHandler requestHandler;
Me@0 64
Me@4 65 //this will run as the first virt processor in workQ, and will be a
Me@4 66 // new born -- so will do all the GCC-generated allocating space on
Me@4 67 // the stack owned by master virt procr -- and will run this last bit
Me@4 68 // of setup code..
Me@4 69 masterPr->nextInstrPt = &&masterLoopStartPt;
Me@0 70
Me@4 71
Me@4 72 masterLoopStartPt:
Me@0 73
Me@4 74 //if another reference to same Master VirtProcr still going, busy-wait
Me@4 75 //Could put this lower, but don't want to think about shared stack..
Me@4 76 while( masterEnv->stillRunning ) /*busy wait*/ ;
Me@4 77 //TODO: want to do busy-wait as assembly, to be sure stack not touched?
Me@4 78
Me@4 79 //this is the only master running now, set flag again
Me@4 80 masterEnv->stillRunning = TRUE;
Me@4 81
Me@4 82 //TODO: gdb -- check that a volatile _VMSMasterEnv and _VMSWorkQ means
Me@4 83 // all these will be re-filled every time jump here..
Me@4 84 workQ = _VMSWorkQ;
Me@4 85 masterEnv = _VMSMasterEnv;
Me@0 86 requestHandler = masterEnv->requestHandler;
Me@0 87 slaveScheduler = masterEnv->slaveScheduler;
Me@4 88 schedSlots = masterEnv->schedSlots;
Me@4 89 filledSlots = masterEnv->filledSlots;
Me@4 90 masterPr = masterEnv->masterVirtPr;
Me@0 91
Me@0 92
Me@0 93 //prepare for scheduling
Me@4 94 masterEnv->numFilled = 0;
Me@0 95
Me@4 96 //Poll each slot's Done flag -- slot 0 reseved for master, start at 1
Me@4 97 for( slotIdx = 1; slotIdx < NUM_SCHED_SLOTS; slotIdx++)
Me@0 98 {
Me@4 99 currSlot = schedSlots[ slotIdx ];
Me@0 100
Me@4 101 if( currSlot->workIsDone )
Me@0 102 {
Me@4 103 currSlot->workIsDone = FALSE;
Me@4 104 currSlot->needsProcrAssigned = TRUE;
Me@0 105
Me@0 106 //process requests from slave to master
Me@4 107 (*requestHandler)( currSlot->procrAssignedToSlot->requests );
Me@0 108 }
Me@4 109 if( currSlot->needsProcrAssigned )
Me@4 110 { //give slot a new virt procr
Me@0 111 success =
Me@4 112 (*slaveScheduler)( currSlot, masterEnv->semanticEnv );
Me@0 113
Me@0 114 if( success )
Me@4 115 { int numFilled = masterEnv->numFilled;
Me@4 116
Me@4 117 filledSlots[numFilled] = currSlot;
Me@4 118 masterEnv->numFilled += 1;
Me@4 119
Me@4 120 currSlot->needsProcrAssigned = FALSE;
Me@0 121 }
Me@0 122 }
Me@0 123 }
Me@0 124
Me@4 125 //put some scheduled slaves in, then continuation, then rest
Me@4 126 numInFirstChunk = masterEnv->numFilled / 2; //tweak this from experiments
Me@4 127 for( filledSlotIdx = 0; filledSlotIdx < numInFirstChunk; filledSlotIdx++)
Me@0 128 {
Me@4 129 writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ );
Me@0 130 }
Me@0 131
Me@0 132 //enqueue continuation of this loop
Me@0 133 // note that After this enqueue, continuation might sneak through
Me@4 134 writeQ( schedSlots[0]->procrAssignedToSlot, workQ );//master always slot 0
Me@4 135 for( filledSlotIdx = numInFirstChunk;
Me@4 136 filledSlotIdx < numScheduled;
Me@4 137 filledSlotIdx++)
Me@0 138 {
Me@4 139 writeQ( filledSlots[ filledSlotIdx ]->procrAssignedToSlot, workQ );
Me@0 140 }
Me@0 141
Me@4 142 masterEnv->numFilled = 0;
Me@4 143
Me@4 144 //Don't want code above to try to look at requests in masterVirtPr,
Me@4 145 // so leave workDone at FALSE, but do want it to schedule into
Me@4 146 // the slot, so set needs procr assigned to TRUE.
Me@4 147 masterPr->schedSlot->needsProcrAssigned = TRUE;
Me@4 148
Me@4 149 //Save stack ptr and frame -- don't need to, take out later, but safe
Me@4 150 // Also, wait to set stillRunning to FALSE until just before jump, to
Me@4 151 // protect stack might need to jmp directly to asm busy-wait to be
Me@4 152 // sure stack not touched
Me@4 153 //TODO: gdb check that busy-wait doesn't touch stack, so this is safe
Me@4 154 //don't need any regs to be valid when come back, so clobber list empty
Me@4 155 //TODO: gdb the jmp -- make sure it jumps through register or mem
Me@4 156 asm volatile("movl %%esp, %0; \
Me@4 157 movl %%ebp, %1; \
Me@4 158 movl $0x0, %2; \
Me@4 159 jmp %3 "
Me@4 160 /* outputs */ : "=m" (masterPr->stackPtr), "=m" (masterPr->framePtr),
Me@4 161 "=m" (masterEnv->stillRunning)
Me@4 162 /* inputs */ : "r" (masterPr->coreLoopStartPt)
Me@4 163 /* clobber */
Me@4 164 );
Me@0 165 }
Me@0 166
Me@0 167