From 99cd465fb5335cffa54fe2072d462ead18bd7170 Mon Sep 17 00:00:00 2001 From: stephey Date: Sun, 26 Sep 2010 05:08:24 +0000 Subject: [PATCH] WaitingQueue Correctness tests for RCR. FAKE mlp_lock.* and RuntimeConflictResolver.* are included so that the waitingQueue can be tested without compiling/including the rest of the project --- .../RuntimeConflictResolver.c | 25 ++ .../RuntimeConflictResolver.h | 15 + .../Testing_WaitingQueue/WaitingQueue.c | 169 +++++++++++ .../Testing_WaitingQueue/WaitingQueue.h | 52 ++++ .../Testing_WaitingQueue/WaitingQueueTest.c | 265 ++++++++++++++++++ .../stephen/Testing_WaitingQueue/mlp_lock.c | 21 ++ .../stephen/Testing_WaitingQueue/mlp_lock.h | 15 + 7 files changed, 562 insertions(+) create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.c create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.h create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.c create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.h create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueueTest.c create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.c create mode 100644 Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.h diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.c b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.c new file mode 100644 index 00000000..4fad4280 --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.c @@ -0,0 +1,25 @@ +/* + * RuntimeConflictResolver.c + * + * Created on: Sep 25, 2010 + * Author: stephey + */ + +#include +#include "RuntimeConflictResolver.h" + +void traverse1(void * inVar) { + printf("Traverser 1 Ran\n"); +} +void traverse2(void * inVar){ + printf("Traverser 2 Ran\n"); +} +void traverse3(void * inVar){ + printf("Traverser 3 Ran\n"); +} + +int traverse(void * startingPtr, int traverserID) { +// printf("Traverser %u Ran\n", traverserID); + + return 2; +} diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.h b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.h new file mode 100644 index 00000000..200668f3 --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/RuntimeConflictResolver.h @@ -0,0 +1,15 @@ +#ifndef __3_RCR_H_ +#define __3_RCR_H_ + +//NOTE these files are the fake locks so I can test without compiling entire compiler +void traverse______b1745___sesea71___(void * InVar); +void traverse______b2746___seseb72___(void * InVar); + +void traverse1(void * inVar); +void traverse2(void * inVar); + +int traverse(void * startingPtr, int traverserID); +void createMasterHashStructureArray(); +void initializeStructsRCR(); +void destroyRCR(); +#endif diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.c b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.c new file mode 100644 index 00000000..4bf4af55 --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.c @@ -0,0 +1,169 @@ +#include "mlp_lock.h" +#include +#include +#include "WaitingQueue.h" +//TODO check that the right path is pointed to by the below #include +#include "RuntimeConflictResolver.h" + +#define NOT_AT_FRONT = 3; +#define TRAVERSER_FINISHED = 2; + +//Note: is global to all processes +WaitingQueueBinVector * freeBinVectors; + +//TODO perhaps print a map of allocSites to arrayIndex? + +//NOTE: Only the HashTable calls this function +WaitingQueueBin * mallocWaitingQueue(int size) { + return (WaitingQueueBin *) malloc(sizeof(WaitingQueueBin) * size); +} + +//NOTE: allocSiteID is NOT the same as allocsite, rather it's an ID generated by the traverser for an alloc site for a traversal. +void putWaitingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID) { + //lock bin + WaitingQueueBinVector * head; + WaitingQueueBinVector * currentVector; + TraverserResumeDataFromWaitingQ * b; + do { + head = (WaitingQueueBinVector *) 0x1; + head = LOCKXCHG(&(queue[allocSiteID]).head, head); + } while (head == (WaitingQueueBinVector *) 0x1); + //now the current bin is locked. + + //completely empty case + if (queue[allocSiteID].tail == NULL) { + currentVector = getUsableVector(); + head = currentVector; + queue[allocSiteID].tail = currentVector; //We do not set the head here because we need lock + } + //Tail bin full + else if (queue[allocSiteID].tail->tailIndex == NUMITEMS_WQ) { + currentVector = getUsableVector(); + queue[allocSiteID].tail->next = currentVector; + queue[allocSiteID].tail = currentVector; + } else { //the bin not full case + currentVector = queue[allocSiteID].tail; + } + + + //For the case in which we try to add the same thing twice + b = &(currentVector->array[currentVector->tailIndex - 1]); + if(b->effectType == effectType && b->resumePtr == resumePtr && b->traverserID == traverserID) { + queue[allocSiteID].head = head; // release lock + return; + } + else {//add item + b = &(currentVector->array[currentVector->tailIndex++]); + + b->resumePtr = resumePtr; + b->traverserID = traverserID; + b->effectType = effectType; + + queue[allocSiteID].size++; + queue[allocSiteID].head = head; // release lock + } +} + + +int isEmptyForWaitingQ(WaitingQueueBin * queue, int allocSiteID) { + return (queue[allocSiteID]).size == 0; +} + +//This method should be called by the SESE block +//Return is how many things are removed. -1 would indicate error +int removeFromQueue(WaitingQueueBin * wQueue, int allocSiteID, int TraverserID) { + TraverserResumeDataFromWaitingQ * td; + WaitingQueueBin * be = &(wQueue[allocSiteID]); + int count = 0; + + if(wQueue[allocSiteID].size == 0) + return -1; //error + + do { + td = &(be->head->array[be->head->headIndex]); + + //TODO perhaps instead of using traverserID to track which variables are resolved, make + //individual IDs for each. + if(td->traverserID != TraverserID) { + return count; + } + + //TODo replace 2 with #define + if(traverse(td->resumePtr, td->traverserID) == 2) { + count++; // means we at least got rid of 1 item in the traverser + be->size--; + + //fast case + if(be->size == 0) { + be->head->headIndex = 0; + be->head->tailIndex = 0; + return count; + } + else if(++(be->head->headIndex) == be->head->tailIndex){ + //Note: be->head->next CANNOT be NULL since that would imply be->size == 0 + be->head = returnVectorToFreePool(be->head); + } + } + else + return count; + + } while(1); +} + +WaitingQueueBinVector * returnVectorToFreePool(WaitingQueueBinVector *ptr) { + WaitingQueueBinVector * freeHead; + WaitingQueueBinVector * ptrNext; + do { + freeHead = (WaitingQueueBinVector *) 0x1; + //TODO check if this cuts off part of the mem addr or not. + freeHead = LOCKXCHG(&freeBinVectors, freeHead); + } while (freeHead == (WaitingQueueBinVector *) 0x1); + //free bins locked + + ptrNext = ptr->next; + if(freeHead == NULL) { + freeBinVectors = ptr; //lock released + } + else { + ptr->next = freeHead; + freeBinVectors = ptr; //lock released + } + + return ptrNext; +} + +WaitingQueueBinVector * getUsableVector() { + //Attempt to take one from the free bin first + WaitingQueueBinVector * ptr; + do { + ptr = (WaitingQueueBinVector *) 0x1; + ptr = LOCKXCHG(&freeBinVectors, ptr); + } while (ptr == (WaitingQueueBinVector *) 0x1); + //free bins locked + + if (ptr == NULL) { + freeBinVectors = NULL; //lock released + return mallocNewVector(); + } else { + freeBinVectors = ptr->next; //lock released + ptr->next = NULL; + ptr->headIndex = 0; + ptr->tailIndex = 0; + return ptr; + } +} + +WaitingQueueBinVector * mallocNewVector() { + WaitingQueueBinVector * retval = (WaitingQueueBinVector *) malloc( + sizeof(WaitingQueueBinVector)); + retval->next = NULL; + retval->headIndex = 0; + retval->tailIndex = 0; + return retval; +} + +//TODO this only a debug method GET RID OF IT WHEN DONE!! +WaitingQueueBinVector * debug_GetTheFreeBinsPtr() { + return freeBinVectors; +} + diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.h b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.h new file mode 100644 index 00000000..7dbd3b08 --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueue.h @@ -0,0 +1,52 @@ +/* + * waitingQueue.h + * + * Created on: Sep 1, 2010 + * Author: stephey + */ +#ifndef WAITINGQUEUE_H_ +#define WAITINGQUEUE_H_ + +#define NOT_AT_FRONT = 3; +#define TRAVERSER_FINISHED = 2; +#define NUMITEMS_WQ 20 + +/* print header */ +typedef struct TraverserData_WQ { + void * resumePtr; + int effectType; + int traverserID; +} TraverserResumeDataFromWaitingQ; + +typedef struct BinVector_wq { + struct TraverserData_WQ array[NUMITEMS_WQ]; + struct BinVector_wq * next; + int headIndex; + int tailIndex; +} WaitingQueueBinVector; + + +typedef struct BinElement_wq { + struct BinVector_wq * head; + struct BinVector_wq * tail; + int size; +} WaitingQueueBin; + + +//TODO in the future, remove this struct all together +//struct WaitingQueue { +// struct BinElement_wq * array; +//}; + +void putWaitingQueue(int allocSiteID, WaitingQueueBin * queue, int effectType, void * resumePtr, int traverserID); +int isEmptyForWaitingQ(WaitingQueueBin * queue, int allocSiteID); +WaitingQueueBin * mallocWaitingQueue(int size); +WaitingQueueBinVector * returnVectorToFreePool(struct BinVector_wq *ptr); +int removeFromQueue(WaitingQueueBin * queue, int allocSiteID, int TraverserID); +//int resolveWaitingQueueChain(struct WaitingQueue * queue, int allocSiteID, int traverserID); +WaitingQueueBinVector * mallocNewVector(); +WaitingQueueBinVector * getUsableVector(); + +//TODO this only a debug method GET RID OF IT WHEN DONE!! +WaitingQueueBinVector * debug_GetTheFreeBinsPtr(); +#endif /* WAITINGQUEUE_H_ */ diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueueTest.c b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueueTest.c new file mode 100644 index 00000000..3a010b6d --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/WaitingQueueTest.c @@ -0,0 +1,265 @@ +/* + * WaitingQueueTest.c + * + * Created on: Sep 25, 2010 + * Author: stephey + */ + +#include "WaitingQueue.h" +#include "mlp_lock.h" +#include "RuntimeConflictResolver.h" +#include +#include +//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 <\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; +} diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.c b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.c new file mode 100644 index 00000000..ef1ce252 --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.c @@ -0,0 +1,21 @@ +/* + * mlp_lock.c + * + * Created on: Sep 25, 2010 + * Author: stephey + */ + +//NOTE these files are the fake locks so I can test without compiling entire compiler +#include "mlp_lock.h" + +long LOCKXCHG(long * ptr1, long ptr2) { + long oldVal = *ptr1; + if(1) { + *ptr1 = ptr2; + } + else { + ptr1 = 0x1; + } + + return oldVal; +} diff --git a/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.h b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.h new file mode 100644 index 00000000..c7ef4786 --- /dev/null +++ b/Robust/src/Tests/mlp/stephen/Testing_WaitingQueue/mlp_lock.h @@ -0,0 +1,15 @@ +/* + * mlp_lock.h + * + * Created on: Sep 25, 2010 + * Author: stephey + */ + +//NOTE these files are the fake locks so I can test without compiling entire compiler + +#ifndef MLP_LOCK_H_ +#define MLP_LOCK_H_ + +long LOCKXCHG(long * ptr1, long ptr2); + +#endif /* MLP_LOCK_H_ */ -- 2.34.1