VMS/VMS_Implementations/SSR_impls/SSR__MC_shared_impl

view SSR_Request_Handlers.c @ 80:494703aecda2

fixed bug -- when entry empty, req was inserted w/o cloning it first
author Sean Halle <seanhalle@yahoo.com>
date Thu, 11 Oct 2012 22:58:35 -0700
parents 833b31a8abc1
children
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 = cloneReq( 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 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
432 semEnv->lastReqType = 1;
433 #endif
434 ptr = VMS_PI__malloc( semReq->sizeToMalloc );
435 requestingPr->dataRetFromReq = ptr;
436 resume_slaveVP( requestingPr, semEnv );
437 }
439 /*
440 */
441 void
442 handleFree( SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv )
443 {
444 DEBUG__printf1(dbgRqstHdlr,"Free request from processor %d",requestingPr->slaveID)
445 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
446 semEnv->lastReqType = 1;
447 #endif
448 VMS_PI__free( semReq->ptrToFree );
449 resume_slaveVP( requestingPr, semEnv );
450 }
453 //===========================================================================
454 //
455 /*Uses ID as index into array of flags. If flag already set, resumes from
456 * end-label. Else, sets flag and resumes normally.
457 */
458 void inline
459 handleStartSingleton_helper( SSRSingleton *singleton, SlaveVP *reqstingPr,
460 SSRSemEnv *semEnv )
461 {
462 if( singleton->hasFinished )
463 { //the code that sets the flag to true first sets the end instr addr
464 reqstingPr->dataRetFromReq = singleton->endInstrAddr;
465 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
466 Dependency newd;
467 newd.from_vp = singleton->executingVp;
468 newd.from_task = singleton->executingTask;
469 newd.to_vp = reqstingPr->slaveID;
470 newd.to_task = reqstingPr->assignCount +1;
471 addToListOfArrays(Dependency,newd,semEnv->singletonDependenciesList);
472 #endif
473 resume_slaveVP( reqstingPr, semEnv );
474 return;
475 }
476 else if( singleton->hasBeenStarted )
477 { //singleton is in-progress in a diff slave, so wait for it to finish
478 writePrivQ(reqstingPr, singleton->waitQ );
479 return;
480 }
481 else
482 { //hasn't been started, so this is the first attempt at the singleton
483 singleton->hasBeenStarted = TRUE;
484 reqstingPr->dataRetFromReq = 0x0;
485 resume_slaveVP( reqstingPr, semEnv );
486 return;
487 }
488 }
489 void inline
490 handleStartFnSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
491 SSRSemEnv *semEnv )
492 { SSRSingleton *singleton;
493 DEBUG__printf1(dbgRqstHdlr,"StartFnSingleton request from processor %d",requestingPr->slaveID)
495 singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
496 handleStartSingleton_helper( singleton, requestingPr, semEnv );
497 }
498 void inline
499 handleStartDataSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
500 SSRSemEnv *semEnv )
501 { SSRSingleton *singleton;
503 DEBUG__printf1(dbgRqstHdlr,"StartDataSingleton request from processor %d",requestingPr->slaveID)
504 if( *(semReq->singletonPtrAddr) == NULL )
505 { singleton = VMS_PI__malloc( sizeof(SSRSingleton) );
506 singleton->waitQ = makeVMSQ();
507 singleton->endInstrAddr = 0x0;
508 singleton->hasBeenStarted = FALSE;
509 singleton->hasFinished = FALSE;
510 *(semReq->singletonPtrAddr) = singleton;
511 }
512 else
513 singleton = *(semReq->singletonPtrAddr);
514 handleStartSingleton_helper( singleton, requestingPr, semEnv );
515 }
518 void inline
519 handleEndSingleton_helper( SSRSingleton *singleton, SlaveVP *requestingPr,
520 SSRSemEnv *semEnv )
521 { PrivQueueStruc *waitQ;
522 int32 numWaiting, i;
523 SlaveVP *resumingPr;
525 if( singleton->hasFinished )
526 { //by definition, only one slave should ever be able to run end singleton
527 // so if this is true, is an error
528 ERROR1( "singleton code ran twice", requestingPr );
529 }
531 singleton->hasFinished = TRUE;
532 singleton->executingVp = requestingPr->slaveID;
533 singleton->executingTask = requestingPr->assignCount;
534 waitQ = singleton->waitQ;
535 numWaiting = numInPrivQ( waitQ );
536 for( i = 0; i < numWaiting; i++ )
537 { //they will resume inside start singleton, then jmp to end singleton
538 resumingPr = readPrivQ( waitQ );
539 resumingPr->dataRetFromReq = singleton->endInstrAddr;
540 #ifdef HOLISTIC__TURN_ON_OBSERVE_UCC
541 Dependency newd;
542 newd.from_vp = singleton->executingVp;
543 newd.from_task = singleton->executingTask;
544 newd.to_vp = resumingPr->slaveID;
545 newd.to_task = resumingPr->assignCount +1;
546 addToListOfArrays(Dependency,newd,semEnv->singletonDependenciesList);
547 #endif
548 resume_slaveVP( resumingPr, semEnv );
549 }
551 resume_slaveVP( requestingPr, semEnv );
553 }
554 void inline
555 handleEndFnSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
556 SSRSemEnv *semEnv )
557 {
558 SSRSingleton *singleton;
560 DEBUG__printf1(dbgRqstHdlr,"EndFnSingleton request from processor %d",requestingPr->slaveID)
562 singleton = &(semEnv->fnSingletons[ semReq->singletonID ]);
563 handleEndSingleton_helper( singleton, requestingPr, semEnv );
564 }
565 void inline
566 handleEndDataSingleton( SSRSemReq *semReq, SlaveVP *requestingPr,
567 SSRSemEnv *semEnv )
568 {
569 SSRSingleton *singleton;
571 DEBUG__printf1(dbgRqstHdlr,"EndDataSingleton request from processor %d",requestingPr->slaveID)
573 singleton = *(semReq->singletonPtrAddr);
574 handleEndSingleton_helper( singleton, requestingPr, semEnv );
575 }
578 /*This executes the function in the masterVP, take the function
579 * pointer out of the request and call it, then resume the VP.
580 */
581 void
582 handleAtomic( SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv )
583 {
584 DEBUG__printf1(dbgRqstHdlr,"Atomic request from processor %d",requestingPr->slaveID)
585 semReq->fnToExecInMaster( semReq->dataForFn );
586 resume_slaveVP( requestingPr, semEnv );
587 }
589 /*First, it looks at the VP's semantic data, to see the highest transactionID
590 * that VP
591 * already has entered. If the current ID is not larger, it throws an
592 * exception stating a bug in the code.
593 *Otherwise it puts the current ID
594 * there, and adds the ID to a linked list of IDs entered -- the list is
595 * used to check that exits are properly ordered.
596 *Next it is uses transactionID as index into an array of transaction
597 * structures.
598 *If the "VP_currently_executing" field is non-null, then put requesting VP
599 * into queue in the struct. (At some point a holder will request
600 * end-transaction, which will take this VP from the queue and resume it.)
601 *If NULL, then write requesting into the field and resume.
602 */
603 void
604 handleTransStart( SSRSemReq *semReq, SlaveVP *requestingPr,
605 SSRSemEnv *semEnv )
606 { SSRSemData *semData;
607 TransListElem *nextTransElem;
609 DEBUG__printf1(dbgRqstHdlr,"TransStart request from processor %d",requestingPr->slaveID)
611 //check ordering of entering transactions is correct
612 semData = requestingPr->semanticData;
613 if( semData->highestTransEntered > semReq->transID )
614 { //throw VMS exception, which shuts down VMS.
615 VMS_PI__throw_exception( "transID smaller than prev", requestingPr, NULL);
616 }
617 //add this trans ID to the list of transactions entered -- check when
618 // end a transaction
619 semData->highestTransEntered = semReq->transID;
620 nextTransElem = VMS_PI__malloc( sizeof(TransListElem) );
621 nextTransElem->transID = semReq->transID;
622 nextTransElem->nextTrans = semData->lastTransEntered;
623 semData->lastTransEntered = nextTransElem;
625 //get the structure for this transaction ID
626 SSRTrans *
627 transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
629 if( transStruc->VPCurrentlyExecuting == NULL )
630 {
631 transStruc->VPCurrentlyExecuting = requestingPr;
632 resume_slaveVP( requestingPr, semEnv );
633 }
634 else
635 { //note, might make future things cleaner if save request with VP and
636 // add this trans ID to the linked list when gets out of queue.
637 // but don't need for now, and lazy..
638 writePrivQ( requestingPr, transStruc->waitingVPQ );
639 }
640 }
643 /*Use the trans ID to get the transaction structure from the array.
644 *Look at VP_currently_executing to be sure it's same as requesting VP.
645 * If different, throw an exception, stating there's a bug in the code.
646 *Next, take the first element off the list of entered transactions.
647 * Check to be sure the ending transaction is the same ID as the next on
648 * the list. If not, incorrectly nested so throw an exception.
649 *
650 *Next, get from the queue in the structure.
651 *If it's empty, set VP_currently_executing field to NULL and resume
652 * requesting VP.
653 *If get somethine, set VP_currently_executing to the VP from the queue, then
654 * resume both.
655 */
656 void
657 handleTransEnd(SSRSemReq *semReq, SlaveVP *requestingPr, SSRSemEnv *semEnv)
658 { SSRSemData *semData;
659 SlaveVP *waitingPr;
660 SSRTrans *transStruc;
661 TransListElem *lastTrans;
663 DEBUG__printf1(dbgRqstHdlr,"TransEnd request from processor %d",requestingPr->slaveID)
665 transStruc = &(semEnv->transactionStrucs[ semReq->transID ]);
667 //make sure transaction ended in same VP as started it.
668 if( transStruc->VPCurrentlyExecuting != requestingPr )
669 {
670 VMS_PI__throw_exception( "trans ended in diff VP", requestingPr, NULL );
671 }
673 //make sure nesting is correct -- last ID entered should == this ID
674 semData = requestingPr->semanticData;
675 lastTrans = semData->lastTransEntered;
676 if( lastTrans->transID != semReq->transID )
677 {
678 VMS_PI__throw_exception( "trans incorrectly nested", requestingPr, NULL );
679 }
681 semData->lastTransEntered = semData->lastTransEntered->nextTrans;
684 waitingPr = readPrivQ( transStruc->waitingVPQ );
685 transStruc->VPCurrentlyExecuting = waitingPr;
687 if( waitingPr != NULL )
688 resume_slaveVP( waitingPr, semEnv );
690 resume_slaveVP( requestingPr, semEnv );
691 }