annotate MasterLoop.c @ 11:e2de204909bf

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