| rev |
line source |
|
seanhalle@29
|
1 /*
|
|
seanhalle@29
|
2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
|
|
seanhalle@29
|
3 *
|
|
seanhalle@29
|
4 * Licensed under BSD
|
|
seanhalle@29
|
5 */
|
|
seanhalle@29
|
6
|
|
seanhalle@29
|
7 #include <stdio.h>
|
|
seanhalle@29
|
8 #include <stdlib.h>
|
|
seanhalle@29
|
9
|
|
seanhalle@29
|
10 #include "VMS_impl/VMS.h"
|
|
seanhalle@29
|
11 #include "Vthread.h"
|
|
seanhalle@29
|
12 #include "Vthread_helper.h"
|
|
seanhalle@29
|
13 #include "C_Libraries/Queue_impl/PrivateQueue.h"
|
|
seanhalle@29
|
14 #include "C_Libraries/Hash_impl/PrivateHash.h"
|
|
seanhalle@29
|
15
|
|
seanhalle@29
|
16
|
|
seanhalle@29
|
17 //==========================================================================
|
|
seanhalle@29
|
18
|
|
seanhalle@29
|
19 void
|
|
seanhalle@29
|
20 Vthread__init();
|
|
seanhalle@29
|
21
|
|
seanhalle@29
|
22 void
|
|
seanhalle@29
|
23 Vthread__init_Seq();
|
|
seanhalle@29
|
24
|
|
seanhalle@29
|
25 void
|
|
seanhalle@29
|
26 Vthread__init_Helper();
|
|
seanhalle@29
|
27
|
|
seanhalle@29
|
28
|
|
seanhalle@29
|
29 //===========================================================================
|
|
seanhalle@29
|
30
|
|
seanhalle@29
|
31 /*These are the library functions *called in the application*
|
|
seanhalle@29
|
32 *
|
|
seanhalle@29
|
33 */
|
|
seanhalle@29
|
34
|
|
seanhalle@29
|
35
|
|
seanhalle@29
|
36
|
|
seanhalle@29
|
37 //===========================================================================
|
|
seanhalle@29
|
38
|
|
seanhalle@29
|
39 inline int32
|
|
seanhalle@29
|
40 Vthread__giveMinWorkUnitCycles( float32 percentOverhead )
|
|
seanhalle@29
|
41 {
|
|
seanhalle@29
|
42 return MIN_WORK_UNIT_CYCLES;
|
|
seanhalle@29
|
43 }
|
|
seanhalle@29
|
44
|
|
seanhalle@29
|
45 inline int32
|
|
seanhalle@29
|
46 Vthread__giveIdealNumWorkUnits()
|
|
seanhalle@29
|
47 {
|
|
seanhalle@29
|
48 return NUM_SCHED_SLOTS * NUM_CORES;
|
|
seanhalle@29
|
49 }
|
|
seanhalle@29
|
50
|
|
seanhalle@29
|
51 inline int32
|
|
seanhalle@29
|
52 Vthread__give_number_of_cores_to_schedule_onto()
|
|
seanhalle@29
|
53 {
|
|
seanhalle@29
|
54 return NUM_CORES;
|
|
seanhalle@29
|
55 }
|
|
seanhalle@29
|
56
|
|
seanhalle@29
|
57 /*For now, use TSC -- later, make these two macros with assembly that first
|
|
seanhalle@29
|
58 * saves jump point, and second jumps back several times to get reliable time
|
|
seanhalle@29
|
59 */
|
|
seanhalle@29
|
60 inline void
|
|
seanhalle@29
|
61 Vthread__start_primitive()
|
|
seanhalle@29
|
62 { saveLowTimeStampCountInto( ((VthdSemEnv *)(_VMSMasterEnv->semanticEnv))->
|
|
seanhalle@29
|
63 primitiveStartTime );
|
|
seanhalle@29
|
64 }
|
|
seanhalle@29
|
65
|
|
seanhalle@29
|
66 /*Just quick and dirty for now -- make reliable later
|
|
seanhalle@29
|
67 * will want this to jump back several times -- to be sure cache is warm
|
|
seanhalle@29
|
68 * because don't want comm time included in calc-time measurement -- and
|
|
seanhalle@29
|
69 * also to throw out any "weird" values due to OS interrupt or TSC rollover
|
|
seanhalle@29
|
70 */
|
|
seanhalle@29
|
71 inline int32
|
|
seanhalle@29
|
72 Vthread__end_primitive_and_give_cycles()
|
|
seanhalle@29
|
73 { int32 endTime, startTime;
|
|
seanhalle@29
|
74 //TODO: fix by repeating time-measurement
|
|
seanhalle@29
|
75 saveLowTimeStampCountInto( endTime );
|
|
seanhalle@29
|
76 startTime=((VthdSemEnv*)(_VMSMasterEnv->semanticEnv))->primitiveStartTime;
|
|
seanhalle@29
|
77 return (endTime - startTime);
|
|
seanhalle@29
|
78 }
|
|
seanhalle@29
|
79
|
|
seanhalle@29
|
80
|
|
seanhalle@29
|
81
|
|
seanhalle@29
|
82 //===========================================================================
|
|
seanhalle@29
|
83
|
|
seanhalle@29
|
84 /*Re-use this in the entry-point fn
|
|
seanhalle@29
|
85 */
|
|
seanhalle@29
|
86 inline SlaveVP *
|
|
seanhalle@29
|
87 Vthread__create_slaveVP_helper( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@29
|
88 VthdSemEnv *semEnv, int32 coreToScheduleOnto )
|
|
seanhalle@29
|
89 { SlaveVP *newSlv;
|
|
seanhalle@29
|
90 VthdSemData *semData;
|
|
seanhalle@29
|
91
|
|
seanhalle@29
|
92 //This is running in master, so use internal version
|
|
seanhalle@29
|
93 newSlv = VMS_WL__create_slaveVP( fnPtr, initData );
|
|
seanhalle@29
|
94
|
|
seanhalle@29
|
95 semData = VMS_WL__malloc( sizeof(VthdSemData) );
|
|
seanhalle@29
|
96 semData->highestTransEntered = -1;
|
|
seanhalle@29
|
97 semData->lastTransEntered = NULL;
|
|
seanhalle@29
|
98
|
|
seanhalle@29
|
99 newSlv->semanticData = semData;
|
|
seanhalle@29
|
100
|
|
seanhalle@29
|
101 //=================== Assign new processor to a core =====================
|
|
seanhalle@29
|
102 #ifdef DEBUG__TURN_ON_SEQUENTIAL_MODE
|
|
seanhalle@29
|
103 newSlv->coreAnimatedBy = 0;
|
|
seanhalle@29
|
104
|
|
seanhalle@29
|
105 #else
|
|
seanhalle@29
|
106
|
|
seanhalle@29
|
107 if(coreToScheduleOnto < 0 || coreToScheduleOnto >= NUM_CORES )
|
|
seanhalle@29
|
108 { //out-of-range, so round-robin assignment
|
|
seanhalle@29
|
109 newSlv->coreAnimatedBy = semEnv->nextCoreToGetNewSlv;
|
|
seanhalle@29
|
110
|
|
seanhalle@29
|
111 if( semEnv->nextCoreToGetNewSlv >= NUM_CORES - 1 )
|
|
seanhalle@29
|
112 semEnv->nextCoreToGetNewSlv = 0;
|
|
seanhalle@29
|
113 else
|
|
seanhalle@29
|
114 semEnv->nextCoreToGetNewSlv += 1;
|
|
seanhalle@29
|
115 }
|
|
seanhalle@29
|
116 else //core num in-range, so use it
|
|
seanhalle@29
|
117 { newSlv->coreAnimatedBy = coreToScheduleOnto;
|
|
seanhalle@29
|
118 }
|
|
seanhalle@29
|
119 #endif
|
|
seanhalle@29
|
120 //========================================================================
|
|
seanhalle@29
|
121
|
|
seanhalle@29
|
122 return newSlv;
|
|
seanhalle@29
|
123 }
|
|
seanhalle@29
|
124
|
|
seanhalle@29
|
125
|
|
seanhalle@29
|
126 /*
|
|
seanhalle@29
|
127 */
|
|
seanhalle@29
|
128 inline SlaveVP *
|
|
seanhalle@29
|
129 Vthread__create_thread( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@29
|
130 SlaveVP *creatingSlv )
|
|
seanhalle@29
|
131 { VthdSemReq reqData;
|
|
seanhalle@29
|
132
|
|
seanhalle@29
|
133 //the semantic request data is on the stack and disappears when this
|
|
seanhalle@29
|
134 // call returns -- it's guaranteed to remain in the Slv's stack for as
|
|
seanhalle@29
|
135 // long as the Slv is suspended.
|
|
seanhalle@29
|
136 reqData.reqType = 0; //know the type because is a VMS create req
|
|
seanhalle@29
|
137 reqData.coreToScheduleOnto = -1; //means round-robin schedule
|
|
seanhalle@29
|
138 reqData.fnPtr = fnPtr;
|
|
seanhalle@29
|
139 reqData.initData = initData;
|
|
seanhalle@29
|
140 reqData.requestingSlv = creatingSlv;
|
|
seanhalle@29
|
141
|
|
seanhalle@29
|
142 VMS_WL__send_create_slaveVP_req( &reqData, creatingSlv );
|
|
seanhalle@29
|
143
|
|
seanhalle@29
|
144 return creatingSlv->dataRetFromReq;
|
|
seanhalle@29
|
145 }
|
|
seanhalle@29
|
146
|
|
seanhalle@29
|
147
|
|
seanhalle@29
|
148 inline SlaveVP *
|
|
seanhalle@29
|
149 Vthread__create_thread_with_affinity( TopLevelFnPtr fnPtr, void *initData,
|
|
seanhalle@29
|
150 SlaveVP *creatingSlv, int32 coreToScheduleOnto )
|
|
seanhalle@29
|
151 { VthdSemReq reqData;
|
|
seanhalle@29
|
152
|
|
seanhalle@29
|
153 //the semantic request data is on the stack and disappears when this
|
|
seanhalle@29
|
154 // call returns -- it's guaranteed to remain in the Slv's stack for as
|
|
seanhalle@29
|
155 // long as the Slv is suspended.
|
|
seanhalle@29
|
156 reqData.reqType = 0; //know type because in a VMS create req
|
|
seanhalle@29
|
157 reqData.coreToScheduleOnto = coreToScheduleOnto;
|
|
seanhalle@29
|
158 reqData.fnPtr = fnPtr;
|
|
seanhalle@29
|
159 reqData.initData = initData;
|
|
seanhalle@29
|
160 reqData.requestingSlv = creatingSlv;
|
|
seanhalle@29
|
161
|
|
seanhalle@29
|
162 VMS_WL__send_create_slaveVP_req( &reqData, creatingSlv );
|
|
seanhalle@29
|
163 }
|
|
seanhalle@29
|
164
|
|
seanhalle@29
|
165 inline void
|
|
seanhalle@29
|
166 Vthread__dissipate_thread( SlaveVP *procrToDissipate )
|
|
seanhalle@29
|
167 {
|
|
seanhalle@29
|
168 VMS_WL__send_dissipate_req( procrToDissipate );
|
|
seanhalle@29
|
169 }
|
|
seanhalle@29
|
170
|
|
seanhalle@29
|
171
|
|
seanhalle@29
|
172 //===========================================================================
|
|
seanhalle@29
|
173
|
|
seanhalle@29
|
174 void *
|
|
seanhalle@29
|
175 Vthread__malloc( size_t sizeToMalloc, SlaveVP *animSlv )
|
|
seanhalle@29
|
176 { VthdSemReq reqData;
|
|
seanhalle@29
|
177
|
|
seanhalle@29
|
178 reqData.reqType = malloc_req;
|
|
seanhalle@29
|
179 reqData.sizeToMalloc = sizeToMalloc;
|
|
seanhalle@29
|
180 reqData.requestingSlv = animSlv;
|
|
seanhalle@29
|
181
|
|
seanhalle@29
|
182 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
183
|
|
seanhalle@29
|
184 return animSlv->dataRetFromReq;
|
|
seanhalle@29
|
185 }
|
|
seanhalle@29
|
186
|
|
seanhalle@29
|
187
|
|
seanhalle@29
|
188 /*Sends request to Master, which does the work of freeing
|
|
seanhalle@29
|
189 */
|
|
seanhalle@29
|
190 void
|
|
seanhalle@29
|
191 Vthread__free( void *ptrToFree, SlaveVP *animSlv )
|
|
seanhalle@29
|
192 { VthdSemReq reqData;
|
|
seanhalle@29
|
193
|
|
seanhalle@29
|
194 reqData.reqType = free_req;
|
|
seanhalle@29
|
195 reqData.ptrToFree = ptrToFree;
|
|
seanhalle@29
|
196 reqData.requestingSlv = animSlv;
|
|
seanhalle@29
|
197
|
|
seanhalle@29
|
198 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
199 }
|
|
seanhalle@29
|
200
|
|
seanhalle@29
|
201
|
|
seanhalle@29
|
202 //===========================================================================
|
|
seanhalle@29
|
203
|
|
seanhalle@29
|
204 inline void
|
|
seanhalle@29
|
205 Vthread__set_globals_to( void *globals )
|
|
seanhalle@29
|
206 {
|
|
seanhalle@29
|
207 ((VthdSemEnv *)
|
|
seanhalle@29
|
208 (_VMSMasterEnv->semanticEnv))->applicationGlobals = globals;
|
|
seanhalle@29
|
209 }
|
|
seanhalle@29
|
210
|
|
seanhalle@29
|
211 inline void *
|
|
seanhalle@29
|
212 Vthread__give_globals()
|
|
seanhalle@29
|
213 {
|
|
seanhalle@29
|
214 return((VthdSemEnv *) (_VMSMasterEnv->semanticEnv))->applicationGlobals;
|
|
seanhalle@29
|
215 }
|
|
seanhalle@29
|
216
|
|
seanhalle@29
|
217
|
|
seanhalle@29
|
218 //===========================================================================
|
|
seanhalle@29
|
219
|
|
seanhalle@29
|
220 inline int32
|
|
seanhalle@29
|
221 Vthread__make_mutex( SlaveVP *animSlv )
|
|
seanhalle@29
|
222 { VthdSemReq reqData;
|
|
seanhalle@29
|
223
|
|
seanhalle@29
|
224 reqData.reqType = make_mutex;
|
|
seanhalle@29
|
225 reqData.requestingSlv = animSlv;
|
|
seanhalle@29
|
226
|
|
seanhalle@29
|
227 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
228
|
|
seanhalle@29
|
229 return (int32)animSlv->dataRetFromReq; //mutexid is 32bit wide
|
|
seanhalle@29
|
230 }
|
|
seanhalle@29
|
231
|
|
seanhalle@29
|
232 inline void
|
|
seanhalle@29
|
233 Vthread__mutex_lock( int32 mutexIdx, SlaveVP *acquiringSlv )
|
|
seanhalle@29
|
234 { VthdSemReq reqData;
|
|
seanhalle@29
|
235
|
|
seanhalle@29
|
236 reqData.reqType = mutex_lock;
|
|
seanhalle@29
|
237 reqData.mutexIdx = mutexIdx;
|
|
seanhalle@29
|
238 reqData.requestingSlv = acquiringSlv;
|
|
seanhalle@29
|
239
|
|
seanhalle@29
|
240 VMS_WL__send_sem_request( &reqData, acquiringSlv );
|
|
seanhalle@29
|
241 }
|
|
seanhalle@29
|
242
|
|
seanhalle@29
|
243 inline void
|
|
seanhalle@29
|
244 Vthread__mutex_unlock( int32 mutexIdx, SlaveVP *releasingSlv )
|
|
seanhalle@29
|
245 { VthdSemReq reqData;
|
|
seanhalle@29
|
246
|
|
seanhalle@29
|
247 reqData.reqType = mutex_unlock;
|
|
seanhalle@29
|
248 reqData.mutexIdx = mutexIdx;
|
|
seanhalle@29
|
249 reqData.requestingSlv = releasingSlv;
|
|
seanhalle@29
|
250
|
|
seanhalle@29
|
251 VMS_WL__send_sem_request( &reqData, releasingSlv );
|
|
seanhalle@29
|
252 }
|
|
seanhalle@29
|
253
|
|
seanhalle@29
|
254
|
|
seanhalle@29
|
255 //=======================
|
|
seanhalle@29
|
256 inline int32
|
|
seanhalle@29
|
257 Vthread__make_cond( int32 ownedMutexIdx, SlaveVP *animSlv)
|
|
seanhalle@29
|
258 { VthdSemReq reqData;
|
|
seanhalle@29
|
259
|
|
seanhalle@29
|
260 reqData.reqType = make_cond;
|
|
seanhalle@29
|
261 reqData.mutexIdx = ownedMutexIdx;
|
|
seanhalle@29
|
262 reqData.requestingSlv = animSlv;
|
|
seanhalle@29
|
263
|
|
seanhalle@29
|
264 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
265
|
|
seanhalle@29
|
266 return (int32)animSlv->dataRetFromReq; //condIdx is 32 bit wide
|
|
seanhalle@29
|
267 }
|
|
seanhalle@29
|
268
|
|
seanhalle@29
|
269 inline void
|
|
seanhalle@29
|
270 Vthread__cond_wait( int32 condIdx, SlaveVP *waitingSlv)
|
|
seanhalle@29
|
271 { VthdSemReq reqData;
|
|
seanhalle@29
|
272
|
|
seanhalle@29
|
273 reqData.reqType = cond_wait;
|
|
seanhalle@29
|
274 reqData.condIdx = condIdx;
|
|
seanhalle@29
|
275 reqData.requestingSlv = waitingSlv;
|
|
seanhalle@29
|
276
|
|
seanhalle@29
|
277 VMS_WL__send_sem_request( &reqData, waitingSlv );
|
|
seanhalle@29
|
278 }
|
|
seanhalle@29
|
279
|
|
seanhalle@29
|
280 inline void *
|
|
seanhalle@29
|
281 Vthread__cond_signal( int32 condIdx, SlaveVP *signallingSlv )
|
|
seanhalle@29
|
282 { VthdSemReq reqData;
|
|
seanhalle@29
|
283
|
|
seanhalle@29
|
284 reqData.reqType = cond_signal;
|
|
seanhalle@29
|
285 reqData.condIdx = condIdx;
|
|
seanhalle@29
|
286 reqData.requestingSlv = signallingSlv;
|
|
seanhalle@29
|
287
|
|
seanhalle@29
|
288 VMS_WL__send_sem_request( &reqData, signallingSlv );
|
|
seanhalle@29
|
289 }
|
|
seanhalle@29
|
290
|
|
seanhalle@29
|
291
|
|
seanhalle@29
|
292 //===========================================================================
|
|
seanhalle@29
|
293 //
|
|
seanhalle@29
|
294 /*A function singleton is a function whose body executes exactly once, on a
|
|
seanhalle@29
|
295 * single core, no matter how many times the fuction is called and no
|
|
seanhalle@29
|
296 * matter how many cores or the timing of cores calling it.
|
|
seanhalle@29
|
297 *
|
|
seanhalle@29
|
298 *A data singleton is a ticket attached to data. That ticket can be used
|
|
seanhalle@29
|
299 * to get the data through the function exactly once, no matter how many
|
|
seanhalle@29
|
300 * times the data is given to the function, and no matter the timing of
|
|
seanhalle@29
|
301 * trying to get the data through from different cores.
|
|
seanhalle@29
|
302 */
|
|
seanhalle@29
|
303
|
|
seanhalle@29
|
304 /*Fn singleton uses ID as index into array of singleton structs held in the
|
|
seanhalle@29
|
305 * semantic environment.
|
|
seanhalle@29
|
306 */
|
|
seanhalle@29
|
307 void
|
|
seanhalle@29
|
308 Vthread__start_fn_singleton( int32 singletonID, SlaveVP *animSlv )
|
|
seanhalle@29
|
309 {
|
|
seanhalle@29
|
310 VthdSemReq reqData;
|
|
seanhalle@29
|
311
|
|
seanhalle@29
|
312 //
|
|
seanhalle@29
|
313 reqData.reqType = singleton_fn_start;
|
|
seanhalle@29
|
314 reqData.singletonID = singletonID;
|
|
seanhalle@29
|
315
|
|
seanhalle@29
|
316 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
317 if( animSlv->dataRetFromReq != 0 ) //addr of matching end-singleton
|
|
seanhalle@29
|
318 {
|
|
seanhalle@29
|
319 VthdSemEnv *semEnv = VMS_int__give_sem_env_for( animSlv ); //not protected!
|
|
seanhalle@29
|
320 VMS_int__return_to_addr_in_ptd_to_loc(
|
|
seanhalle@29
|
321 &((semEnv->fnSingletons[singletonID]).savedRetAddr) );
|
|
seanhalle@29
|
322 }
|
|
seanhalle@29
|
323 }
|
|
seanhalle@29
|
324
|
|
seanhalle@29
|
325 /*Data singleton hands addr of loc holding a pointer to a singleton struct.
|
|
seanhalle@29
|
326 * The start_data_singleton makes the structure and puts its addr into the
|
|
seanhalle@29
|
327 * location.
|
|
seanhalle@29
|
328 */
|
|
seanhalle@29
|
329 void
|
|
seanhalle@29
|
330 Vthread__start_data_singleton( VthdSingleton *singleton, SlaveVP *animSlv )
|
|
seanhalle@29
|
331 {
|
|
seanhalle@29
|
332 VthdSemReq reqData;
|
|
seanhalle@29
|
333
|
|
seanhalle@29
|
334 if( singleton->savedRetAddr && singleton->hasFinished )
|
|
seanhalle@29
|
335 goto JmpToEndSingleton;
|
|
seanhalle@29
|
336
|
|
seanhalle@29
|
337 reqData.reqType = singleton_data_start;
|
|
seanhalle@29
|
338 reqData.singleton = singleton;
|
|
seanhalle@29
|
339
|
|
seanhalle@29
|
340 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
341 if( animSlv->dataRetFromReq ) //either 0 or end singleton's return addr
|
|
seanhalle@29
|
342 {
|
|
seanhalle@29
|
343 JmpToEndSingleton:
|
|
seanhalle@29
|
344 VMS_int__return_to_addr_in_ptd_to_loc(&(singleton->savedRetAddr));
|
|
seanhalle@29
|
345 }
|
|
seanhalle@29
|
346 //now, simply return
|
|
seanhalle@29
|
347 //will exit either from the start singleton call or the end-singleton call
|
|
seanhalle@29
|
348 }
|
|
seanhalle@29
|
349
|
|
seanhalle@29
|
350 /*Uses ID as index into array of flags. If flag already set, resumes from
|
|
seanhalle@29
|
351 * end-label. Else, sets flag and resumes normally.
|
|
seanhalle@29
|
352 *
|
|
seanhalle@29
|
353 *Note, this call cannot be inlined because the instr addr at the label
|
|
seanhalle@29
|
354 * inside is shared by all invocations of a given singleton ID.
|
|
seanhalle@29
|
355 */
|
|
seanhalle@29
|
356 void
|
|
seanhalle@29
|
357 Vthread__end_fn_singleton( int32 singletonID, SlaveVP *animSlv )
|
|
seanhalle@29
|
358 {
|
|
seanhalle@29
|
359 VthdSemReq reqData;
|
|
seanhalle@29
|
360
|
|
seanhalle@29
|
361 //don't need this addr until after at least one singleton has reached
|
|
seanhalle@29
|
362 // this function
|
|
seanhalle@29
|
363 VthdSemEnv *semEnv = VMS_int__give_sem_env_for( animSlv );
|
|
seanhalle@29
|
364 VMS_int__return_to_addr_in_ptd_to_loc(
|
|
seanhalle@29
|
365 &((semEnv->fnSingletons[singletonID]).savedRetAddr) );
|
|
seanhalle@29
|
366
|
|
seanhalle@29
|
367 reqData.reqType = singleton_fn_end;
|
|
seanhalle@29
|
368 reqData.singletonID = singletonID;
|
|
seanhalle@29
|
369
|
|
seanhalle@29
|
370 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
371 }
|
|
seanhalle@29
|
372
|
|
seanhalle@29
|
373 void
|
|
seanhalle@29
|
374 Vthread__end_data_singleton( VthdSingleton *singleton, SlaveVP *animSlv )
|
|
seanhalle@29
|
375 {
|
|
seanhalle@29
|
376 VthdSemReq reqData;
|
|
seanhalle@29
|
377
|
|
seanhalle@29
|
378 //don't need this addr until after singleton struct has reached
|
|
seanhalle@29
|
379 // this function for first time
|
|
seanhalle@29
|
380 //do assembly that saves the return addr of this fn call into the
|
|
seanhalle@29
|
381 // data singleton -- that data-singleton can only be given to exactly
|
|
seanhalle@29
|
382 // one instance in the code of this function. However, can use this
|
|
seanhalle@29
|
383 // function in different places for different data-singletons.
|
|
seanhalle@29
|
384
|
|
seanhalle@29
|
385 VMS_int__save_return_into_ptd_to_loc_then_do_ret(&(singleton->savedRetAddr));
|
|
seanhalle@29
|
386
|
|
seanhalle@29
|
387 reqData.reqType = singleton_data_end;
|
|
seanhalle@29
|
388 reqData.singleton = singleton;
|
|
seanhalle@29
|
389
|
|
seanhalle@29
|
390 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
391 }
|
|
seanhalle@29
|
392
|
|
seanhalle@29
|
393
|
|
seanhalle@29
|
394 /*This executes the function in the masterVP, so it executes in isolation
|
|
seanhalle@29
|
395 * from any other copies -- only one copy of the function can ever execute
|
|
seanhalle@29
|
396 * at a time.
|
|
seanhalle@29
|
397 *
|
|
seanhalle@29
|
398 *It suspends to the master, and the request handler takes the function
|
|
seanhalle@29
|
399 * pointer out of the request and calls it, then resumes the Slv.
|
|
seanhalle@29
|
400 *Only very short functions should be called this way -- for longer-running
|
|
seanhalle@29
|
401 * isolation, use transaction-start and transaction-end, which run the code
|
|
seanhalle@29
|
402 * between as work-code.
|
|
seanhalle@29
|
403 */
|
|
seanhalle@29
|
404 void
|
|
seanhalle@29
|
405 Vthread__animate_short_fn_in_isolation( PtrToAtomicFn ptrToFnToExecInMaster,
|
|
seanhalle@29
|
406 void *data, SlaveVP *animSlv )
|
|
seanhalle@29
|
407 {
|
|
seanhalle@29
|
408 VthdSemReq reqData;
|
|
seanhalle@29
|
409
|
|
seanhalle@29
|
410 //
|
|
seanhalle@29
|
411 reqData.reqType = atomic;
|
|
seanhalle@29
|
412 reqData.fnToExecInMaster = ptrToFnToExecInMaster;
|
|
seanhalle@29
|
413 reqData.dataForFn = data;
|
|
seanhalle@29
|
414
|
|
seanhalle@29
|
415 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
416 }
|
|
seanhalle@29
|
417
|
|
seanhalle@29
|
418
|
|
seanhalle@29
|
419 /*This suspends to the master.
|
|
seanhalle@29
|
420 *First, it looks at the Slv's data, to see the highest transactionID that Slv
|
|
seanhalle@29
|
421 * already has entered. If the current ID is not larger, it throws an
|
|
seanhalle@29
|
422 * exception stating a bug in the code. Otherwise it puts the current ID
|
|
seanhalle@29
|
423 * there, and adds the ID to a linked list of IDs entered -- the list is
|
|
seanhalle@29
|
424 * used to check that exits are properly ordered.
|
|
seanhalle@29
|
425 *Next it is uses transactionID as index into an array of transaction
|
|
seanhalle@29
|
426 * structures.
|
|
seanhalle@29
|
427 *If the "Slv_currently_executing" field is non-null, then put requesting Slv
|
|
seanhalle@29
|
428 * into queue in the struct. (At some point a holder will request
|
|
seanhalle@29
|
429 * end-transaction, which will take this Slv from the queue and resume it.)
|
|
seanhalle@29
|
430 *If NULL, then write requesting into the field and resume.
|
|
seanhalle@29
|
431 */
|
|
seanhalle@29
|
432 void
|
|
seanhalle@29
|
433 Vthread__start_transaction( int32 transactionID, SlaveVP *animSlv )
|
|
seanhalle@29
|
434 {
|
|
seanhalle@29
|
435 VthdSemReq reqData;
|
|
seanhalle@29
|
436
|
|
seanhalle@29
|
437 //
|
|
seanhalle@29
|
438 reqData.reqType = trans_start;
|
|
seanhalle@29
|
439 reqData.transID = transactionID;
|
|
seanhalle@29
|
440
|
|
seanhalle@29
|
441 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
442 }
|
|
seanhalle@29
|
443
|
|
seanhalle@29
|
444 /*This suspends to the master, then uses transactionID as index into an
|
|
seanhalle@29
|
445 * array of transaction structures.
|
|
seanhalle@29
|
446 *It looks at Slv_currently_executing to be sure it's same as requesting Slv.
|
|
seanhalle@29
|
447 * If different, throws an exception, stating there's a bug in the code.
|
|
seanhalle@29
|
448 *Next it looks at the queue in the structure.
|
|
seanhalle@29
|
449 *If it's empty, it sets Slv_currently_executing field to NULL and resumes.
|
|
seanhalle@29
|
450 *If something in, gets it, sets Slv_currently_executing to that Slv, then
|
|
seanhalle@29
|
451 * resumes both.
|
|
seanhalle@29
|
452 */
|
|
seanhalle@29
|
453 void
|
|
seanhalle@29
|
454 Vthread__end_transaction( int32 transactionID, SlaveVP *animSlv )
|
|
seanhalle@29
|
455 {
|
|
seanhalle@29
|
456 VthdSemReq reqData;
|
|
seanhalle@29
|
457
|
|
seanhalle@29
|
458 //
|
|
seanhalle@29
|
459 reqData.reqType = trans_end;
|
|
seanhalle@29
|
460 reqData.transID = transactionID;
|
|
seanhalle@29
|
461
|
|
seanhalle@29
|
462 VMS_WL__send_sem_request( &reqData, animSlv );
|
|
seanhalle@29
|
463 }
|
|
seanhalle@29
|
464 //===========================================================================
|