void MR_deallocate(MR_MemoryList allocated) { while (allocated != NULL) { MR_MemoryList next = allocated->next; /* ** These were allocated with MR_GC_NEW_ARRAY_ATTRIB so we must free ** using MR_GC_free_attrib. **/ MR_GC_free_attrib(allocated->data); MR_GC_free_attrib(allocated); allocated = next; } }
/* ** 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 }
static MR_MemoryZone * MR_rewind_nondetstack_segments(MR_Word *maxfr) { MR_MemoryZone *zone_to_reuse; MR_MemoryZone *zone; MR_Word *limit; MR_MemoryZones *list; zone_to_reuse = NULL; for (;;) { zone = MR_CONTEXT(MR_ctxt_nondetstack_zone); limit = (MR_Word *) zone->MR_zone_end; if (maxfr >= zone->MR_zone_min && maxfr < limit) { break; } #ifdef MR_DEBUG_STACK_SEGMENTS printf("\nfreeing zone\n"); MR_print_zone(stdout, zone); #endif // If there are several currently unneeded segments, this algorithm // reuses the zone of the topmost segment (the first segment in the // list from the top), since its contents are more likely to have been // recently referred to, and thus more likely to be in the cache. // // However, reusing the zone of the bottom-most unneeded segment // would look conceptually a bit neater in that it would preserve // the follows/precedes relationship between the zones. if (zone_to_reuse == NULL) { zone_to_reuse = zone; } else { MR_release_zone(zone); } list = MR_CONTEXT(MR_ctxt_prev_nondetstack_zones); assert(list != NULL); MR_CONTEXT(MR_ctxt_nondetstack_zone) = list->MR_zones_head; MR_CONTEXT(MR_ctxt_prev_nondetstack_zones) = list->MR_zones_tail; MR_GC_free_attrib(list); } #ifdef MR_DEBUG_STACK_SEGMENTS if (zone_to_reuse == NULL) { printf("\nno old nondet segment zone available for reuse\n"); } else { printf("\nreturning zone of old nondet segment for reuse: %p\n", zone_to_reuse); } #endif return zone_to_reuse; }