VMS/VMS_Implementations/SSR_impls/SSR__MC_shared_impl

view SSR_Request_Handlers.c @ 76:6647aea90477

commented out uses of SemEnv->lastReqType .. wasn't compiling..
author Sean Halle <seanhalle@yahoo.com>
date Sun, 15 Jul 2012 02:03:43 -0700
parents b73e4a6f3497
children 833b31a8abc1
line source
1 /*
2 * Copyright 2010 OpenSourceCodeStewardshipFoundation
3 *
4 * Licensed under BSD
5 */
7 #include <stdio.h>
8 #include <stdlib.h>
10 #include "VMS_impl/VMS.h"
11 #include "Queue_impl/PrivateQueue.h"
12 #include "Hash_impl/PrivateHash.h"
13 #include "SSR.h"
17 //=========================== Local Fn Prototypes ===========================
18 void
19 resume_slaveVP( SlaveVP *procr, SSRSemEnv *semEnv );
23 //===========================================================================
24 // Helpers
26 /*Only clone the elements of req used in these reqst handlers
27 */
28 SSRSemReq *
29 cloneReq( SSRSemReq *semReq )
30 { SSRSemReq *clonedReq;
32 clonedReq = VMS_PI__malloc( sizeof(SSRSemReq) );
33 clonedReq->reqType = semReq->reqType;
34 clonedReq->sendPr = semReq->sendPr;
35 clonedReq->msg = semReq->msg;
36 clonedReq->nextReqInHashEntry = NULL;
38 return clonedReq;
39 }
41 HashEntry *
42 giveEntryElseInsertReqst( char *key, SSRSemReq *semReq,
43 HashTable *commHashTbl )
44 { HashEntry *entry;
45 SSRSemReq *waitingReq;
47 entry = getEntryFromTable( (char *)key, commHashTbl );
48 if( entry == NULL )
49 { //no waiting sends or receives, so add this request and exit
50 // note: have to clone the request because it's on stack of sender
51 addValueIntoTable( key, cloneReq( semReq ), commHashTbl );
52 return NULL;
53 }
54 waitingReq = (SSRSemReq *)entry->content;
55 if( waitingReq == NULL ) //might happen when last waiting gets paired
56 { //no waiting sends or receives, so add this request and exit
57 entry->content = semReq;
58 return NULL;
59 }
60 return entry;
61 }
66 //===========================================================================
67 /*The semantic request has the receiving processor and the message type
68 *
69 *Note one value in this approach: without the extra VMS layer,
70 * the send and receive would happen in real time instead of virtual time,
71 * which would waste real time while one of them waited for other
72 *
73 *When successfully pair-up, transfer ownership of the sent data
74 * to the receiving processor
75 *
76 *Messages of a given Type have to be kept separate.. so need a separate
77 * entry in the hash table for each pair: receivePr, msgType
78 *
79 *Also, if same sender sends multiple before any get received, then need to
80 * stack the sends up -- even if a send waits until it's paired, several
81 * separate processors can send to the same receiver, and hashing on the
82 * receive processor, so they will stack up.
83 */
84 void
85 handleSendType( SSRSemReq *semReq, SSRSemEnv *semEnv )
86 { SlaveVP *sendPr, *receivePr;
87 int key[] = {0,0,0};
88 SSRSemReq *waitingReq;
89 HashEntry *entry;
90 HashTable *commHashTbl = semEnv->commHashTbl;
92 DEBUG__printf1(dbgRqstHdlr,"SendType request from processor %d",semReq->sendPr->slaveID)
94 receivePr = semReq->receivePr; //For "send", know both send & recv procrs
95 sendPr = semReq->sendPr;
97 //TODO: handle transfer of msg-locs ownership
98 //TODO: hash table implemented such that using "addEntry" or
99 // "addValue" to table causes the *value* in old entry to be
100 // *freed* -- this is bad. Want to stack up values in a linked
101 // list when multiple have the same key.
103 //TODO: use a faster hash function -- see notes in intelligence gather
104 key[0] = (int)receivePr->slaveID;
105 key[1] = (int)(semReq->msgType);
106 //key[2] acts as the 0 that terminates the string
108 entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
109 if( entry == NULL ) return; //was just inserted
111 waitingReq = (SSRSemReq *)entry->content;
113 //At this point, know have waiting request(s) -- either sends or recv
114 //Note, can only have max of one receive waiting, and cannot have both
115 // sends and receives waiting (they would have paired off)
116 // but can have multiple sends from diff sending VPs, all same msg-type
117 if( waitingReq->reqType == send_type )
118 { //waiting request is another send, so stack this up on list
119 // but first clone the sending request so it persists.
120 SSRSemReq *clonedReq = cloneReq( semReq );
121 clonedReq-> nextReqInHashEntry = waitingReq->nextReqInHashEntry;
122 waitingReq->nextReqInHashEntry = clonedReq;
123 DEBUG__printf2( dbgRqstHdlr, "linked requests: %p, %p ", clonedReq,\
124 waitingReq )
125 return;
126 }
127 else
128 {
129 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
130 Dependency newd;
131 newd.from_vp = sendPr->slaveID;
132 newd.from_task = sendPr->assignCount;
133 newd.to_vp = receivePr->slaveID;
134 newd.to_task = receivePr->assignCount +1;
135 //(newd,semEnv->commDependenciesList);
136 addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList);
137 int32 groupId = semReq->msgType;
138 if(semEnv->ntonGroupsInfo->numInArray <= groupId){
139 makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId);
140 }
141 if(semEnv->ntonGroups[groupId] == NULL){
142 semEnv->ntonGroups[groupId] = new_NtoN(groupId);
143 }
144 Unit u;
145 u.vp = sendPr->slaveID;
146 u.task = sendPr->assignCount;
147 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders);
148 u.vp = receivePr->slaveID;
149 u.task = receivePr->assignCount +1;
150 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers);
151 #endif
153 //waiting request is a receive, so it pairs to this send
154 //First, remove the waiting receive request from the entry
155 entry->content = waitingReq->nextReqInHashEntry;
156 VMS_PI__free( waitingReq ); //Don't use contents -- so free it
158 if( entry->content == NULL )
159 { //TODO: mod hash table to double-link, so can delete entry from
160 // table without hashing the key and looking it up again
161 deleteEntryFromTable( entry->key, commHashTbl ); //frees hashEntry
162 }
164 //attach msg that's in this send request to receiving procr
165 // when comes back from suspend will have msg in dataRetFromReq
166 receivePr->dataRetFromReq = semReq->msg;
168 //bring both processors back from suspend
169 resume_slaveVP( sendPr, semEnv );
170 resume_slaveVP( receivePr, semEnv );
172 return;
173 }
174 }
177 /*Looks like can make single handler for both sends..
178 */
179 //TODO: combine both send handlers into single handler
180 void
181 handleSendFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv)
182 { SlaveVP *sendPr, *receivePr;
183 int key[] = {0,0,0};
184 SSRSemReq *waitingReq;
185 HashEntry *entry;
186 HashTable *commHashTbl = semEnv->commHashTbl;
188 DEBUG__printf2(dbgRqstHdlr,"SendFromTo request from processor %d to %d",semReq->sendPr->slaveID,semReq->receivePr->slaveID)
190 receivePr = semReq->receivePr; //For "send", know both send & recv procrs
191 sendPr = semReq->sendPr;
194 key[0] = (int)receivePr->slaveID;
195 key[1] = (int)sendPr->slaveID;
196 //key[2] acts at the 0 that terminates the string
198 entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
199 if( entry == NULL ) return; //was just inserted
201 waitingReq = (SSRSemReq *)entry->content;
203 //At this point, know have waiting request(s) -- either sends or recv
204 if( waitingReq->reqType == send_from_to )
205 { printf("\n ERROR: shouldn't be two send-from-tos waiting \n");
206 }
207 else
208 { //waiting request is a receive, so it completes pair with this send
209 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
210 Dependency newd;
211 newd.from_vp = sendPr->slaveID;
212 newd.from_task = sendPr->assignCount;
213 newd.to_vp = receivePr->slaveID;
214 newd.to_task = receivePr->assignCount +1;
215 //addToListOfArraysDependency(newd,semEnv->commDependenciesList);
216 addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);
217 #endif
218 //First, remove the waiting receive request from the entry
219 entry->content = waitingReq->nextReqInHashEntry;
220 VMS_PI__free( waitingReq ); //Don't use contents -- so free it
222 //can only be one waiting req for "from-to" semantics
223 if( entry->content != NULL )
224 {
225 printf("\nERROR in handleSendFromTo\n");
226 }
227 deleteEntryFromTable( entry->key, commHashTbl ); //frees HashEntry
229 //attach msg that's in this send request to receiving procr
230 // when comes back from suspend, will have msg in dataRetFromReq
231 receivePr->dataRetFromReq = semReq->msg;
233 //bring both processors back from suspend
234 resume_slaveVP( sendPr, semEnv );
235 resume_slaveVP( receivePr, semEnv );
237 return;
238 }
239 }
243 //============================== Receives ===========================
244 //
245 /*Removed this one for now, because forces either a search or going to a
246 * two-level hash table, where one level the key is the receivePr, in the
247 * other level, the key is the type.
248 *So, each dest procr that either does a receive_type or that a send_type
249 * targets it, would have a hash table created just for it and placed
250 * into the first-level hash table entry for that receive procr.
251 *Then, doing a receive_type first looks up entry for receive procr in first
252 * table, gets the type-table out of that entry, and does a second lookup
253 * in the type-table.
254 *Doing a receive from-to looks up in the first table, gets the second table
255 * hashed on "from" procr.
256 *Doing a receive_any looks up in the first table, then looks to see if
257 * either of the hash tables have any entries -- would then have to do a
258 * linear search through the hash-table's array for the first non-empty
259 * spot
260 *Yuck.
261 *
262 *Alternatively, could keep two hash tables updated all the time -- one that
263 * does the receive_type and receive_from_to and a second that does
264 * receive_any -- would only hash the second table by the receive procr.
265 * When remove from one table, keep back-links to both tables, so can also
266 * quickly remove from other table.
267 *Cost is doing two hash-table lookups for every insert.
268 * If ever add receive_any, looking like this second option easier and even
269 * less costly.
270 */
271 void
272 handleReceiveAny( SSRSemReq *semReq, SSRSemEnv *semEnv)
273 {
275 }
278 void
279 handleReceiveType( SSRSemReq *semReq, SSRSemEnv *semEnv)
280 { SlaveVP *sendPr, *receivePr;
281 int key[] = {0,0,0};
282 SSRSemReq *waitingReq;
283 HashEntry *entry;
284 HashTable *commHashTbl = semEnv->commHashTbl;
286 receivePr = semReq->receivePr;
288 DEBUG__printf1(dbgRqstHdlr,"ReceiveType request from processor %d",receivePr->slaveID)
290 key[0] = (int)receivePr->slaveID;
291 key[1] = (int)(semReq->msgType);
292 //key[2] acts as the 0 that terminates the string
295 entry = giveEntryElseInsertReqst((char*)key, semReq, commHashTbl);//clones
296 if( entry == NULL ) return; //was just inserted
298 waitingReq = (SSRSemReq *)entry->content; //previously cloned by insert
300 //At this point, know have waiting request(s) -- should be send(s)
301 if( waitingReq->reqType == send_type )
302 { //waiting request is a send, so pair it with this receive
303 //first, remove the waiting send request from the list in entry
305 entry->content = waitingReq->nextReqInHashEntry;
306 if( entry->content == NULL )
307 { deleteEntryFromTable( entry->key, commHashTbl ); //frees HashEntry
308 }
310 //attach msg that's in the send request to receiving procr
311 // when comes back from suspend, will have msg in dataRetFromReq
312 receivePr->dataRetFromReq = waitingReq->msg;
314 //bring both processors back from suspend
315 sendPr = waitingReq->sendPr;
316 VMS_PI__free( waitingReq );
318 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
319 Dependency newd;
320 newd.from_vp = sendPr->slaveID;
321 newd.from_task = sendPr->assignCount;
322 newd.to_vp = receivePr->slaveID;
323 newd.to_task = receivePr->assignCount +1;
324 //addToListOfArraysDependency(newd,semEnv->commDependenciesList);
325 addToListOfArrays(Dependency,newd,semEnv->dynDependenciesList);
326 int32 groupId = semReq->msgType;
327 if(semEnv->ntonGroupsInfo->numInArray <= groupId){
328 makeHighestDynArrayIndexBeAtLeast(semEnv->ntonGroupsInfo, groupId);
329 }
330 if(semEnv->ntonGroups[groupId] == NULL){
331 semEnv->ntonGroups[groupId] = new_NtoN(groupId);
332 }
333 Unit u;
334 u.vp = sendPr->slaveID;
335 u.task = sendPr->assignCount;
336 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->senders);
337 u.vp = receivePr->slaveID;
338 u.task = receivePr->assignCount +1;
339 addToListOfArrays(Unit,u,semEnv->ntonGroups[groupId]->receivers);
340 #endif
342 resume_slaveVP( sendPr, semEnv );
343 resume_slaveVP( receivePr, semEnv );
345 return;
346 }
347 printf("\nLang Impl Error: Should never be two waiting receives!\n");
348 }
351 /*
352 */
353 void
354 handleReceiveFromTo( SSRSemReq *semReq, SSRSemEnv *semEnv)
355 { SlaveVP *sendPr, *receivePr;
356 int key[] = {0,0,0};
357 SSRSemReq *waitingReq;
358 HashEntry *entry;
359 HashTable *commHashTbl = semEnv->commHashTbl;
361 DEBUG__printf2(dbgRqstHdlr,"ReceiveFromTo %d : %d",semReq->sendPr->slaveID,semReq->receivePr->slaveID)
363 receivePr = semReq->receivePr;
364 sendPr = semReq->sendPr; //for receive from-to, know send procr
366 key[0] = (int)receivePr->slaveID;
367 key[1] = (int)sendPr->slaveID;
368 //key[2] acts at the 0 that terminates the string
370 entry = giveEntryElseInsertReqst( (char *)key, semReq, commHashTbl);
371 if( entry == NULL ) return; //was just inserted
373 waitingReq = (SSRSemReq *)entry->content;
375 //At this point, know have waiting request(s) -- should be send(s)
376 if( waitingReq->reqType == send_from_to )
377 { //waiting request is a send, so pair it with this receive
378 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
379 Dependency newd;
380 newd.from_vp = sendPr->slaveID;
381 newd.from_task = sendPr->assignCount;
382 newd.to_vp = receivePr->slaveID;
383 newd.to_task = receivePr->assignCount +1;
384 //addToListOfArraysDependency(newd,semEnv->commDependenciesList);
385 addToListOfArrays(Dependency,newd,semEnv->commDependenciesList);
386 #endif
387 //For from-to, should only ever be a single reqst waiting tobe paird
388 entry->content = waitingReq->nextReqInHashEntry;
389 if( entry->content != NULL ) printf("\nERROR in handleRecvFromTo\n");
390 deleteEntryFromTable( entry->key, commHashTbl ); //frees entry too
392 //attach msg that's in the send request to receiving procr
393 // when comes back from suspend, will have msg in dataRetFromReq
394 receivePr->dataRetFromReq = waitingReq->msg;
396 //bring both processors back from suspend
397 sendPr = waitingReq->sendPr;
398 VMS_PI__free( waitingReq );
400 resume_slaveVP( sendPr, semEnv );
401 resume_slaveVP( receivePr, semEnv );
403 return;
404 }
405 printf("\nLang Impl Error: Should never be two waiting receives!\n");
406 }
410 //===============================================
411 void
412 handleTransferTo( SSRSemReq *semReq, SSRSemEnv *semEnv)
413 {
415 }
417 void
418 handleTransferOut( SSRSemReq *semReq, SSRSemEnv *semEnv)
419 {
421 }
424 /*
425 */
426 void
427 handleMalloc( SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv )
428 { void *ptr;
430 DEBUG__printf1(dbgRqstHdlr,"Malloc request from processor %d",requestingPr->slaveID)
431 // semEnv->lastReqType = 1;
432 ptr = VMS_PI__malloc( semReq->sizeToMalloc );
433 requestingPr->dataRetFromReq = ptr;
434 resume_slaveVP( requestingPr, semEnv );
435 }
437 /*
438 */
439 void
440 handleFree( SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv )
441 {
442 DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingPr->slaveID)
443 // semEnv->lastReqType = 1;
444 VMS_PI__free( semReq->ptrToFree );
445 resume_slaveVP( requestingPr, semEnv );
446 }
449 //===========================================================================
450 //
451 /*Uses ID as index into array of flags. If flag already set, resumes from
452 * end-label. Else, sets flag and resumes normally.
453 */
454 void inline
455 handleStartSingleton_helper( SSRSingleton *singleton, SlaveVP *reqstingPr,
456 SSRSemEnv *semEnv )
457 {
458 if( singleton->hasFinished )
459 { //the code that sets the flag to true first sets the end instr addr
460 reqstingPr->dataRetFromReq = singleton->endInstrAddr;
461 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
462 Dependency newd;
463 newd.from_vp = singleton->executingVp;
464 newd.from_task = singleton->executingTask;
465 newd.to_vp = reqstingPr->slaveID;
466 newd.to_task = reqstingPr->assignCount +1;
467 addToListOfArrays(Dependency,newd,semEnv->singletonDependenciesList);
468 #endif
469 resume_slaveVP( reqstingPr, semEnv );
470 return;
471 }
472 else if( singleton->hasBeenStarted )
473 { //singleton is in-progress in a diff slave, so wait for it to finish
474 writePrivQ(reqstingPr, singleton->waitQ );
475 return;
476 }
477 else
478 { //hasn't been started, so this is the first attempt at the singleton
479 singleton->hasBeenStarted = TRUE;
480 reqstingPr->dataRetFromReq = 0x0;
481 resume_slaveVP( reqstingPr, semEnv );
482 return;
483 }
484 }
485 void inline
486 handleStartFnSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
487 SSRSemEnv *semEnv )
488 { SSRSingleton *singleton;
489 DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingPr->slaveID)
491 singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
492 handleStartSingleton_helper( singleton, requestingPr, semEnv );
493 }
494 void inline
495 handleStartDataSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
496 SSRSemEnv *semEnv )
497 { SSRSingleton *singleton;
499 DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingPr->slaveID)
500 if( *(semReq->singletonPtrAddr) == NULL )
501 { singleton = VMS_PI__malloc( sizeof(SSRSingleton) );
502 singleton->waitQ = makeVMSQ();
503 singleton->endInstrAddr = 0x0;
504 singleton->hasBeenStarted = FALSE;
505 singleton->hasFinished = FALSE;
506 *(semReq->singletonPtrAddr) = singleton;
507 }
508 else
509 singleton = *(semReq->singletonPtrAddr);
510 handleStartSingleton_helper( singleton, requestingPr, semEnv );
511 }
514 void inline
515 handleEndSingleton_helper( SSRSingleton *singleton, SlaveVP *requestingPr,
516 SSRSemEnv *semEnv )
517 { PrivQueueStruc *waitQ;
518 int32 numWaiting, i;
519 SlaveVP *resumingPr;
521 if( singleton->hasFinished )
522 { //by definition, only one slave should ever be able to run end singleton
523 // so if this is true, is an error
524 ERROR1( "singleton code ran twice", requestingPr );
525 }
527 singleton->hasFinished = TRUE;
528 singleton->executingVp = requestingPr->slaveID;
529 singleton->executingTask = requestingPr->assignCount;
530 waitQ = singleton->waitQ;
531 numWaiting = numInPrivQ( waitQ );
532 for( i = 0; i < numWaiting; i++ )
533 { //they will resume inside start singleton, then jmp to end singleton
534 resumingPr = readPrivQ( waitQ );
535 resumingPr->dataRetFromReq = singleton->endInstrAddr;
536 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
537 Dependency newd;
538 newd.from_vp = singleton->executingVp;
539 newd.from_task = singleton->executingTask;
540 newd.to_vp = resumingPr->slaveID;
541 newd.to_task = resumingPr->assignCount +1;
542 addToListOfArrays(Dependency,newd,semEnv->singletonDependenciesList);
543 #endif
544 resume_slaveVP( resumingPr, semEnv );
545 }
547 resume_slaveVP( requestingPr, semEnv );
549 }
550 void inline
551 handleEndFnSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
552 SSRSemEnv *semEnv )
553 {
554 SSRSingleton *singleton;
556 DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingPr->slaveID)
558 singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
559 handleEndSingleton_helper( singleton, requestingPr, semEnv );
560 }
561 void inline
562 handleEndDataSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
563 SSRSemEnv *semEnv )
564 {
565 SSRSingleton *singleton;
567 DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingPr->slaveID)
569 singleton = *(semReq->singletonPtrAddr);
570 handleEndSingleton_helper( singleton, requestingPr, semEnv );
571 }
574 /*This executes the function in the masterVP, take the function
575 * pointer out of the request and call it, then resume the VP.
576 */
577 void
578 handleAtomic( SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv )
579 {
580 DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingPr->slaveID)
581 semReq->fnToExecInMaster( semReq->dataForFn );
582 resume_slaveVP( requestingPr, semEnv );
583 }
585 /*First, it looks at the VP's semantic data, to see the highest transactionID
586 * that VP
587 * already has entered. If the current ID is not larger, it throws an
588 * exception stating a bug in the code.
589 *Otherwise it puts the current ID
590 * there, and adds the ID to a linked list of IDs entered -- the list is
591 * used to check that exits are properly ordered.
592 *Next it is uses transactionID as index into an array of transaction
593 * structures.
594 *If the "VP_currently_executing" field is non-null, then put requesting VP
595 * into queue in the struct. (At some point a holder will request
596 * end-transaction, which will take this VP from the queue and resume it.)
597 *If NULL, then write requesting into the field and resume.
598 */
599 void
600 handleTransStart( SSRSemReq *semReq, SlaveVP *requestingPr,
601 SSRSemEnv *semEnv )
602 { SSRSemData *semData;
603 TransListElem *nextTransElem;
605 DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingPr->slaveID)
607 //check ordering of entering transactions is correct
608 semData = requestingPr->semanticData;
609 if( semData->highestTransEntered > semReq->transID )
610 { //throw VMS exception, which shuts down VMS.
611 VMS_PI__throw_exception( "transID smaller than prev", requestingPr, NULL);
612 }
613 //add this trans ID to the list of transactions entered -- check when
614 // end a transaction
615 semData->highestTransEntered = semReq->transID;
616 nextTransElem = VMS_PI__malloc( sizeof(TransListElem) );
617 nextTransElem->transID = semReq->transID;
618 nextTransElem->nextTrans = semData->lastTransEntered;
619 semData->lastTransEntered = nextTransElem;
621 //get the structure for this transaction ID
622 SSRTrans *
623 transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
625 if( transStruc->VPCurrentlyExecuting == NULL )
626 {
627 transStruc->VPCurrentlyExecuting = requestingPr;
628 resume_slaveVP( requestingPr, semEnv );
629 }
630 else
631 { //note, might make future things cleaner if save request with VP and
632 // add this trans ID to the linked list when gets out of queue.
633 // but don't need for now, and lazy..
634 writePrivQ( requestingPr, transStruc->waitingVPQ );
635 }
636 }
639 /*Use the trans ID to get the transaction structure from the array.
640 *Look at VP_currently_executing to be sure it's same as requesting VP.
641 * If different, throw an exception, stating there's a bug in the code.
642 *Next, take the first element off the list of entered transactions.
643 * Check to be sure the ending transaction is the same ID as the next on
644 * the list. If not, incorrectly nested so throw an exception.
645 *
646 *Next, get from the queue in the structure.
647 *If it's empty, set VP_currently_executing field to NULL and resume
648 * requesting VP.
649 *If get somethine, set VP_currently_executing to the VP from the queue, then
650 * resume both.
651 */
652 void
653 handleTransEnd(SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv)
654 { SSRSemData *semData;
655 SlaveVP *waitingPr;
656 SSRTrans *transStruc;
657 TransListElem *lastTrans;
659 DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingPr->slaveID)
661 transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
663 //make sure transaction ended in same VP as started it.
664 if( transStruc->VPCurrentlyExecuting != requestingPr )
665 {
666 VMS_PI__throw_exception( "trans ended in diff VP", requestingPr, NULL );
667 }
669 //make sure nesting is correct -- last ID entered should == this ID
670 semData = requestingPr->semanticData;
671 lastTrans = semData->lastTransEntered;
672 if( lastTrans->transID != semReq->transID )
673 {
674 VMS_PI__throw_exception( "trans incorrectly nested", requestingPr, NULL );
675 }
677 semData->lastTransEntered = semData->lastTransEntered->nextTrans;
680 waitingPr = readPrivQ( transStruc->waitingVPQ );
681 transStruc->VPCurrentlyExecuting = waitingPr;
683 if( waitingPr != NULL )
684 resume_slaveVP( waitingPr, semEnv );
686 resume_slaveVP( requestingPr, semEnv );
687 }