/** * Increments the global reference count of a managed value * * @pre h != NULL * * @post h->global_rc = h->global_rc@pre + 1 * * @param Handle to update */ void PICC_handle_incr_ref_count(PICC_Handle *h) { /* #ifdef CONTRACT_PRE_INV */ /* //inv */ /* PICC_Channel_inv(channel); */ /* #endif */ #ifdef CONTRACT_PRE //pre ASSERT(h != NULL ); #endif #ifdef CONTRACT_POST // capture // int global_rc_at_pre = h->global_rc; #endif LOCK_HANDLE(h); h->global_rc++; RELEASE_HANDLE(h); /* #ifdef CONTRACT_POST_INV */ /* //inv */ /* PICC_Channel_inv(channel); */ /* #endif */ /* #ifdef CONTRACT_POST */ /* //post */ /* ASSERT(channel->global_rc == global_rc_at_pre + 1 ); */ /* // cannot be asserted ! as the lock is released we don't have any garanty */ /* #endif */ }
static void *process_thread(void *par) { struct genhistdb_struct *handle = (struct genhistdb_struct *)par; pthread_t self_thread; Node *node; hist_t *hist = NULL; int self_ind; if(!handle) goto bailout; pthread_barrier_wait(&handle->barrier); if(handle->error != 0) { goto bailout; } self_thread = pthread_self(); for(self_ind = 0; self_ind < handle->nr_threads; self_ind++) { if(handle->threads[self_ind] == self_thread) break; } if(self_ind == handle->nr_threads) { printf("ERROR! I am not one of the started threads for this handle\n"); goto bailout; } node = handle->per_thread_list[self_ind]; while(node) { hist = gen_hist(node->name); LOCK_HANDLE(handle, self_ind); handle->completed++; if(!hist) { printf("Hist generation for %s failed\n", node->name); } else { handle->updated++; memcpy(&handle->hist_list[handle->hist_len], hist, sizeof(hist_t)); free(hist); handle->hist_len++; } UNLOCK_HANDLE(handle, self_ind); node = node->next; } bailout: pthread_exit(NULL); }
/** * Decrements the global reference count of a managed value * * @pre h != NULL * * @post h->global_rc = h->global_rc@pre - 1 * * @param Handle to update */ void PICC_handle_dec_ref_count(PICC_Handle **h) { /* #ifdef CONTRACT_PRE_INV */ /* //inv */ /* PICC_Channel_inv(*channel); */ /* #endif */ #ifdef CONTRACT_PRE //pre ASSERT(*h != NULL ); #endif #ifdef CONTRACT_POST // capture // int global_rc_at_pre = (*h)->global_rc; #endif // I think there is a problem here: what happens if global_rc is equal to one // and another thread was about to increment it but lost the race to acquire the lock ? // // moreover, for now the lock is alocated in the channel/handle with the previous // case in mind we cannot free it in the reclaim // I think a solution would be to have a pool of Lock witch contain the lock itself // and the value it's suposed to lock // // kind of: // struct{ // atomic_int cpt; // void *content; // } // // in the function lock_alloc we would keep track of all the locks and we could // reuse the ones that have cpt == 0 && content == NULL // LOCK_HANDLE(*h); (*h)->global_rc--; if ((*h)->global_rc == 0) { RELEASE_HANDLE(*h); ALLOC_ERROR(reclaim_error); (*h)->reclaim(*h, &reclaim_error); *h = NULL; if (HAS_ERROR(reclaim_error)) CRASH(&reclaim_error); } else{ RELEASE_HANDLE(*h); } /* #ifdef CONTRACT_POST_INV */ /* if (*h != NULL) */ /* PICC_Channel_inv(*channel); */ /* #endif */ /* #ifdef CONTRACT_POST */ /* if(global_rc_at_pre > 1) */ /* ASSERT((*channel)->global_rc == global_rc_at_pre - 1 ); */ //cannot be asserted see incr for the same comment /* #endif */ }