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;
49 int rcr_WRITEBINCASE(HashStructure *T, void *ptr, SESEcommon *task, int index) {
50 //chain of bins exists => tail is valid
51 //if there is something in front of us, then we are not ready
53 int key=rcr_generateKey(ptr);
54 BinElement_rcr* be= &(T->array[key]); //do not grab head from here since it's locked (i.e. = 0x1)
56 //LOCK is still needed as different threads will remove items...
58 val=(BinItem_rcr *)0x1;
59 val=(BinItem_rcr *)LOCKXCHG((unsigned INTPTR*)&(be->head), (unsigned INTPTR)val);
60 } while(val==(BinItem_rcr*)0x1);
63 BinItem_rcr * b=(BinItem_rcr*)rcr_createWriteBinItem();
64 WriteBinItem_rcr * td = (WriteBinItem_rcr*)b;
68 //common to both types
70 td->bitindexrd=td->bitindexwr=1<<index;
78 BinItem_rcr *bintail=be->tail;
79 bitvt rdmask=0,wrmask=0;
82 if (ISWRITEBIN(bintail->type)) {
83 WriteBinItem_rcr * td = (WriteBinItem_rcr *)bintail;
84 //last one is to check for SESE blocks in a while loop.
85 if(unlikely(td->task == task)) {
88 if (!(bit & td->bitindexwr)) {
91 return (bintail->status==READY)?READY:SPECNOTREADY;
96 TraverserData * td = &((ReadBinItem_rcr *)bintail)->array[((ReadBinItem_rcr *)bintail)->index - 1];
97 if(unlikely(td->task == task)) {
98 //if it matches, then we remove it and the code below will upgrade it to a write.
99 ((ReadBinItem_rcr *)bintail)->index--;
100 atomic_dec(&bintail->total);
102 if (bintail->status!=READY)
108 WriteBinItem_rcr *b=rcr_createWriteBinItem();
114 //count already includes this
117 b->bitindexwr=bit|wrmask;
118 b->bitindexrd=bit|rdmask;
119 b->item.status=status;
120 bintail->next=(BinItem_rcr*)b;
121 be->tail=(BinItem_rcr*)b;
123 if (bintail->status==READY&&bintail->total==0) {
124 //we may have to set write as ready
125 while(val->total==0) {
126 if (val==((BinItem_rcr *)b)) {
127 b->item.status=READY;
140 int rcr_READBINCASE(HashStructure *T, void *ptr, SESEcommon * task, int index) {
142 int key=rcr_generateKey(ptr);
143 BinElement_rcr * be = &(T->array[key]);
145 //LOCK is still needed as different threads will remove items...
147 val=(BinItem_rcr *)0x1;
148 val=(BinItem_rcr *)LOCKXCHG((unsigned INTPTR*)&(be->head), (unsigned INTPTR)val);
149 } while(val==(BinItem_rcr*)0x1);
152 BinItem_rcr * b=(BinItem_rcr*)rcr_createReadBinItem();
153 ReadBinItem_rcr* readbin=(ReadBinItem_rcr*)b;
154 TraverserData * td = &(readbin->array[readbin->index++]);
158 //common to both types
160 td->bitindex=1<<index;
170 BinItem_rcr * bintail=be->tail;
172 //check if already added item or not.
173 if (ISWRITEBIN(bintail->type)) {
174 WriteBinItem_rcr * td = (WriteBinItem_rcr *)bintail;
175 if(unlikely(td->task==task)) {
178 int status=bintail->status;
179 if (!(td->bitindexrd & bit)) {
182 if (status==NOTREADY)
190 TraverserData * td = &((ReadBinItem_rcr *)bintail)->array[((ReadBinItem_rcr *)bintail)->index - 1];
191 if (unlikely(td->task==task)) {
194 int status=bintail->status;
195 if (!(td->bitindex & bit)) {
197 if (status==NOTREADY)
206 if (ISREADBIN(bintail->type)) {
207 return rcr_TAILREADCASE(T, ptr, val, bintail, key, task, index);
209 rcr_TAILWRITECASE(T, ptr, val, bintail, key, task, index);
215 int rcr_TAILREADCASE(HashStructure *T, void * ptr, BinItem_rcr *val, BinItem_rcr *bintail, int key, SESEcommon * task, int index) {
216 ReadBinItem_rcr * readbintail=(ReadBinItem_rcr*)T->array[key].tail;
219 if (readbintail->item.status==READY) {
227 if (readbintail->index==RNUMREAD) { // create new read group
228 ReadBinItem_rcr* rb=rcr_createReadBinItem();
229 td = &rb->array[rb->index++];
232 rb->item.status=status;
233 T->array[key].tail->next=(BinItem_rcr*)rb;
234 T->array[key].tail=(BinItem_rcr*)rb;
235 } else { // group into old tail
236 td = &readbintail->array[readbintail->index++];
237 atomic_inc(&readbintail->item.total);
241 td->bitindex=1<<index;
243 T->array[key].head=val;//released lock
247 void rcr_TAILWRITECASE(HashStructure *T, void *ptr, BinItem_rcr *val, BinItem_rcr *bintail, int key, SESEcommon * task, int index) {
248 ReadBinItem_rcr* rb=rcr_createReadBinItem();
249 TraverserData * td = &(rb->array[rb->index++]);
251 rb->item.status=NOTREADY;
254 td->bitindex=1<<index;
256 T->array[key].tail->next=(BinItem_rcr*)rb;
257 T->array[key].tail=(BinItem_rcr*)rb;
258 T->array[key].head=val;//released lock
261 rcr_RETIREHASHTABLE(HashStructure *T, SESEcommon *task, int key) {
262 BinElement_rcr * be = &(T->array[key]);
263 BinItem_rcr *b=be->head;
265 if(ISREADBIN(READBIN)) {
266 atomic_dec(&b->total);
267 if (b->next==NULL || b->total>0) {
271 //We either have a write bin or we are at the end of a read bin
274 // CHECK FIRST IF next is nonnull to guarantee that b.total cannot change
275 BinItem_rcr * val=(BinItem_rcr *)0x1;
277 val=(BinItem_rcr*)LOCKXCHG((unsigned INTPTR*)&(be->head), (unsigned INTPTR)val);
278 } while(val==(BinItem_rcr*)0x1);
280 // at this point have locked bin
281 BinItem_rcr *ptr=val;
285 if (ISREADBIN(ptr->type)) {
286 if (ptr->status==NOTREADY) {
287 ReadBinItem_rcr* rptr=(ReadBinItem_rcr*)ptr;
288 for (i=0;i<rptr->index;i++) {
289 RESOLVE(rptr->array[i]);
290 if (((INTPTR)rptr->array[i].task)&PARENTBIN) {
291 //parents go immediately
292 atomic_dec(&rptr->item.total);
297 if (ptr->next==NULL) {
302 } else if (ptr==val) {
309 if(ptr->status==NOTREADY) {
310 WriteBinItem_rcr* wptr=(WriteBinItem_rcr*)ptr;
313 if(((INTPTR)wptr->task)&PARENTBIN) {
317 } else { // write bin is already resolved
323 be->head=val; // release lock