/*************************************************************************** locksheld.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. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include "hash.h" #include "ltypes.h" #include "setlocks.h" #include "lockset.h" /* First start coding the pthread_id_node hash. I shall forever be known to my professor as hashman now. */ unsigned int pthread_hashsize = 0; unsigned int pthread_number = 0; pthread_id_node_t* pthread_id_hash; int construct_pthread_hash(int init_size) { pthread_id_hash = NULL; pthread_hashsize = getNextPrime(init_size); //init pthread hash. pthread_id_hash = malloc(sizeof(pthread_id_node_t) * pthread_hashsize); if(!pthread_id_hash) { assert(pthread_id_hash); return -1; } memset(pthread_id_hash,0,sizeof(pthread_id_node_t) * pthread_hashsize); return 0; } /* For efficient hashing. */ unsigned int pthread_hash_func(pthread_t thread) { return (thread << 2) % pthread_hashsize; } /* Make this linear. */ unsigned int pthread_hash_get(pthread_t thread) { unsigned int i = pthread_hash_func(thread); while(pthread_id_hash[i].is_full && pthread_id_hash[i].thread_id != thread) i++; if(pthread_id_hash[i].is_full) return i; //Else its a newly detected thread. pthread_id_hash[i].thread_id = thread; pthread_id_hash[i].is_full = true; pthread_id_hash[i].locks = NULL; pthread_number++; return i; } int add_lock_to_thread(pthread_mutex_t* mutex,pthread_t thread) { unsigned int i = pthread_hash_get(thread); lock_node_t* cur,*temp; //initialize the list. if(pthread_id_hash[i].locks == NULL) { pthread_id_hash[i].locks = malloc(sizeof(lock_node_t)); assert(pthread_id_hash[i].locks); if(!pthread_id_hash[i].locks) { assert(pthread_id_hash[i].locks); locksmith_bail(); //bail out. return -1; } pthread_id_hash[i].locks->mutex = mutex; pthread_id_hash[i].locks->timestamp = time(NULL); pthread_id_hash[i].locks->next = NULL; return 0; } cur = pthread_id_hash[i].locks; //I don't care if you get the lock more than once. if(pthread_id_hash[i].locks->mutex > mutex) { temp = pthread_id_hash[i].locks; pthread_id_hash[i].locks = malloc(sizeof(lock_node_t)); assert(pthread_id_hash[i].locks); if(!pthread_id_hash[i].locks) { assert(pthread_id_hash[i].locks); locksmith_bail(); //bail out. return -1; } pthread_id_hash[i].locks->mutex = mutex; pthread_id_hash[i].locks->timestamp = time(NULL); pthread_id_hash[i].locks->next = temp; return 0; } if(pthread_id_hash[i].locks->mutex == mutex) { return 0; } //This thing is going to be sorted. for(;cur->next != NULL && cur->next->mutex < mutex ;cur = cur->next); if(cur->next != NULL && cur->next->mutex == mutex) { return 0; } temp = cur->next; cur->next = malloc(sizeof(lock_node_t)); assert(cur->next); if(!cur->next) { assert(cur->next); locksmith_bail(); //bail out. return -1; } cur->next->mutex = mutex; cur->next->timestamp = time(NULL); cur->next->next = temp; return 0; } int remove_lock_from_thread(pthread_mutex_t* mutex,pthread_t thread) { unsigned int i = pthread_hash_get(thread); lock_node_t* cur,*temp; cur = pthread_id_hash[i].locks; if(cur == NULL) return 0; if(cur->mutex == mutex) { pthread_id_hash[i].locks = cur->next; free(cur); return 0; } //I don't care if you get the lock more than once. for(;cur->next != NULL && cur->next->mutex != mutex ;cur = cur->next); if(cur->next != NULL) { temp = cur->next->next; free(cur->next); cur->next = temp; } return 0; } void destroy_pthread_hash() { int i = 0; lock_node_t* cur,* temp; if(pthread_id_hash == NULL) return; for(;i < pthread_hashsize;i++) { if(pthread_id_hash[i].is_full) { cur = pthread_id_hash[i].locks; while(cur != NULL) { temp = cur->next; free(cur); cur = temp; } } } free(pthread_id_hash); } //if it gets to many resize the hash. int resize_pthread_hash() { pthread_id_node_t* temp = pthread_id_hash; unsigned int i = 0,j = 0, oldhashsize = pthread_hashsize; pthread_number = 0; pthread_hashsize = getNextPrime(2*pthread_hashsize); pthread_id_hash = malloc(sizeof(pthread_id_node_t)*pthread_hashsize); if(!pthread_id_hash) { assert(pthread_id_hash); pthread_id_hash = temp; locksmith_bail(); return -1; } //copy the old into the new. for(;i < oldhashsize;i++) { if(temp[i].is_full) { j = pthread_hash_get(temp[i].thread_id); pthread_id_hash[j].locks = temp[i].locks; } } free(temp); return 0; } lock_node_t* get_current_locks(pthread_t thread) { unsigned int i = pthread_hash_get(thread); return pthread_id_hash[i].locks; } void dump_lock_info() { int i = 0; lock_node_t* cur; FILE* output = fopen("lockdump.out","w"); if(pthread_id_hash == NULL) return; for(;i < pthread_hashsize;i++) { if(pthread_id_hash[i].is_full) { fprintf(output,"\nPthread id: %d, has locks\n",pthread_id_hash[i].thread_id); cur = pthread_id_hash[i].locks; while(cur != NULL) { fprintf(output,":%d ",cur->mutex); cur = cur->next; } } } fclose(output); }