/* ** MR_STM_block_thread is called to block the thread in high level C grades, ** using POSIX thread facilities, as there is a POSIX thread for every ** Mercury thread in these grades. The low level C grade equivalent of this ** code is defined in the stm_builtin library module. */ void MR_STM_block_thread(MR_STM_TransLog *tlog) { #if defined(MR_THREAD_SAFE) MR_STM_ConditionVar *thread_condvar; thread_condvar = MR_GC_NEW_ATTRIB(MR_STM_ConditionVar, MR_ALLOC_SITE_RUNTIME); MR_STM_condvar_init(thread_condvar); MR_STM_wait(tlog, thread_condvar); #if defined(MR_STM_DEBUG) fprintf(stderr, "STM BLOCKING: log <0x%.8lx>\n", (MR_Word)tlog); #endif MR_STM_condvar_wait(thread_condvar, &MR_STM_lock); #if defined(MR_STM_DEBUG) fprintf(stderr, "STM RESCHEDULING: log <0x%.8lx>\n", (MR_Word)tlog); #endif MR_STM_unwait(tlog, thread_condvar); MR_UNLOCK(&MR_STM_lock, "MR_STM_block_thread"); MR_GC_free_attrib(thread_condvar); #else MR_fatal_error("Blocking thread in non-parallel grade"); #endif }
MR_Dlist * MR_dlist_makelist0(void) { MR_Dlist *list; list = MR_GC_NEW_ATTRIB(MR_Dlist, MR_ALLOC_SITE_RUNTIME); MR_dlist_data(list) = NULL; MR_dlist_next(list) = list; MR_dlist_prev(list) = list; return list; }
void MR_insert_internal_label(const char *name, MR_Code *addr, const MR_LabelLayout *label_layout) { MR_Internal *internal; MR_Internal *prev_internal; MR_do_init_label_tables(); internal = MR_GC_NEW_ATTRIB(MR_Internal, MR_ALLOC_SITE_RUNTIME); internal->MR_internal_addr = addr; internal->MR_internal_layout = label_layout; internal->MR_internal_name = name; #ifdef MR_LOWLEVEL_DEBUG if (MR_progdebug) { /* ** We can't assume that MR_LOWLEVEL_DEBUG was turned on in the code ** that generated the call to this function just because ** MR_LOWLEVEL_DEBUG is turned on here. */ if (name != NULL) { printf("inserting internal label %s at %p\n", name, addr); } else { printf("inserting internal label at %p\n", addr); } } #endif prev_internal = (MR_Internal *) MR_insert_hash_table(internal_addr_table, internal); if (prev_internal != NULL) { /* ** Two labels at same location will happen quite often, when the code ** generated between them turns out to be empty. In this case, ** MR_insert_hash_table will not have inserted internal into the table. ** ** If only one of internal and prev_internal have a layout structure, ** make sure that we associate the layout structure with the label ** address. ** ** If both internal and prev_internal have a layout structure, ** we rely on the compiler to make sure that it is ok to use ** either of their layout structures. */ if (prev_internal->MR_internal_layout == NULL) { prev_internal->MR_internal_layout = label_layout; } } }
void MR_STM_record_transaction(MR_STM_TransLog *tlog, MR_STM_Var *var, MR_Word old_value, MR_Word new_value) { MR_STM_TransRecord *new_record; new_record = MR_GC_NEW_ATTRIB(MR_STM_TransRecord, MR_ALLOC_SITE_RUNTIME); new_record->MR_STM_tr_var = var; new_record->MR_STM_tr_old_value = old_value; new_record->MR_STM_tr_new_value = new_value; new_record->MR_STM_tr_next = tlog->MR_STM_tl_records; tlog->MR_STM_tl_records = new_record; }
void MR_STM_attach_waiter(MR_STM_Var *var, MR_ThreadId tid, MR_STM_ConditionVar *cvar) { MR_STM_Waiter *new_waiter; new_waiter = MR_GC_NEW_ATTRIB(MR_STM_Waiter, MR_ALLOC_SITE_RUNTIME); new_waiter->MR_STM_cond_var = cvar; if (var->MR_STM_var_waiters == NULL) { var->MR_STM_var_waiters = new_waiter; new_waiter->MR_STM_waiter_prev = NULL; new_waiter->MR_STM_waiter_next = NULL; } else { new_waiter->MR_STM_waiter_prev = NULL; new_waiter->MR_STM_waiter_next = var->MR_STM_var_waiters; var->MR_STM_var_waiters->MR_STM_waiter_prev = new_waiter; var->MR_STM_var_waiters = new_waiter; } }
MR_Dlist * MR_dlist_addtail(MR_Dlist *list, const void *data) { MR_Dlist *item; if (list == NULL) { list = MR_dlist_makelist0(); } item = MR_GC_NEW_ATTRIB(MR_Dlist, MR_ALLOC_SITE_RUNTIME); MR_dlist_data(item) = data; MR_dlist_length_field(list)++; // Item's pointers. MR_dlist_next(item) = list; MR_dlist_prev(item) = MR_dlist_prev(list); // Neighbours' pointers. MR_dlist_next(MR_dlist_prev(item)) = item; MR_dlist_prev(MR_dlist_next(item)) = item; return list; }