annotate MasterLoop.c @ 18:734c665500e4

Kinda have test working -- assembly looks right for saving core loop frame and stack and restoring them But have a bug that looks timing-related, so thinking maybe some threads are going to completion? The whole test isn't quite right yet -- it throws exception because the suspended virtual processors never have a continuation put back into the workQ (is this right? Is that why it throws exception?) Want to move to full code to finish debugging
author Me
date Tue, 22 Jun 2010 12:37:43 -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