/*************************************************************************** lockset.c - description ------------------- begin : Sat Nov 10 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 "ltypes.h" #include "setlocks.h" /* This functions copies the lock nodes. Deep copy. */ lock_node_t* copy_lock_node_list(lock_node_t* list) { lock_node_t* cur1 = NULL; lock_node_t* cur2 = NULL; lock_node_t* result = NULL; if(list == NULL) return NULL; result = malloc(sizeof(lock_node_t)); if(!result) { assert(result); locksmith_bail(); return NULL; } cur1 = list; cur2 = result; while(1) { *cur2 = *cur1; //copy the list. if(cur1->next == NULL) { cur2->next = NULL; return result; } cur2->next = malloc(sizeof(lock_node_t)); if(!cur2->next) { assert(cur2->next); locksmith_bail(); break; } cur2 = cur2->next; cur1 = cur1->next; } for(;result != NULL;result = result->next) { cur2 = result->next; free(result); } return NULL; } /* Since sorting the linked list would be a major pain in the ass, this is better. I am in a hurry! */ unsigned int count_nodes(lock_node_t* list) { int i = 0; for(;list != NULL;list = list->next,i++); return i; } bool compare_lock_lists(lock_node_t* l1,lock_node_t* l2) { //they are the same size don't worry. for(;l1 != NULL && l2 != NULL && l1->mutex != l2->mutex;l1 = l1->next,l2 = l2->next); if(l1 == NULL) return true; else return false; } void delete_lock_nodes(lock_node_t* node) { if(node == NULL) return; delete_lock_nodes(node->next); node->next = NULL; free(node); } lock_node_t* lock_union(lock_node_t* l1,lock_node_t* l2) { lock_node_t* result = NULL,*cur = NULL; while(l1 != NULL && l2 != NULL) { if(l1->mutex == l2->mutex) { if(result == NULL) { cur = malloc(sizeof(lock_node_t)); if(!cur) { assert(cur); delete_lock_nodes(result); locksmith_bail(); return NULL; } if(result == NULL) result = cur; *cur = *l1; cur->next = NULL; l1 = l1->next; l2 = l2->next; } else { cur->next = malloc(sizeof(lock_node_t)); if(!cur->next) { assert(cur->next); delete_lock_nodes(result); locksmith_bail(); return NULL; } *(cur->next) = *l1; cur->next->next = NULL; l1 = l1->next; l2 = l2->next; cur = cur->next; } } else if(l1->mutex > l2->mutex) { l2 = l2->next; }else { l1 = l1->next; } } return result; } int do_lockset(lock_set_t* set,line_type_e type,pthread_t thread) { lock_node_t* cur; switch(set->state) { case LS_EXCLUSIVE: { //this is the exclusive state. printf("Exclusive!\n"); if(set->excl_thread == thread) { return 0; //This is an exclusive reference. } else if(type == L_DYNAMIC_READ || type == L_STATIC_READ) { set->state = LS_SHARED; //mem now in read only shared state. return 0; }else { set->state = LS_SHRD_MOD; //mem now in read only shared state. } } case LS_SHARED: { printf("Shared\n"); if(type == L_DYNAMIC_READ || type == L_STATIC_READ) { if(set->all_locks == true) { set->read_held = copy_lock_node_list(get_current_locks(thread)); set->all_locks = false; }else { set->read_held = lock_union(get_current_locks(thread),set->read_held); } return 0; } //otherwise its now free game to be checked intesively. set->state = LS_SHRD_MOD; //will stay in shared modified mode. } case LS_SHRD_MOD: { //A little simpler. printf("Shared Mod\n"); if(set->all_locks == true) { set->read_held = copy_lock_node_list(get_current_locks(thread)); set->all_locks = false; }else { printf("\ncurrent: "); for(cur = get_current_locks(thread);cur != NULL;cur = cur->next) { printf("%d ",cur->mutex); } printf("\n"); printf("\nheld: "); for(cur = set->read_held;cur != NULL;cur = cur->next) { printf("%d ",cur->mutex); } printf("\n"); set->read_held = lock_union(get_current_locks(thread),set->read_held); printf("union: "); for(cur = set->read_held;cur != NULL;cur = cur->next) { printf("%d ",cur->mutex); } printf("\n"); } if(set->read_held == NULL) { fprintf(stderr,"Race Condition!\n"); return -1; } return 0; break; } } return -1; }