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