--- /dev/null
+#include "mlp_lock.h"\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "WaitingQueue.h"\r
+//TODO check that the right path is pointed to by the below #include\r
+#include "RuntimeConflictResolver.h"\r
+\r
+#define NOT_AT_FRONT = 3;\r
+#define TRAVERSER_FINISHED = 2;\r
+\r
+//Note: is global to all processes\r
+WaitingQueueBinVector * freeBinVectors;\r
+\r
+//TODO perhaps print a map of allocSites to arrayIndex?\r
+\r
+//NOTE: Only the HashTable calls this function\r
+WaitingQueueBin * mallocWaitingQueue(int size) {\r
+ return (WaitingQueueBin *) malloc(sizeof(WaitingQueueBin) * size);\r
+}\r
+\r
+//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
+void putWaitingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID) {\r
+ //lock bin\r
+ WaitingQueueBinVector * head;\r
+ WaitingQueueBinVector * currentVector;\r
+ TraverserResumeDataFromWaitingQ * b;\r
+ do {\r
+ head = (WaitingQueueBinVector *) 0x1;\r
+ head = LOCKXCHG(&(queue[allocSiteID]).head, head);\r
+ } while (head == (WaitingQueueBinVector *) 0x1);\r
+ //now the current bin is locked.\r
+\r
+ //completely empty case\r
+ if (queue[allocSiteID].tail == NULL) {\r
+ currentVector = getUsableVector();\r
+ head = currentVector;\r
+ queue[allocSiteID].tail = currentVector; //We do not set the head here because we need lock\r
+ }\r
+ //Tail bin full\r
+ else if (queue[allocSiteID].tail->tailIndex == NUMITEMS_WQ) {\r
+ currentVector = getUsableVector();\r
+ queue[allocSiteID].tail->next = currentVector;\r
+ queue[allocSiteID].tail = currentVector;\r
+ } else { //the bin not full case\r
+ currentVector = queue[allocSiteID].tail;\r
+ }\r
+\r
+\r
+ //For the case in which we try to add the same thing twice\r
+ b = &(currentVector->array[currentVector->tailIndex - 1]);\r
+ if(b->effectType == effectType && b->resumePtr == resumePtr && b->traverserID == traverserID) {\r
+ queue[allocSiteID].head = head; // release lock\r
+ return;\r
+ }\r
+ else {//add item\r
+ b = &(currentVector->array[currentVector->tailIndex++]);\r
+\r
+ b->resumePtr = resumePtr;\r
+ b->traverserID = traverserID;\r
+ b->effectType = effectType;\r
+\r
+ queue[allocSiteID].size++;\r
+ queue[allocSiteID].head = head; // release lock\r
+ }\r
+}\r
+\r
+\r
+int isEmptyForWaitingQ(WaitingQueueBin * queue, int allocSiteID) {\r
+ return (queue[allocSiteID]).size == 0;\r
+}\r
+\r
+//This method should be called by the SESE block\r
+//Return is how many things are removed. -1 would indicate error\r
+int removeFromQueue(WaitingQueueBin * wQueue, int allocSiteID, int TraverserID) {\r
+ TraverserResumeDataFromWaitingQ * td;\r
+ WaitingQueueBin * be = &(wQueue[allocSiteID]);\r
+ int count = 0;\r
+\r
+ if(wQueue[allocSiteID].size == 0)\r
+ return -1; //error\r
+\r
+ do {\r
+ td = &(be->head->array[be->head->headIndex]);\r
+\r
+ //TODO perhaps instead of using traverserID to track which variables are resolved, make\r
+ //individual IDs for each.\r
+ if(td->traverserID != TraverserID) {\r
+ return count;\r
+ }\r
+\r
+ //TODo replace 2 with #define\r
+ if(traverse(td->resumePtr, td->traverserID) == 2) {\r
+ count++; // means we at least got rid of 1 item in the traverser\r
+ be->size--;\r
+\r
+ //fast case\r
+ if(be->size == 0) {\r
+ be->head->headIndex = 0;\r
+ be->head->tailIndex = 0;\r
+ return count;\r
+ }\r
+ else if(++(be->head->headIndex) == be->head->tailIndex){\r
+ //Note: be->head->next CANNOT be NULL since that would imply be->size == 0\r
+ be->head = returnVectorToFreePool(be->head);\r
+ }\r
+ }\r
+ else\r
+ return count;\r
+\r
+ } while(1);\r
+}\r
+\r
+WaitingQueueBinVector * returnVectorToFreePool(WaitingQueueBinVector *ptr) {\r
+ WaitingQueueBinVector * freeHead;\r
+ WaitingQueueBinVector * ptrNext;\r
+ do {\r
+ freeHead = (WaitingQueueBinVector *) 0x1;\r
+ //TODO check if this cuts off part of the mem addr or not.\r
+ freeHead = LOCKXCHG(&freeBinVectors, freeHead);\r
+ } while (freeHead == (WaitingQueueBinVector *) 0x1);\r
+ //free bins locked\r
+\r
+ ptrNext = ptr->next;\r
+ if(freeHead == NULL) {\r
+ freeBinVectors = ptr; //lock released\r
+ }\r
+ else {\r
+ ptr->next = freeHead;\r
+ freeBinVectors = ptr; //lock released\r
+ }\r
+\r
+ return ptrNext;\r
+}\r
+\r
+WaitingQueueBinVector * getUsableVector() {\r
+ //Attempt to take one from the free bin first\r
+ WaitingQueueBinVector * ptr;\r
+ do {\r
+ ptr = (WaitingQueueBinVector *) 0x1;\r
+ ptr = LOCKXCHG(&freeBinVectors, ptr);\r
+ } while (ptr == (WaitingQueueBinVector *) 0x1);\r
+ //free bins locked\r
+\r
+ if (ptr == NULL) {\r
+ freeBinVectors = NULL; //lock released\r
+ return mallocNewVector();\r
+ } else {\r
+ freeBinVectors = ptr->next; //lock released\r
+ ptr->next = NULL;\r
+ ptr->headIndex = 0;\r
+ ptr->tailIndex = 0;\r
+ return ptr;\r
+ }\r
+}\r
+\r
+WaitingQueueBinVector * mallocNewVector() {\r
+ WaitingQueueBinVector * retval = (WaitingQueueBinVector *) malloc(\r
+ sizeof(WaitingQueueBinVector));\r
+ retval->next = NULL;\r
+ retval->headIndex = 0;\r
+ retval->tailIndex = 0;\r
+ return retval;\r
+}\r
+\r
+//TODO this only a debug method GET RID OF IT WHEN DONE!!\r
+WaitingQueueBinVector * debug_GetTheFreeBinsPtr() {\r
+ return freeBinVectors;\r
+}\r
+\r
--- /dev/null
+/*\r
+ * waitingQueue.h\r
+ *\r
+ * Created on: Sep 1, 2010\r
+ * Author: stephey\r
+ */\r
+#ifndef WAITINGQUEUE_H_\r
+#define WAITINGQUEUE_H_\r
+\r
+#define NOT_AT_FRONT = 3;\r
+#define TRAVERSER_FINISHED = 2;\r
+#define NUMITEMS_WQ 20\r
+\r
+/* print header */\r
+typedef struct TraverserData_WQ {\r
+ void * resumePtr;\r
+ int effectType;\r
+ int traverserID;\r
+} TraverserResumeDataFromWaitingQ;\r
+\r
+typedef struct BinVector_wq {\r
+ struct TraverserData_WQ array[NUMITEMS_WQ];\r
+ struct BinVector_wq * next;\r
+ int headIndex;\r
+ int tailIndex;\r
+} WaitingQueueBinVector;\r
+\r
+\r
+typedef struct BinElement_wq {\r
+ struct BinVector_wq * head;\r
+ struct BinVector_wq * tail;\r
+ int size;\r
+} WaitingQueueBin;\r
+\r
+\r
+//TODO in the future, remove this struct all together\r
+//struct WaitingQueue {\r
+// struct BinElement_wq * array;\r
+//};\r
+\r
+void putWaitingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID);\r
+int isEmptyForWaitingQ(WaitingQueueBin * queue, int allocSiteID);\r
+WaitingQueueBin * mallocWaitingQueue(int size);\r
+WaitingQueueBinVector * returnVectorToFreePool(struct BinVector_wq *ptr);\r
+int removeFromQueue(WaitingQueueBin * queue, int allocSiteID, int TraverserID);\r
+//int resolveWaitingQueueChain(struct WaitingQueue * queue, int allocSiteID, int traverserID);\r
+WaitingQueueBinVector * mallocNewVector();\r
+WaitingQueueBinVector * getUsableVector();\r
+\r
+//TODO this only a debug method GET RID OF IT WHEN DONE!!\r
+WaitingQueueBinVector * debug_GetTheFreeBinsPtr();\r
+#endif /* WAITINGQUEUE_H_ */\r
--- /dev/null
+/*
+ * WaitingQueueTest.c
+ *
+ * Created on: Sep 25, 2010
+ * Author: stephey
+ */
+
+#include "WaitingQueue.h"
+#include "mlp_lock.h"
+#include "RuntimeConflictResolver.h"
+#include <stdio.h>
+#include <stdlib.h>
+//Make sure you only test ONE thing at a time.
+void testMalloc(int maxTests) {
+ printf("Testing malloc from 1 to %u\n", maxTests);
+ int i = 1;
+ WaitingQueueBin * array[maxTests];
+
+ for(i = 0; i < maxTests; i++) {
+ array[i] = NULL;
+ }
+
+ for(i = 0; i <= maxTests; i++) {
+ array[i-1] = mallocWaitingQueue(i);
+ }
+
+ for(i = 0; i <maxTests; i++) {
+ if(array[i] == NULL) {
+ printf("Crap, it didn't work somewhere at index %u\n", i);
+ }
+ }
+}
+
+//P.S. make sure this is the FIRST and ONLY thing to run if you want to test this.
+void testWaitingQueueFreeBinsSingleTest() {
+ WaitingQueueBinVector * ptr = getUsableVector();
+
+ if(ptr == NULL) {
+ printf("waitingQueueBinVector didn't work ><\n");
+ }
+
+ if(debug_GetTheFreeBinsPtr() != NULL) {
+ printf("either testWaitingQueueFreeBins wasn't called first or somehow it's not null....");
+ }
+
+ if(returnVectorToFreePool(ptr) != NULL) {
+ printf("Returning the .next in the waiting queue didn't quite work...");
+ }
+
+ if(debug_GetTheFreeBinsPtr() != ptr) {
+ printf("The old ptr wasn't returned into the free bins pool");
+ }
+}
+
+void waitingQueuePutAndRemoveTestSingle() {
+ WaitingQueueBin * waitingQueue = mallocWaitingQueue(200);
+ int i;
+
+ for(i = 0; i < 200; i++) {
+ if(!isEmptyForWaitingQ(waitingQueue, i)) {
+ printf("Waiting Queue is not empty at Bin %u of %u\n", i, 200);
+ }
+
+ if(waitingQueue[i].head != NULL || waitingQueue[i].size != 0 || waitingQueue[i].tail !=NULL){
+ printf("Something was initialized incorrectly at bin %u of %u\n", i, 200);
+ }
+ }
+
+ //void putWaintingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID);
+ putWaitingQueue(100, waitingQueue, 1, 2, 3);
+
+ if(isEmptyForWaitingQ(waitingQueue, 100)) {
+ printf("The one item added at location %u did not actually get put there according to isEmpty\n", 100);
+ }
+
+ if(waitingQueue[100].head == NULL || waitingQueue[100].size != 1 || waitingQueue[100].tail != waitingQueue[100].head) {
+ printf("Add information contained within the bin appears to be incorrect\n");
+ }
+
+ TraverserResumeDataFromWaitingQ * td = &(waitingQueue[100].head->array[waitingQueue[100].head->headIndex]);
+
+ if(td->effectType != 1 || td->resumePtr != 2 || td->traverserID != 3) {
+ printf("Something went wrong in putting the item into the waitingQueue\n");
+ }
+
+ for(i = 0; i < 200; i++) {
+ if(i != 100) {
+ if(!isEmptyForWaitingQ(waitingQueue, i)) {
+ printf("Waiting Queue is not empty at Bin %u of %u\n", i, 200);
+ }
+
+ if(waitingQueue[i].head != NULL || waitingQueue[i].size != 0 || waitingQueue[i].tail !=NULL){
+ printf("Something was initialized incorrectly at bin %u of %u\n", i, 200);
+ }
+ }
+ }
+
+ //int removeFromQueue(WaitingQueueBin * wQueue, int allocSiteID, int TraverserID)
+ if(removeFromQueue(waitingQueue, 100, 3) != 1) {
+ printf("it appears that removing doens't remove the correct # of items\n");
+ }
+
+ if(waitingQueue[100].head == NULL || waitingQueue[100].size != 0 || waitingQueue[100].tail != waitingQueue[100].head) {
+ printf("Remove information contained within the bin appears to be incorrect\n");
+ }
+
+ printf("just ran waitingQueuePutTestSingle()\n");
+
+}
+
+void waitingQueuePutAndRemoveTestMulti() {
+ WaitingQueueBin * waitingQueue = mallocWaitingQueue(200);
+ int i;
+
+ //add 2 more
+ //void putWaintingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID);
+ putWaitingQueue(100, waitingQueue, 1, 2, 4);
+ putWaitingQueue(100, waitingQueue, 1, 2, 4);
+ putWaitingQueue(100, waitingQueue, 1, 2, 5);
+
+ for(i = 0; i < 200; i++) {
+ if(i != 100) {
+ if(!isEmptyForWaitingQ(waitingQueue, i)) {
+ printf("Waiting Queue is not empty at Bin %u of %u\n", i, 200);
+ }
+
+ if(waitingQueue[i].head != NULL || waitingQueue[i].size != 0 || waitingQueue[i].tail !=NULL){
+ printf("Something was initialized incorrectly at bin %u of %u\n", i, 200);
+ }
+ }
+ }
+
+ if(waitingQueue[100].head == NULL || waitingQueue[100].size != 2 || waitingQueue[100].tail != waitingQueue[100].head) {
+ printf("Add information contained within the bin appears to be incorrect (this is add 3 with 2 duplicates)\n");
+ }
+
+// //Return is how many things are removed. -1 would indicate error
+// int removeFromQueue(WaitingQueueBin * wQueue, int allocSiteID, int TraverserID)
+
+ if(removeFromQueue(waitingQueue, 101,0) != -1) {
+ printf("failsafe does not work in removeFromQueue\n");
+ }
+
+ if(removeFromQueue(waitingQueue, 100, 29038) != 0 || removeFromQueue(waitingQueue, 100, 5) != 0) {
+ printf("removeFromQueue does not check element's traverserID before removing");
+ }
+
+ if(removeFromQueue(waitingQueue, 100, 4) != 1 || waitingQueue[100].size != 1) {
+ printf("removeFromQueue didn't remove items and/or didn't decrement counter correctly 1\n");
+ }
+
+ if(removeFromQueue(waitingQueue, 100, 4) != 0 || waitingQueue[100].size != 1) {
+ printf("removeFromQueue didn't remove items and/or didn't decrement counter correctly 2\n");
+ }
+
+ if(removeFromQueue(waitingQueue, 99, 5) != -1 || waitingQueue[99].size != 0) {
+ printf("failsafe in remove does not work correctly\n");
+ }
+
+ if(removeFromQueue(waitingQueue, 100, 5) != 1 || waitingQueue[100].size != 0 || !isEmptyForWaitingQ(waitingQueue, 100)) {
+ printf("removeFromQueue didn't remove items and/or didn't decrement counter correctly 3\n");
+ }
+
+ //next try adding 10,000 items
+
+ for(i = 0; i < 10000; i++) {
+ putWaitingQueue(100, waitingQueue, 1, 2, i);
+ }
+
+ if(isEmptyForWaitingQ(waitingQueue, 100)) {
+ printf("isEmpty reports that queue is empty even though it's not\n");
+ }
+
+ if(waitingQueue[100].size != 10000) {
+ printf("Some of the 10000 items were not added");
+ }
+
+ if(debug_GetTheFreeBinsPtr() != NULL) {
+ printf("Program put something in freeBinsPtr even though it should have never touched it\n");
+ }
+
+ for(i = 0; i <10000; i++) {
+ if(removeFromQueue(waitingQueue, 100, i) != 1) {
+ printf("remove from 10000 didn't properly just remove ONE item");
+ }
+
+ if(waitingQueue[100].size != 10000 - i -1) {
+ printf("counter did not properly decrement itself in 10000 remove\n");
+ }
+ }
+
+ if(waitingQueue[100].size != 0 ) {
+ printf("Something went wrong and after 10000 removes, the size is not 0\n");
+ }
+
+ if(waitingQueue[100].head == NULL || waitingQueue[100].head != waitingQueue[100].tail) {
+ printf("head tail pointers in bin element is not properly aligned after 10000 remove\n");
+ }
+
+ if(debug_GetTheFreeBinsPtr() == NULL || debug_GetTheFreeBinsPtr()->next == NULL || debug_GetTheFreeBinsPtr()->next->next == NULL) {
+ printf("either the numbins constant is really high or things aren't being put into the freeBinsPtr correctly\n");
+ }
+
+ printf("Just ran waitingQueuePutAndRemoveTestMulti()\n");
+}
+
+void testWaitingQueueFreeBinsMultipleTest(int size) {
+ WaitingQueueBinVector ** ptrs = malloc(sizeof(WaitingQueueBinVector *) * size);
+ int i;
+
+ for(i = 0; i < size; i++) {
+ ptrs[i] = getUsableVector();
+ ptrs[i]->tailIndex = 293847; //this is to make sure we don't get a segmentation fault
+
+ if(ptrs[i]->next != NULL || ptrs[i]->tailIndex != 293847) {
+ printf("either something wasn't initialized correctly or we are given a fake pointer at getUsableVector()\n");
+ }
+
+ if(debug_GetTheFreeBinsPtr() != NULL) {
+ printf("somehow they got to the freebins pool at index %u\n", i);
+ }
+ }
+
+ for(i = 0; i < size; i++) {
+ returnVectorToFreePool(ptrs[i]);
+ if(debug_GetTheFreeBinsPtr() != ptrs[i]) {
+ printf("it appears that the returnVectorToFreePool didn't put the vector at the front at index %u\n", i);
+ }
+ }
+
+ for(i = size-1; i>= 0; i--) {
+ if(getUsableVector() != ptrs[i]) {
+ printf("getUsableVector does not get the correct one at index %u\n", i);
+ }
+ }
+
+ if(debug_GetTheFreeBinsPtr() != NULL) {
+ printf("Apparently our free loop didn't free everything correctly\n");
+ }
+
+ printf("I just tested testWaitingQueueFreeBinsMultipleTest(%u);\n", size);
+}
+
+//This test was because I wanted to make my own lockxchng method
+void testLOCKXCHG() {
+ int a = 5;
+ int * aPtr = &a;
+ int * lock = (int *) 0x1;
+
+ printf("lockxchg test\n");
+ lock = LOCKXCHG(&aPtr, lock);
+
+ if(aPtr =! 0x1) {
+ printf("lock failed\n");
+ }
+
+ if(lock != &a) {
+ printf("The revtal to LOCKXCHG isn't correct; return = %p; supposed to be %p\n", lock, &a);
+ }
+}
+
+int main() {
+ waitingQueuePutAndRemoveTestMulti();
+ return 1;
+}