asize_t caml_norm_minor_heap_size (intnat wsize) { asize_t page_size = caml_mem_round_up_pages(1); asize_t bs, max; if (wsize < Minor_heap_min) wsize = Minor_heap_min; bs = caml_mem_round_up_pages(Bsize_wsize (wsize)); Assert(page_size * 2 < (1 << Minor_heap_align_bits)); max = (1 << Minor_heap_align_bits) - page_size * 2; if (bs > max) bs = max; return bs; }
void caml_init_domains(uintnat minor_size) { int i; uintnat size; void* heaps_base; /* sanity check configuration */ if (caml_mem_round_up_pages(1 << Minor_heap_align_bits) != (1 << Minor_heap_align_bits)) caml_fatal_error("Minor_heap_align_bits misconfigured for this platform"); /* reserve memory space for minor heaps */ size = (uintnat)1 << (Minor_heap_sel_bits + Minor_heap_align_bits); /* To ensure Is_foreign gives no false positives, we reserve twice the address space needed and only use the first half */ heaps_base = caml_mem_map(size*2, size*2, 1 /* reserve_only */); if (!heaps_base) caml_raise_out_of_memory(); minor_heaps_base = (uintnat) heaps_base; caml_plat_mutex_init(&all_domains_lock); for (i = 0; i < Max_domains; i++) { struct dom_internal* dom = &all_domains[i]; caml_plat_mutex_init(&dom->roots_lock); dom->running = 0; dom->state.id = i; dom->tls_area = minor_heaps_base + (uintnat)(1 << Minor_heap_align_bits) * (uintnat)i; dom->tls_area_end = caml_mem_round_up_pages(dom->tls_area + sizeof(struct caml_domain_state)); dom->minor_heap_area = /* skip guard page */ caml_mem_round_up_pages(dom->tls_area_end + 1); dom->minor_heap_area_end = dom->minor_heap_area + (1 << Minor_heap_align_bits); } create_domain(minor_size, 1); if (!domain_self) caml_fatal_error("Failed to create main domain"); caml_init_global_roots(); caml_init_signal_handling(); }
void* caml_mem_map(uintnat size, uintnat alignment, int reserve_only) { uintnat alloc_sz = caml_mem_round_up_pages(size + alignment); void* mem; uintnat base, aligned_start, aligned_end; Assert(Is_power_2(alignment)); alignment = caml_mem_round_up_pages(alignment); Assert (alloc_sz > size); mem = mmap(0, alloc_sz, reserve_only ? PROT_NONE : (PROT_READ | PROT_WRITE), MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mem == MAP_FAILED) { return 0; } /* trim to an aligned region */ base = (uintnat)mem; aligned_start = round_up(base, alignment); aligned_end = aligned_start + caml_mem_round_up_pages(size); caml_mem_unmap((void*)base, aligned_start - base); caml_mem_unmap((void*)aligned_end, (base + alloc_sz) - aligned_end); return (void*)aligned_start; }