void* sgen_nursery_alloc_range (size_t desired_size, size_t minimum_size, size_t *out_alloc_size) { SGEN_LOG (4, "Searching for byte range desired size: %zd minimum size %zd", desired_size, minimum_size); HEAVY_STAT (++stat_nursery_alloc_range_requests); return sgen_fragment_allocator_par_range_alloc (&mutator_allocator, desired_size, minimum_size, out_alloc_size); }
static char* par_alloc_for_promotion_slow_path (int age, size_t objsize) { char *p; size_t allocated_size; size_t aligned_objsize = (size_t)align_up (objsize, SGEN_TO_SPACE_GRANULE_BITS); mono_mutex_lock (&par_alloc_buffer_refill_mutex); restart: p = age_alloc_buffers [age].next; if (G_LIKELY (p + objsize <= age_alloc_buffers [age].end)) { if (SGEN_CAS_PTR ((void*)&age_alloc_buffers [age].next, p + objsize, p) != p) goto restart; } else { /* Reclaim remaining space - if we OOMd the nursery nothing to see here. */ char *end = age_alloc_buffers [age].end; if (end) { do { p = age_alloc_buffers [age].next; } while (SGEN_CAS_PTR ((void*)&age_alloc_buffers [age].next, end, p) != p); sgen_clear_range (p, end); } /* By setting end to NULL we make sure no other thread can advance while we're updating.*/ age_alloc_buffers [age].end = NULL; STORE_STORE_FENCE; p = sgen_fragment_allocator_par_range_alloc ( &collector_allocator, MAX (aligned_objsize, AGE_ALLOC_BUFFER_DESIRED_SIZE), MAX (aligned_objsize, AGE_ALLOC_BUFFER_MIN_SIZE), &allocated_size); if (p) { set_age_in_range (p, p + allocated_size, age); age_alloc_buffers [age].next = p + objsize; STORE_STORE_FENCE; /* Next must arrive before the new value for next. */ age_alloc_buffers [age].end = p + allocated_size; } } mono_mutex_unlock (&par_alloc_buffer_refill_mutex); return p; }