annotate MasterLoop.c @ 43:e3b78148e9de

test after moving directories around
author Me
date Sat, 11 Sep 2010 07:40:44 -0700
parents cf3e9238aeb0
children 054006c26b92 8f7141a9272e
rev   line source
Me@0 1 /*
Me@38 2 * Copyright 2010 OpenSourceStewardshipFoundation
Me@43 3 *
Me@0 4 * Licensed under BSD
Me@0 5 */
Me@0 6
Me@0 7
Me@0 8
Me@0 9 #include <stdio.h>
Me@0 10 #include <malloc.h>
Me@9 11 #include <stddef.h>
Me@0 12
Me@0 13 #include "VMS.h"
Me@0 14
Me@0 15
Me@0 16
Me@0 17 /*This code is animated by the virtual Master processor.
Me@0 18 *
Me@11 19 *Polls each sched slot exactly once, hands any requests made by a newly
Me@11 20 * done slave to the "request handler" plug-in function
Me@0 21 *
Me@11 22 *Any slots that need a virt procr assigned are given to the "schedule"
Me@11 23 * plug-in function, which tries to assign a virt procr (slave) to it.
Me@0 24 *
Me@11 25 *When all slots needing a processor have been given to the schedule plug-in,
Me@11 26 * a fraction of the procrs successfully scheduled are put into the
Me@11 27 * work queue, then a continuation of this function is put in, then the rest
Me@11 28 * of the virt procrs that were successfully scheduled.
Me@0 29 *
Me@11 30 *The first thing the continuation does is busy-wait until the previous
Me@11 31 * animation completes. This is because an (unlikely) continuation may
Me@11 32 * sneak through queue before previous continuation is done putting second
Me@11 33 * part of scheduled slaves in, which is the only race condition.
Me@0 34 *
Me@0 35 */
Me@0 36
Me@4 37 /*May 29, 2010 -- birth a Master during init so that first core loop to
Me@11 38 * start running gets it and does all the stuff for a newly born --
Me@11 39 * from then on, will be doing continuation, but do suspension self
Me@4 40 * directly at end of master loop
Me@4 41 *So VMS__init just births the master virtual processor same way it births
Me@4 42 * all the others -- then does any extra setup needed and puts it into the
Me@4 43 * work queue.
Me@4 44 *However means have to make masterEnv a global static volatile the same way
Me@31 45 * did with readyToAnimateQ in core loop. -- for performance, put the
Me@11 46 * jump to the core loop directly in here, and have it directly jump back.
Me@31 47 *
Me@31 48 *
Me@31 49 *Aug 18, 2010 -- Going to a separate MasterVP for each core, to see if this
Me@31 50 * avoids the suspected bug in the system stack that causes bizarre faults
Me@31 51 * at random places in the system code.
Me@31 52 *
Me@31 53 *So, this function is coupled to each of the MasterVPs, -- meaning this
Me@31 54 * function can't rely on a particular stack and frame -- each MasterVP that
Me@31 55 * animates this function has a different one.
Me@31 56 *
Me@31 57 *At this point, the masterLoop does not write itself into the queue anymore,
Me@31 58 * instead, the coreLoop acquires the masterLock when it has nothing to
Me@31 59 * animate, and then animates its own masterLoop. However, still try to put
Me@31 60 * several AppVPs into the queue to amortize the startup cost of switching
Me@31 61 * to the MasterVP. Note, don't have to worry about latency of requests much
Me@31 62 * because most requests generate work for same core -- only latency issue
Me@31 63 * is case when other cores starved and one core's requests generate work
Me@31 64 * for them -- so keep max in queue to 3 or 4..
Me@4 65 */
Me@31 66 void masterLoop( void *initData, VirtProcr *animatingPr )
Me@21 67 {
Me@31 68 int slotIdx;
Me@21 69 VirtProcr *schedVirtPr;
Me@31 70 SchedSlot *currSlot, **schedSlots;
Me@0 71 MasterEnv *masterEnv;
Me@31 72 VMSQueueStruc *readyToAnimateQ;
Me@4 73
Me@0 74 SlaveScheduler slaveScheduler;
Me@0 75 RequestHandler requestHandler;
Me@31 76 void *semanticEnv;
Me@0 77
Me@31 78 int thisCoresIdx;
Me@31 79 VirtProcr *masterPr;
Me@31 80 volatile VirtProcr *volatileMasterPr;
Me@31 81
Me@31 82 volatileMasterPr = animatingPr;
Me@31 83 masterPr = volatileMasterPr; //used to force re-define after jmp
Me@31 84
Me@31 85 //First animation of each MasterVP will in turn animate this part
Me@31 86 // of setup code.. (VP creator sets up the stack as if this function
Me@31 87 // was called normally, but actually get here by jmp)
Me@31 88 //So, setup values about stack ptr, jmp pt and all that
Me@4 89 masterPr->nextInstrPt = &&masterLoopStartPt;
Me@0 90
Me@26 91
Me@31 92 //Note, got rid of writing the stack and frame ptr up here, because
Me@31 93 // only one
Me@31 94 // core can ever animate a given MasterVP, so don't need to communicate
Me@31 95 // new frame and stack ptr to the MasterVP storage before a second
Me@31 96 // version of that MasterVP can get animated on a different core.
Me@31 97 //Also got rid of the busy-wait.
Me@26 98
Me@31 99
Me@4 100 masterLoopStartPt:
Me@38 101 //============================= MEASUREMENT STUFF ========================
Me@38 102 #ifdef MEAS__TIME_MASTER
Me@38 103 //Total Master time includes one coreloop time -- just assume the core
Me@38 104 // loop time is same for Master as for AppVPs, even though it will be
Me@41 105 // smaller due to high predictability of the fixed jmp.
Me@38 106 saveLowTimeStampCountInto( masterPr->startMasterTSCLow );
Me@38 107 #endif
Me@38 108 //========================================================================
Me@0 109
Me@31 110 masterEnv = _VMSMasterEnv;
Me@4 111
Me@31 112 //TODO: check that compiles so that always re-define from frame-storage
Me@31 113 masterPr = volatileMasterPr; //just to make sure after jmp
Me@31 114 thisCoresIdx = masterPr->coreAnimatedBy;
Me@31 115 readyToAnimateQ = masterEnv->readyToAnimateQs[thisCoresIdx];
Me@31 116 schedSlots = masterEnv->allSchedSlots[thisCoresIdx];
Me@4 117
Me@0 118 requestHandler = masterEnv->requestHandler;
Me@0 119 slaveScheduler = masterEnv->slaveScheduler;
Me@21 120 semanticEnv = masterEnv->semanticEnv;
Me@0 121
Me@0 122
Me@31 123 //Poll each slot's Done flag
Me@26 124 for( slotIdx = 0; slotIdx < NUM_SCHED_SLOTS; slotIdx++)
Me@0 125 {
Me@4 126 currSlot = schedSlots[ slotIdx ];
Me@0 127
Me@4 128 if( currSlot->workIsDone )
Me@0 129 {
Me@4 130 currSlot->workIsDone = FALSE;
Me@4 131 currSlot->needsProcrAssigned = TRUE;
Me@0 132
Me@0 133 //process requests from slave to master
Me@21 134 (*requestHandler)( currSlot->procrAssignedToSlot, semanticEnv );
Me@0 135 }
Me@4 136 if( currSlot->needsProcrAssigned )
Me@4 137 { //give slot a new virt procr
Me@21 138 schedVirtPr =
Me@31 139 (*slaveScheduler)( semanticEnv, thisCoresIdx );
Me@0 140
Me@21 141 if( schedVirtPr != NULL )
Me@21 142 { currSlot->procrAssignedToSlot = schedVirtPr;
Me@26 143 schedVirtPr->schedSlot = currSlot;
Me@26 144 currSlot->needsProcrAssigned = FALSE;
Me@4 145
Me@31 146 writeSRSWQ( schedVirtPr, readyToAnimateQ );
Me@0 147 }
Me@0 148 }
Me@0 149 }
Me@0 150
Me@26 151
Me@31 152 //Save stack ptr and frame, restore CoreLoop's stack and frame,
Me@31 153 // and clear the MasterLock
Me@21 154 //TODO: cafefully verify don't need to force saving anything to stack
Me@21 155 // before jumping back to core loop.
Me@31 156 void *stackPtrAddr, *framePtrAddr, *masterLockAddr;
Me@31 157 void *jmpPt, *coreLoopFramePtr, *coreLoopStackPtr;
Me@31 158
Me@21 159 stackPtrAddr = &(masterPr->stackPtr);
Me@21 160 framePtrAddr = &(masterPr->framePtr);
Me@31 161 masterLockAddr = &(_VMSMasterEnv->masterLock);
Me@21 162
Me@31 163 jmpPt = _VMSMasterEnv->coreLoopStartPt;
Me@21 164 coreLoopFramePtr = masterPr->coreLoopFramePtr;//need this only
Me@21 165 coreLoopStackPtr = masterPr->coreLoopStackPtr;//shouldn't need -- safety
Me@21 166
Me@38 167 #ifdef MEAS__TIME_MASTER
Me@38 168 saveLowTimeStampCountInto( masterPr->endMasterTSCLow );
Me@38 169 #endif
Me@38 170
Me@21 171 asm volatile("movl %0, %%eax; \
Me@21 172 movl %%esp, (%%eax); \
Me@21 173 movl %1, %%eax; \
Me@21 174 movl %%ebp, (%%eax); \
Me@21 175 movl %2, %%ebx; \
Me@21 176 movl %3, %%eax; \
Me@21 177 movl %4, %%esp; \
Me@21 178 movl %5, %%ebp; \
Me@21 179 movl $0x0, (%%ebx); \
Me@30 180 jmp %%eax;" \
Me@21 181 /* outputs */ : "=g" (stackPtrAddr), "=g" (framePtrAddr), \
Me@38 182 "=g"(masterLockAddr) \
Me@21 183 /* inputs */ : "g" (jmpPt), "g"(coreLoopStackPtr), "g"(coreLoopFramePtr)\
Me@21 184 /* clobber */ : "memory", "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi" \
Me@21 185 );//can probably make clobber list empty -- but safe for now
Me@0 186 }
Me@0 187
Me@0 188