Redesign actionlist and change acquire fence
[c11tester.git] / actionlist.cc
diff --git a/actionlist.cc b/actionlist.cc
new file mode 100644 (file)
index 0000000..f859746
--- /dev/null
@@ -0,0 +1,248 @@
+#include "actionlist.h"
+#include "action.h"
+#include <string.h>
+#include "stl-model.h"
+#include <limits.h>
+
+actionlist::actionlist() :
+       _size(0)
+{
+}
+
+actionlist::~actionlist() {
+}
+
+allnode::allnode() :
+       count(0) {
+       bzero(children, sizeof(children));
+}
+
+allnode::~allnode() {
+       if (count != 0)
+               for(int i=0;i<ALLNODESIZE;i++) {
+                       if (children[i] != NULL && !(((uintptr_t) children[i]) & ISACT))
+                               delete children[i];
+               }
+}
+
+sllnode<ModelAction *> * allnode::findPrev(modelclock_t index) {
+       allnode * ptr = this;
+       modelclock_t increment = 1;
+       modelclock_t mask = ALLMASK;
+       int totalshift = 0;
+       index -= increment;
+
+       while(1) {
+               modelclock_t shiftclock = index >> totalshift;
+               modelclock_t currindex = shiftclock & ALLMASK;
+
+               //See if we went negative...
+               if (currindex != ALLMASK) {
+                       if (ptr->children[currindex] == NULL) {
+                               //need to keep searching at this level
+                               index -= increment;
+                               continue;
+                       } else {
+                               //found non-null...
+                               if (totalshift != 0)
+                                       ptr = ptr->children[currindex];
+                               //need to increment here...
+                               increment = increment >> ALLBITS;
+                               mask = mask >> ALLBITS;
+                               totalshift -= ALLBITS;
+                               break;
+                       }
+               }
+               //If we get here, we already did the decrement earlier...no need to decrement again
+               ptr = ptr->parent;
+               increment = increment << ALLBITS;
+               mask = mask << ALLBITS;
+               totalshift += ALLBITS;
+
+               if (increment == 0) {
+                       return NULL;
+               }
+       }
+
+       while(1) {
+               while(1) {
+                       modelclock_t shiftclock = index >> totalshift;
+                       modelclock_t currindex = shiftclock & ALLMASK;
+                       if (ptr->children[currindex] != NULL) {
+                               if (totalshift != 0) {
+                                       ptr = ptr->children[currindex];
+                               } else {
+                                       allnode * act = ptr->children[currindex];
+                                       sllnode<ModelAction *> * node = reinterpret_cast<sllnode<ModelAction *>*>(((uintptr_t)act) & ALLMASK);
+                                       return node;
+                               }
+                       }
+                       index -= increment;
+               }
+
+               increment = increment >> ALLBITS;
+               mask = mask >> ALLBITS;
+               totalshift -= ALLBITS;
+       }
+}
+
+void actionlist::addAction(ModelAction * act) {
+       _size++;
+       int shiftbits = MODELCLOCKBITS - ALLBITS;
+       modelclock_t clock = act->get_seq_number();
+
+       allnode * ptr = &root;
+       do {
+               int index = (clock >> shiftbits) & ALLMASK;
+               allnode * tmp = ptr->children[index];
+               if (shiftbits == 0) {
+                       sllnode<ModelAction *> * llnode = new sllnode<ModelAction *>();
+                       llnode->val = act;
+                       if (tmp == NULL) {
+                               ptr->children[index] = reinterpret_cast<allnode *>(((uintptr_t) llnode) | ISACT);
+                               sllnode<ModelAction *> * llnodeprev = ptr->findPrev(index);
+                               if (llnodeprev != NULL) {
+
+                                       llnode->next = llnodeprev->next;
+                                       llnode->prev = llnodeprev;
+
+                                       //see if we are the new tail
+                                       if (llnodeprev->next == NULL)
+                                               tail = llnode;
+                                       else
+                                               llnode->next->prev = llnode;
+
+                                       llnodeprev->next = llnode;
+                               } else {
+                                       //We are the begining
+                                       llnode->next = head;
+                                       llnode->prev = NULL;
+                                       if (head != NULL) {
+                                               head->prev = llnode;
+                                       } else {
+                                               //we are the first node
+                                               tail = llnode;
+                                       }
+
+                                       head = llnode;
+                               }
+                               //need to find next link
+                               ptr->count++;
+                       } else {
+                               //handle case where something else is here
+
+                               sllnode<ModelAction *> * llnodeprev = reinterpret_cast<sllnode<ModelAction *>*>(((uintptr_t) llnode) & ALLMASK);
+                               llnode->next = llnodeprev->next;
+                               llnode->prev = llnodeprev;
+                               llnode->next->prev = llnode;
+                               llnodeprev->next = llnode;
+                               ptr->children[index] = reinterpret_cast<allnode *>(((uintptr_t) llnode) | ISACT);
+                       }
+                       return;
+               } else if (tmp == NULL) {
+                       tmp = new allnode();
+                       ptr->children[index] = tmp;
+                       tmp->parent=ptr;
+                       ptr->count++;
+               }
+               shiftbits -= ALLBITS;
+               ptr = tmp;
+       } while(1);
+
+}
+
+void decrementCount(allnode * ptr) {
+       ptr->count--;
+       if (ptr->count == 0) {
+               if (ptr->parent != NULL) {
+                       for(uint i=0;i<ALLNODESIZE;i++) {
+                               if (ptr->parent->children[i]==ptr) {
+                                       ptr->parent->children[i] = NULL;
+                                       decrementCount(ptr->parent);
+                               }
+                       }
+               }
+               delete ptr;
+       }
+}
+
+void actionlist::removeAction(ModelAction * act) {
+       int shiftbits = MODELCLOCKBITS - ALLBITS;
+       modelclock_t clock = act->get_seq_number();
+       allnode * ptr = &root;
+       do {
+               int index = (clock >> shiftbits) & ALLMASK;
+               allnode * tmp = ptr->children[index];
+               if (shiftbits == 0) {
+                       if (tmp == NULL) {
+                               //not found
+                               return;
+                       } else {
+                               sllnode<ModelAction *> * llnode = reinterpret_cast<sllnode<ModelAction *> *>(((uintptr_t) tmp) & ALLMASK);
+                               bool first = true;
+                               do {
+                                       if (llnode->val == act) {
+                                               //found node to remove
+                                               sllnode<ModelAction *> * llnodeprev = llnode->prev;
+                                               sllnode<ModelAction *> * llnodenext = llnode->next;
+                                               if (llnodeprev != NULL) {
+                                                       llnodeprev->next = llnodenext;
+                                               } else {
+                                                       head = llnodenext;
+                                               }
+                                               if (llnodenext != NULL) {
+                                                       llnodenext->prev = llnodeprev;
+                                               } else {
+                                                       tail = llnodeprev;
+                                               }
+                                               if (first) {
+                                                       //see if previous node has same clock as us...
+                                                       if (llnodeprev->val->get_seq_number() == clock) {
+                                                               ptr->children[index] = reinterpret_cast<allnode *>(((uintptr_t)llnodeprev) | ISACT);
+                                                       } else {
+                                                               //remove ourselves and go up tree
+                                                               ptr->children[index] = NULL;
+                                                               decrementCount(ptr);
+                                                       }
+                                               }
+                                               delete llnode;
+                                               _size--;
+                                               return;
+                                       }
+                                       llnode = llnode->prev;
+                                       first = false;
+                               } while(llnode != NULL && llnode->val->get_seq_number() == clock);
+                               //node not found in list... no deletion
+                               return;
+                       }
+               } else if (tmp == NULL) {
+                       //not found
+                       return;
+               }
+               shiftbits -= ALLBITS;
+               ptr = tmp;
+       } while(1);
+}
+
+void actionlist::clear() {
+       for(uint i = 0;i < ALLNODESIZE;i++) {
+               if (root.children[i] != NULL) {
+                       delete root.children[i];
+                       root.children[i] = NULL;
+               }
+       }
+
+       while(head != NULL) {
+               sllnode<ModelAction *> *tmp=head->next;
+               delete head;
+               head = tmp;
+       }
+       tail=NULL;
+
+       root.count = 0;
+       _size = 0;
+}
+
+bool actionlist::isEmpty() {
+       return root.count == 0;
+}