1 #include "mlp_lock.h"
\r
4 #include "WaitingQueue.h"
\r
5 //TODO check that the right path is pointed to by the below #include
\r
6 #include "RuntimeConflictResolver.h"
\r
8 //Note: is global to all processes
\r
9 WaitingQueueBinVector * freeBinVectors;
\r
11 //TODO perhaps print a map of allocSites to arrayIndex?
\r
13 //NOTE: Only the HashTable calls this function
\r
14 WaitingQueueBin * mallocWaitingQueue(int size) {
\r
15 return (WaitingQueueBin *) malloc(sizeof(WaitingQueueBin) * size);
\r
18 //NOTE: allocSiteID is NOT the same as allocsite, rather it's an ID generated by the traverser for an alloc site for a traversal.
\r
19 void putIntoWaitingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID) {
\r
20 //since Put SHOULD be done only by 1 thread (from 1 hashtable), the locking mechanism is removed.
\r
21 WaitingQueueBin *qptr=&queue[allocSiteID];
\r
22 WaitingQueueBinVector * tail = qptr->tail;
\r
25 //completely empty case
\r
26 WaitingQueueBinVector * currentVector = getUsableWaitingQueueBinVector();
\r
27 TraverserResumeDataFromWaitingQ * b = &(currentVector->array[currentVector->tailIndex++]);
\r
28 //Add new bin to list
\r
29 qptr->head = currentVector;
\r
30 qptr->tail = currentVector;
\r
31 //Insert item into bin
\r
32 b->resumePtr = resumePtr;
\r
33 b->traverserID = traverserID;
\r
34 b->effectType = effectType;
\r
36 } else if (tail->tailIndex == NUMITEMS_WQ) {
\r
38 WaitingQueueBinVector * currentVector = tail;
\r
39 TraverserResumeDataFromWaitingQ * b = &(currentVector->array[currentVector->tailIndex-1]);
\r
41 if(b->effectType != effectType || b->resumePtr != resumePtr || b->traverserID != traverserID) {
\r
43 currentVector = getUsableWaitingQueueBinVector();
\r
44 tail->next = currentVector;
\r
45 qptr->tail = currentVector;
\r
46 b = &(currentVector->array[currentVector->tailIndex++]);
\r
47 b->resumePtr = resumePtr;
\r
48 b->traverserID = traverserID;
\r
49 b->effectType = effectType;
\r
52 } else { //the bin not full case
\r
53 WaitingQueueBinVector * currentVector = tail;
\r
54 TraverserResumeDataFromWaitingQ * b = &(currentVector->array[currentVector->tailIndex-1]);
\r
56 if(b->effectType != effectType || b->resumePtr != resumePtr || b->traverserID != traverserID) {
\r
58 b = &(currentVector->array[currentVector->tailIndex++]);
\r
59 b->resumePtr = resumePtr;
\r
60 b->traverserID = traverserID;
\r
61 b->effectType = effectType;
\r
67 int isEmptyForWaitingQ(WaitingQueueBin * queue, int allocSiteID) {
\r
68 return (queue[allocSiteID]).size == 0;
\r
71 //This method should be called by the SESE block
\r
72 //Return is how many things are removed. -1 would indicate error
\r
73 int removeFromWaitingQueue(WaitingQueueBin * wQueue, int allocSiteID, int TraverserID) {
\r
74 TraverserResumeDataFromWaitingQ * td;
\r
75 WaitingQueueBin * be = &(wQueue[allocSiteID]);
\r
78 if(wQueue[allocSiteID].size == 0)
\r
82 td = &(be->head->array[be->head->headIndex]);
\r
84 //TODO perhaps instead of using traverserID to track which variables are resolved, make
\r
85 //individual IDs for each.
\r
86 if(td->traverserID != TraverserID) {
\r
90 if(traverse(td->resumePtr, td->traverserID) == TRAVERSER_FINISHED) {
\r
91 count++; // means we at least got rid of 1 item in the traverser
\r
96 be->head->headIndex = 0;
\r
97 be->head->tailIndex = 0;
\r
100 else if(++(be->head->headIndex) == be->head->tailIndex){
\r
101 //Note: be->head->next CANNOT be NULL since that would imply be->size == 0
\r
102 be->head = returnWaitingQueueBinVectorToFreePool(be->head);
\r
111 WaitingQueueBinVector * returnWaitingQueueBinVectorToFreePool(WaitingQueueBinVector *ptr) {
\r
112 WaitingQueueBinVector * freeHead;
\r
113 WaitingQueueBinVector * ptrNext;
\r
115 freeHead = (WaitingQueueBinVector *) 0x1;
\r
116 freeHead = LOCKXCHG(&freeBinVectors, freeHead);
\r
117 } while (freeHead == (WaitingQueueBinVector *) 0x1);
\r
120 ptrNext = ptr->next;
\r
121 if(freeHead == NULL) {
\r
122 freeBinVectors = ptr; //lock released
\r
125 ptr->next = freeHead;
\r
126 freeBinVectors = ptr; //lock released
\r
132 WaitingQueueBinVector * getUsableWaitingQueueBinVector() {
\r
133 //Attempt to take one from the free bin first
\r
134 WaitingQueueBinVector * ptr;
\r
136 ptr = (WaitingQueueBinVector *) 0x1;
\r
137 ptr = LOCKXCHG(&freeBinVectors, ptr);
\r
138 } while (ptr == (WaitingQueueBinVector *) 0x1);
\r
142 freeBinVectors = NULL; //lock released
\r
143 return mallocNewWaitingQueueBinVector();
\r
145 freeBinVectors = ptr->next; //lock released
\r
147 ptr->headIndex = 0;
\r
148 ptr->tailIndex = 0;
\r
153 WaitingQueueBinVector * mallocNewWaitingQueueBinVector() {
\r
154 WaitingQueueBinVector * retval = (WaitingQueueBinVector *) malloc(
\r
155 sizeof(WaitingQueueBinVector));
\r
156 retval->next = NULL;
\r
157 retval->headIndex = 0;
\r
158 retval->tailIndex = 0;
\r