CILK_EXPORT void __CILKRTS_STRAND_STALE( __cilkrts_hyper_destroy(__cilkrts_hyperobject_base *hb)) { // Disable Cilkscreen for the duration of this call. The destructor for // this class will re-enable Cilkscreen when the method returns. This // will prevent Cilkscreen from reporting apparent races in reducers DisableCilkscreen x; __cilkrts_worker* w = __cilkrts_get_tls_worker(); if (! w) { // If no worker, then Cilk is not running and there is no reducer // map. Do nothing. The reducer's destructor will take care of // destroying the leftmost view. return; } const char *UNSYNCED_REDUCER_MSG = "Destroying a reducer while it is visible to unsynced child tasks, or\n" "calling CILK_C_UNREGISTER_REDUCER() on an unregistered reducer.\n" "Did you forget a _Cilk_sync or CILK_C_REGISTER_REDUCER()?"; cilkred_map* h = w->reducer_map; if (NULL == h) cilkos_error(UNSYNCED_REDUCER_MSG); // Does not return if (h->merging) { verify_current_wkr(w); __cilkrts_bug("User error: hyperobject used by another hyperobject"); } void* key = get_hyperobject_key(hb); elem *el = h->lookup(key); // Verify that the reducer is being destroyed from the leftmost strand for // which the reducer is defined. if (! (el && el->is_leftmost())) cilkos_error(UNSYNCED_REDUCER_MSG); #if REDPAR_DEBUG >= 3 fprintf(stderr, "[W=%d, key=%p, lookup in map %p, found el=%p, about to destroy]\n", w->self, key, h, el); #endif // Remove the element from the hash bucket. Do not bother shrinking // the bucket. Note that the destroy() function does not actually // call the destructor for the leftmost view. el->destroy(); do { el[0] = el[1]; ++el; } while (el->key); --h->nelem; #if REDPAR_DEBUG >= 2 fprintf(stderr, "[W=%d, desc=hyper_destroy_finish, key=%p, w->reducer_map=%p]\n", w->self, key, w->reducer_map); #endif }
/** * Load the replay log for a worker into memory. * * @param w The worker we're loading the replay for. */ static void load_recorded_log(__cilkrts_worker *w) { char ped_type[PED_TYPE_SIZE]; char ped_str[PEDIGREE_BUFF_SIZE]; int32_t i1 = -1, i2 = -1; int fret; char local_replay_file_name[512]; FILE *f; // Open the log for reading cilk_snprintf_si(local_replay_file_name, sizeof(local_replay_file_name), "%s%d.cilklog", w->g->record_replay_file_name, w->self); f = fopen(local_replay_file_name, "r"); // Make sure we found a log! CILK_ASSERT (NULL != f); // Initialize the replay_list allocate_replay_list(w, f); replay_entry_t *entry = w->l->replay_list_root; // Read the data out and add it to our tables while (! feof(f)) { #ifndef INCLUDE_SEQUENCE_NUMBER fret = fscanf(f, "%s %s %d %d\n", ped_type, ped_str, &i1, &i2); if(EOF == fret) break; // We must have read 4 fields CILK_ASSERT(4 == fret); #else int32_t write_num; fret = fscanf(f, "%s %s %d %d %d\n", ped_type, ped_str, &i1, &i2, &write_num); if(EOF == fret) break; // We must have read 5 fields CILK_ASSERT(5 == fret); #endif // INCLUDE_SEQUENCE_NUMBER // Load the data into the entry if (0 == strcmp(ped_type, PED_TYPE_STR_WORKERS)) { // Verify we're replaying with the same number of workers we recorded with if (i1 != w->g->P) { // Fatal error - does not return cilkos_error("Cannot continue replay: number of workers(%d) doesn't match " "that from the recording(%d).\n", w->g->P, i1); } // Verify that we understand this version of the pedigree file if (PED_VERSION != i2) { // Fatal error - does not return cilkos_error("Pedigree file version %d doesn't match current " "version %d - cannot continue.\n", i2, PED_VERSION); } } else { entry->load(ped_type, ped_str, i1, i2); entry++; } } // Make sure we've filled the allocated memory. We initialized the last // entry in CILK_ASSERT(ped_type_last == entry->m_type); w->l->replay_list_entry = w->l->replay_list_root; // Close the log and return fclose(f); }