VMS/VMS_Implementations/SSR_impls/SSR__MC_shared_impl

annotate SSR_Request_Handlers.c @ 77:833b31a8abc1

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