/*************************************************************************** hash.c - description ------------------- begin : Thu Nov 8 2001 copyright : (C) 2001 by Matt Sabins email : sabinsmh@clarkson.edu ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ //Insert Hashtable code here /* This is my old hashtable with I originally intended to use for compiler. Written in C. Found some bugs and had to remove the exception handing with jmp. I really should comment these things more. */ #include #include #include #include #include #include #include "hash.h" #include "ltypes.h" #include "setlocks.h" #include "lockset.h" int hashsize; // the size of the hash table; int secondhash; // the hash2 hash number. int number; //number of smith_node_ts in hashtable #define RESIZE_RATIO 4/5 smith_node_t* vect; int put(smith_node_t* cell); unsigned int get_index(memaddr_t a); __inline unsigned int ComputeIndexer(memaddr_t a) { return a + hashsize / 2; } unsigned int isPrime(unsigned int i) { unsigned int k; unsigned int j = i / 2 + 1; for(k = 2;k < j;k++) if(i % k == 0) return 0; return 1; } unsigned int getNextPrime(int i) { if((i % 2) == 0) i++; for(;!isPrime(i); i = i + 2); return i; } int resize() { unsigned int i = 0; unsigned int oldhashsize = hashsize; smith_node_t* newvect; smith_node_t* oldvect; hashsize = getNextPrime(hashsize*2); newvect = (smith_node_t *) malloc(sizeof(smith_node_t) * hashsize); if(newvect == NULL) { assert(newvect); hashsize = oldhashsize; locksmith_bail(); return -1; } secondhash = getNextPrime(2*hashsize); number = 0; oldvect = vect; vect = newvect; memset(vect,0,sizeof(smith_node_t)*hashsize); for(i = 0;i < oldhashsize;i++) { if(oldvect[i].isfull) { put(&oldvect[i]); } } free(oldvect); return 0; } int put(smith_node_t* cell) { int hashindex = ComputeIndexer(cell->addr); int index = (hashindex % hashsize); int hashed2 = (hashindex % secondhash); int i = 0; //just a counters; index = (index > 0) ? index : -index; //gets the hashed key; hashed2 = (hashed2 > 0) ? hashed2 : -hashed2; while(1) { if(!vect[index].isfull || vect[index].addr == cell->addr) { //the smith_node_t is open put it there; vect[index] = *cell; return 0; } i++; index = (index + i * hashed2) % hashsize; } } unsigned int get_index(memaddr_t a) { int hashindex = ComputeIndexer(a); int index = (hashindex % hashsize); int hashed2 = (hashindex % secondhash); int i = 0; //just a counters; index = (index > 0) ? index : -index; //gets the hashed key; hashed2 = (hashed2 > 0) ? hashed2 : -hashed2; while(1) { if(!vect[index].isfull || vect[index].addr == a) { //the smith_node_t is open put it there; return index; } i++; index = (index + i * hashed2) % hashsize; } } //almost the external function. int add_memory_access(memaddr_t addr, line_type_e type,pthread_t thread) { unsigned int index = get_index(addr); if(type == L_STATIC_READ || type == L_DYNAMIC_READ) { printf("Memaddr %d READ by thread %d\n",addr,thread); }else { printf("Memaddr %d WRITTEN to by thread %d\n",addr,thread); } //A first time memory access at code location!. if(!vect[index].isfull) { // if(type == L_STATIC_READ || type == L_DYNAMIC_READ) { // //An uninitialized read. Compiler should pick that up. // return 0; // } vect[index].addr = addr; vect[index].data = malloc(sizeof(lock_set_t)); if(!vect[index].data) { assert(vect[index].data); return -1; } vect[index].data->access_type = type; vect[index].data->state = LS_EXCLUSIVE; //A reade already. vect[index].data->excl_thread = thread; vect[index].data->read_held = NULL; vect[index].data->all_locks = true; vect[index].isfull = true; number++; printf("%d newly added\n",addr); if(number >= hashsize * RESIZE_RATIO) { puts("resized"); return resize(); } return 0; } //there is already a record of an access. //more importantly there is already a lockset associated with the loc. //first compare all the lock sets with the current lockset. assert(vect[index].data); //would be very bad not happen do_lockset(vect[index].data,type,thread); return 0; } int dump_memory_locks() { int i = 0; lock_node_t* cur = 0; FILE* output = fopen("memdump.out","w"); fprintf(output,"Memory dump\n"); for(;i < hashsize;i++) { if(vect[i].isfull) { fprintf(output,"Memory location: %d has locks at addresses.\n",vect[i].addr); if(vect[i].data) { switch(vect[i].data->state) { case LS_EXCLUSIVE: fprintf(output,"Exclusive to thread, %d.\n",vect[i].data->excl_thread); break; case LS_SHARED: fprintf(output,"Shared\n");break; case LS_SHRD_MOD: fprintf(output,"Shared Mod\n");break; } cur = vect[i].data->read_held; if(cur == NULL) fprintf(output,"No locks held:"); for(;cur != NULL;cur = cur->next) { fprintf(output,":%d ",cur->mutex); } fprintf(output,"\n"); } } } return 0; } int construct_hash(unsigned int size) { number = 0; hashsize = getNextPrime(size); secondhash = getNextPrime(hashsize + 1); vect = (smith_node_t *) malloc(sizeof(smith_node_t) * hashsize); if(!vect) { assert(vect); locksmith_bail(); return -1; } memset(vect,0,sizeof(smith_node_t)*hashsize); return 0; } /* Its late and I want to get to testing. */ void delete_lock_sets(lock_set_t* set) { if(set == NULL) return; delete_lock_nodes(set->read_held); free(set); } void destroy_hash() { //release memory. int i = 0; for(;i < hashsize;i++) { if(vect[i].isfull) { delete_lock_sets(vect[i].data); } } free(vect); //free hash. }