| 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@0
|
9 #include <stdio.h>
|
|
Me@0
|
10 #include <malloc.h>
|
|
Me@0
|
11
|
|
Me@0
|
12 #include "VMS.h"
|
|
Me@0
|
13
|
|
Me@0
|
14
|
|
Me@0
|
15
|
|
Me@0
|
16 /*This code is animated by the virtual Master processor.
|
|
Me@0
|
17 *Note, it is animated on a different level in virtual processor hierarchy
|
|
Me@0
|
18 * than the CoreLoop -- this is the code pointed to in a work-unit that the
|
|
Me@0
|
19 * coreLoop jumps to
|
|
Me@0
|
20 *
|
|
Me@0
|
21 *Polls each virtual slave exactly once, hands any requests made by the slave
|
|
Me@0
|
22 * to the "request handler" plug-in function
|
|
Me@0
|
23 *
|
|
Me@0
|
24 *Any slaves that have no work-unit assigned are given to the "schedule"
|
|
Me@0
|
25 * plug-in function, which tries to assign a work-unit to it.
|
|
Me@0
|
26 *
|
|
Me@0
|
27 *When all slaves that need work-units have been given to the schedule plug-in,
|
|
Me@0
|
28 * half of the ones that were successfully scheduled are put into the work
|
|
Me@0
|
29 * queue, then a continuation of this function is put in, then the rest of the
|
|
Me@0
|
30 * slaves that were successfully scheduled.
|
|
Me@0
|
31 *
|
|
Me@0
|
32 *The first thing this function does is busy-wait until the previous work-unit
|
|
Me@0
|
33 * running this function is done. This ensures it doesn't overlap with
|
|
Me@0
|
34 * tail-end of previous -- IE, continuation may sneak through queue before
|
|
Me@0
|
35 * previous done putting second half of scheduled slaves in. This is the only
|
|
Me@0
|
36 * race condition.
|
|
Me@0
|
37 *
|
|
Me@0
|
38 */
|
|
Me@0
|
39
|
|
Me@0
|
40 void masterLoop( void *data )
|
|
Me@0
|
41 { bool8 success;
|
|
Me@0
|
42 int slaveIdx, numScheduled, numInFirstHalf, schedSlaveIdx;
|
|
Me@0
|
43 VMSProcr currSlave, *virtSlaves;
|
|
Me@0
|
44 MasterEnv *masterEnv;
|
|
Me@0
|
45 SlaveScheduler slaveScheduler;
|
|
Me@0
|
46 RequestHandler requestHandler;
|
|
Me@0
|
47
|
|
Me@0
|
48
|
|
Me@0
|
49 masterEnv = (MasterEnv *)data;
|
|
Me@0
|
50
|
|
Me@0
|
51 requestHandler = masterEnv->requestHandler;
|
|
Me@0
|
52 slaveScheduler = masterEnv->slaveScheduler;
|
|
Me@0
|
53 virtSlaves = masterEnv->virtSlaves;
|
|
Me@0
|
54
|
|
Me@0
|
55 //if another continuation of Master still running, busy-wait
|
|
Me@0
|
56 while( masterEnv->stillRunning ) /*busy wait*/ ;
|
|
Me@0
|
57
|
|
Me@0
|
58 //this is the only master running now, set flag again
|
|
Me@0
|
59 masterEnv->stillRunning = 1;
|
|
Me@0
|
60
|
|
Me@0
|
61 //prepare for scheduling
|
|
Me@0
|
62 masterEnv->numScheduled = 0;
|
|
Me@0
|
63
|
|
Me@0
|
64 //Poll each slave structure's Done flag
|
|
Me@0
|
65 for( slaveIdx = 0; slaveIdx < NUM_SLAVES; slaveIdx++)
|
|
Me@0
|
66 {
|
|
Me@0
|
67 currSlave = virtSlaves[ slaveIdx ];
|
|
Me@0
|
68
|
|
Me@0
|
69 if( currSlave->workIsDone )
|
|
Me@0
|
70 {
|
|
Me@0
|
71 currSlave->workIsDone = FALSE;
|
|
Me@0
|
72 currSlave->needsWorkAssigned = TRUE;
|
|
Me@0
|
73
|
|
Me@0
|
74 //process requests from slave to master
|
|
Me@0
|
75 (*requestHandler)( currSlave );
|
|
Me@0
|
76 }
|
|
Me@0
|
77 if( currSlave->needsWorkAssigned )
|
|
Me@0
|
78 { //give slave a new work-unit
|
|
Me@0
|
79 success =
|
|
Me@0
|
80 (*slaveScheduler)( currSlave, masterEnv );
|
|
Me@0
|
81
|
|
Me@0
|
82 if( success )
|
|
Me@0
|
83 { addToVect( currSlave, &(masterEnv->scheduledSlaves),
|
|
Me@0
|
84 &(masterEnv->numScheduled) );
|
|
Me@0
|
85 currSlave->needsWorkAssigned = FALSE;
|
|
Me@0
|
86 }
|
|
Me@0
|
87 }
|
|
Me@0
|
88 }
|
|
Me@0
|
89
|
|
Me@0
|
90 //put half scheduled slaves in, then continuation, then other half
|
|
Me@0
|
91 VMSProcr **scheduledSlaves;
|
|
Me@0
|
92 numInFirstHalf = masterEnv->numScheduled / 2;
|
|
Me@0
|
93 scheduledSlaves = masterEnv->scheduledSlaves;
|
|
Me@0
|
94 for( schedSlaveIdx = 0; schedSlaveIdx < numInFirstHalf; schedSlaveIdx++)
|
|
Me@0
|
95 {
|
|
Me@0
|
96 writeQ( scheduledSlaves[ schedSlaveIdx ], workQ );
|
|
Me@0
|
97 }
|
|
Me@0
|
98
|
|
Me@0
|
99 //enqueue continuation of this loop
|
|
Me@0
|
100 // note that After this enqueue, continuation might sneak through
|
|
Me@0
|
101 writeQ( masterEnv->masterWorkUnit, workQ );
|
|
Me@0
|
102 for( schedSlaveIdx = numInFirstHalf;
|
|
Me@0
|
103 schedSlaveIdx < numScheduled;
|
|
Me@0
|
104 schedSlaveIdx++)
|
|
Me@0
|
105 {
|
|
Me@0
|
106 writeQ( scheduledSlaves[ schedSlaveIdx ]->workUnitToDo, workQ );
|
|
Me@0
|
107 }
|
|
Me@0
|
108
|
|
Me@0
|
109 //all done, so okay for continuation to proceed
|
|
Me@0
|
110 masterEnv->stillRunning = 0;
|
|
Me@0
|
111 }
|
|
Me@0
|
112
|
|
Me@0
|
113
|