summaryrefslogtreecommitdiff
path: root/headers.c
diff options
context:
space:
mode:
authorPeter Wang <novalazy@gmail.com>2021-06-09 23:17:51 +0300
committerIvan Maidanski <ivmai@mail.ru>2021-06-09 23:22:05 +0300
commit9245e1154d271b9fd69c5c6de75c6ac37f3badc4 (patch)
treeca0f8d71f6eaeeee0be73e82ee68485441c51908 /headers.c
parent57b97be07c514fcc4b608b13768fd2bf637a5899 (diff)
downloadbdwgc-9245e1154d271b9fd69c5c6de75c6ac37f3badc4.tar.gz
Limit number of unmapped regions (Linux)
Issue #324 (bdwgc). When the number of areas exceeds vm.max_map_count on Linux (~65530 by default) then the mmap call in GC_unmap fails with ENOMEM. This commit fixes the issue by establishing a soft limit on the number of unmapped regions. * allchblk.c (get_block_ending_at): New static function. * allchblk.c [USE_MUNMAP && COUNT_UNMAPPED_REGIONS] (calc_num_unmapped_regions_delta): Likewise. * allchblk.c (GC_free_block_ending_at): Use get_block_ending_at(). * allchblk.c [GC_adjust_num_unmapped] (GC_adjust_num_unmapped): New inline function. * allchblk.c [USE_MUNMAP && COUNT_UNMAPPED_REGIONS] (GC_unmap_old): Skip unmapping if GC_num_unmapped_regions exceeds GC_UNMAPPED_REGIONS_SOFT_LIMIT, update GC_num_unmapped_regions value otherwise (before GC_unmap). * allchblk.c [USE_MUNMAP] (GC_merge_unmapped, GC_allochblk_nth): Call GC_adjust_num_unmapped() before GC_remap() and GC_unmap(). * headers.c (GC_next_used_block, GC_prev_block): Move/refine comment to gc_priv.h. * headers.c (GC_next_used_block): Rename to GC_next_block and add allow_free parameter. * include/private/gc_priv.h (GC_next_used_block): Likewise. * include/private/gc_priv.h [USE_MUNMAP && COUNT_UNMAPPED_REGIONS] (_GC_arrays): Add _num_unmapped_regions field. * include/private/gcconfig.h [(M68K || POWERPC || SPARC || I386 || MIPS || OR1K || ALPHA || IA64 || S390 || AARCH64 || ARM32 || CRIS || SH && !SH4 || AVR32 || M32R || X86_64 || HEXAGON || TILEPRO || TILEGX || RISCV) && LINUX] (COUNT_UNMAPPED_REGIONS): Define macro. * include/private/gcconfig.h [USE_MUNMAP && COUNT_UNMAPPED_REGIONS && !GC_UNMAPPED_REGIONS_SOFT_LIMIT] (GC_UNMAPPED_REGIONS_SOFT_LIMIT): Likewise. * os_dep.c [USE_MUNMAP] (GC_unmap_end): Move to gc_priv.h and make it inline. * mark.c (GC_push_next_marked, GC_push_next_marked_dirty, GC_push_next_marked_uncollectable): Use GC_next_block(h, FALSE) instead of GC_next_used_block(h).
Diffstat (limited to 'headers.c')
-rw-r--r--headers.c14
1 files changed, 5 insertions, 9 deletions
diff --git a/headers.c b/headers.c
index a1ab35a3..c71449f1 100644
--- a/headers.c
+++ b/headers.c
@@ -333,9 +333,7 @@ void GC_apply_to_all_blocks(void (*fn)(struct hblk *h, word client_data),
}
}
-/* Get the next valid block whose address is at least h */
-/* Return 0 if there is none. */
-GC_INNER struct hblk * GC_next_used_block(struct hblk *h)
+GC_INNER struct hblk * GC_next_block(struct hblk *h, GC_bool allow_free)
{
REGISTER bottom_index * bi;
REGISTER word j = ((word)h >> LOG_HBLKSIZE) & (BOTTOM_SZ-1);
@@ -349,14 +347,15 @@ GC_INNER struct hblk * GC_next_used_block(struct hblk *h)
while (bi != 0 && bi -> key < hi) bi = bi -> asc_link;
j = 0;
}
- while(bi != 0) {
+
+ while (bi != 0) {
while (j < BOTTOM_SZ) {
hdr * hhdr = bi -> index[j];
if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
j++;
} else {
- if (!HBLK_IS_FREE(hhdr)) {
- return((struct hblk *)
+ if (allow_free || !HBLK_IS_FREE(hhdr)) {
+ return ((struct hblk *)
(((bi -> key << LOG_BOTTOM_SZ) + j)
<< LOG_HBLKSIZE));
} else {
@@ -370,9 +369,6 @@ GC_INNER struct hblk * GC_next_used_block(struct hblk *h)
return(0);
}
-/* Get the last (highest address) block whose address is */
-/* at most h. Return 0 if there is none. */
-/* Unlike the above, this may return a free block. */
GC_INNER struct hblk * GC_prev_block(struct hblk *h)
{
bottom_index * bi;