1 #include "hashStructure.h"
2 //#include "WaitingQueue.h"
7 //NOTE: this is only temporary (for testing) and will be removed in favor of thread local variables
8 //It's basically an array of hashStructures so we can simulate what would happen in a many-threaded version
9 HashStructure ** allHashStructures;
10 #define ISWRITEBIN(x) (x&BINMASK)
11 #define ISREADBIN(x) (!(x&BINMASK))
12 //#define POPCOUNT(x) __builtin_popcountll(x)
13 //__builtin_popcountll
17 //NOTE: only temporary
18 void rcr_createMasterHashTableArray(int maxSize){
21 HashStructure* rcr_createHashtable(int sizeofWaitingQueue){
23 HashStructure* newTable=(HashStructure*)RUNMALLOC(sizeof(HashStructure));
24 for(i=0;i<RNUMBINS;i++){
25 newTable->array[i].head=NULL;
26 newTable->array[i].tail=NULL;
32 WriteBinItem_rcr* rcr_createWriteBinItem(){
33 WriteBinItem_rcr* binitem=(WriteBinItem_rcr*)RUNMALLOC(sizeof(WriteBinItem_rcr));
34 binitem->item.type=WRITEBIN;
38 ReadBinItem_rcr* rcr_createReadBinItem(){
39 ReadBinItem_rcr* binitem=(ReadBinItem_rcr*)RUNMALLOC(sizeof(ReadBinItem_rcr));
41 binitem->item.type=READBIN;
45 inline int rcr_generateKey(void * ptr){
46 return (((struct ___Object___ *) ptr)->oid)&RH_MASK;
51 int rcr_WRITEBINCASE(HashStructure *T, void *ptr, SESEcommon *task, int index) {
52 //chain of bins exists => tail is valid
53 //if there is something in front of us, then we are not ready
55 int key=rcr_generateKey(ptr);
56 BinElement_rcr* be= &(T->array[key]); //do not grab head from here since it's locked (i.e. = 0x1)
58 //LOCK is still needed as different threads will remove items...
60 val=(BinItem_rcr *)0x1;
61 val=(BinItem_rcr *)LOCKXCHG((unsigned INTPTR*)&(be->head), (unsigned INTPTR)val);
62 } while(val==(BinItem_rcr*)0x1);
65 BinItem_rcr * b=(BinItem_rcr*)rcr_createWriteBinItem();
66 WriteBinItem_rcr * td = (WriteBinItem_rcr*)b;
70 //common to both types
72 td->bitindexrd=td->bitindexwr=1<<index;
80 BinItem_rcr *bintail=be->tail;
81 bitvt rdmask=0,wrmask=0;
84 if (ISWRITEBIN(bintail->type)) {
85 WriteBinItem_rcr * td = (WriteBinItem_rcr *)bintail;
86 //last one is to check for SESE blocks in a while loop.
87 if(unlikely(td->task == task)) {
90 if (!(bit & td->bitindexwr)) {
93 return (bintail->status==READY)?SPECREADY:SPECNOTREADY;
98 TraverserData * td = &((ReadBinItem_rcr *)bintail)->array[((ReadBinItem_rcr *)bintail)->index - 1];
99 if(unlikely(td->task == task)) {
100 //if it matches, then we remove it and the code below will upgrade it to a write.
101 ((ReadBinItem_rcr *)bintail)->index--;
102 atomic_dec(&bintail->total);
104 if (bintail->status!=READY)
110 WriteBinItem_rcr *b=rcr_createWriteBinItem();
116 //count already includes this
119 b->bitindexwr=bit|wrmask;
120 b->bitindexrd=bit|rdmask;
121 b->item.status=status;
122 bintail->next=(BinItem_rcr*)b;
123 be->tail=(BinItem_rcr*)b;
125 if (bintail->status==READY&&bintail->total==0) {
126 //we may have to set write as ready
127 while(val->total==0) {
128 if (val==((BinItem_rcr *)b)) {
129 b->item.status=READY;
142 int rcr_READBINCASE(HashStructure *T, void *ptr, SESEcommon * task, int index) {
144 int key=rcr_generateKey(ptr);
145 BinElement_rcr * be = &(T->array[key]);
147 //LOCK is still needed as different threads will remove items...
149 val=(BinItem_rcr *)0x1;
150 val=(BinItem_rcr *)LOCKXCHG((unsigned INTPTR*)&(be->head), (unsigned INTPTR)val);
151 } while(val==(BinItem_rcr*)0x1);
154 BinItem_rcr * b=(BinItem_rcr*)rcr_createReadBinItem();
155 ReadBinItem_rcr* readbin=(ReadBinItem_rcr*)b;
156 TraverserData * td = &(readbin->array[readbin->index++]);
160 //common to both types
162 td->bitindex=1<<index;
172 BinItem_rcr * bintail=be->tail;
174 //check if already added item or not.
175 if (ISWRITEBIN(bintail->type)) {
176 WriteBinItem_rcr * td = (WriteBinItem_rcr *)bintail;
177 if(unlikely(td->task==task)) {
180 int status=bintail->status;
181 if (!(td->bitindexrd & bit)) {
184 if (status==NOTREADY)
192 TraverserData * td = &((ReadBinItem_rcr *)bintail)->array[((ReadBinItem_rcr *)bintail)->index - 1];
193 if (unlikely(td->task==task)) {
196 int status=bintail->status;
197 if (!(td->bitindex & bit)) {
199 if (status==NOTREADY)
208 if (ISREADBIN(bintail->type)) {
209 return rcr_TAILREADCASE(T, ptr, val, bintail, key, task, index);
211 rcr_TAILWRITECASE(T, ptr, val, bintail, key, task, index);
217 int rcr_TAILREADCASE(HashStructure *T, void * ptr, BinItem_rcr *val, BinItem_rcr *bintail, int key, SESEcommon * task, int index) {
218 ReadBinItem_rcr * readbintail=(ReadBinItem_rcr*)T->array[key].tail;
221 if (readbintail->item.status==READY) {
229 if (readbintail->index==RNUMREAD) { // create new read group
230 ReadBinItem_rcr* rb=rcr_createReadBinItem();
231 td = &rb->array[rb->index++];
234 rb->item.status=status;
235 T->array[key].tail->next=(BinItem_rcr*)rb;
236 T->array[key].tail=(BinItem_rcr*)rb;
237 } else { // group into old tail
238 td = &readbintail->array[readbintail->index++];
239 atomic_inc(&readbintail->item.total);
243 td->bitindex=1<<index;
245 T->array[key].head=val;//released lock
249 void rcr_TAILWRITECASE(HashStructure *T, void *ptr, BinItem_rcr *val, BinItem_rcr *bintail, int key, SESEcommon * task, int index) {
250 ReadBinItem_rcr* rb=rcr_createReadBinItem();
251 TraverserData * td = &(rb->array[rb->index++]);
253 rb->item.status=NOTREADY;
256 td->bitindex=1<<index;
258 T->array[key].tail->next=(BinItem_rcr*)rb;
259 T->array[key].tail=(BinItem_rcr*)rb;
260 T->array[key].head=val;//released lock
263 rcr_RETIREHASHTABLE(HashStructure *T, SESEcommon *task, int key) {
264 BinElement_rcr * be = &(T->array[key]);
265 BinItem_rcr *b=be->head;
267 if(ISREADBIN(READBIN)) {
268 atomic_dec(&b->total);
269 if (b->next==NULL || b->total>0) {
273 //We either have a write bin or we are at the end of a read bin
276 // CHECK FIRST IF next is nonnull to guarantee that b.total cannot change
277 BinItem_rcr * val=(BinItem_rcr *)0x1;
279 val=(BinItem_rcr*)LOCKXCHG((unsigned INTPTR*)&(be->head), (unsigned INTPTR)val);
280 } while(val==(BinItem_rcr*)0x1);
282 // at this point have locked bin
283 BinItem_rcr *ptr=val;
287 if (ISREADBIN(ptr->type)) {
288 if (ptr->status==NOTREADY) {
289 ReadBinItem_rcr* rptr=(ReadBinItem_rcr*)ptr;
290 for (i=0;i<rptr->index;i++) {
291 RESOLVE(rptr->array[i]);
292 if (((INTPTR)rptr->array[i].task)&PARENTBIN) {
293 //parents go immediately
294 atomic_dec(&rptr->item.total);
299 if (ptr->next==NULL) {
304 } else if (ptr==val) {
311 if(ptr->status==NOTREADY) {
312 WriteBinItem_rcr* wptr=(WriteBinItem_rcr*)ptr;
315 if(((INTPTR)wptr->task)&PARENTBIN) {
319 } else { // write bin is already resolved
325 be->head=val; // release lock