Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent collection of uncollectable allocations #26

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions allchblk.c
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,11 @@ GC_INNER void GC_freehblk(struct hblk *hbp)
/* space at once. If we don't catch it here, strange things happen */
/* later. */

// Clear all the mark bytes to prevent blocks from lingering as
// uncollectable. Instead, this should only be opted-in on each allocation.
BZERO(hhdr->hb_marks, sizeof(hhdr->hb_marks));
GC_remove_counts(hbp, (size_t)size);

hhdr -> hb_sz = size;
# ifdef USE_MUNMAP
hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no;
Expand Down
2 changes: 1 addition & 1 deletion include/private/gc_pmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ GC_INLINE mse * GC_push_obj(ptr_t obj, const hdr * hhdr, mse * mark_stack_top,
{ /* cannot use do-while(0) here */ \
char * mark_byte_addr = (char *)(hhdr)->hb_marks + (bit_no); \
if (*mark_byte_addr != 0) break; /* go to the enclosing loop end */ \
*mark_byte_addr = 1; \
*mark_byte_addr |= MARK_TAG; \
}
# endif /* !PARALLEL_MARK */
#else
Expand Down
14 changes: 13 additions & 1 deletion malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,10 @@ GC_INNER void * GC_generic_malloc_aligned(size_t lb, int k, unsigned flags,

GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc(size_t lb, int k)
{
return GC_generic_malloc_aligned(lb, k, 0 /* flags */, 0 /* align_m1 */);
void* ptr = GC_generic_malloc_aligned(lb, k, 0 /* flags */, 0 /* align_m1 */);
if (ptr)
GC_clear_uncollectable(ptr);
return ptr;
}

GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_kind_global(size_t lb, int k)
Expand Down Expand Up @@ -451,7 +454,14 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_generic_malloc_uncollectable(
/* Allocate lb bytes of pointerful, traced, but not collectible data. */
GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb)
{
#ifdef FINALIZER_ELISION
void* ptr = GC_generic_malloc(lb, NORMAL);
if (ptr)
GC_set_uncollectable(ptr);
return ptr;
#else
return GC_generic_malloc_uncollectable(lb, UNCOLLECTABLE);
#endif
}

#ifdef GC_ATOMIC_UNCOLLECTABLE
Expand Down Expand Up @@ -667,8 +677,10 @@ GC_API void GC_CALL GC_free(void * p)
if (EXPECT(NULL == hhdr, FALSE)) return;
# endif
GC_ASSERT(GC_base(p) == p);
GC_ASSERT(GC_is_uncollectable(p));
LOCK();
free_internal(p, hhdr);

FREE_PROFILER_HOOK(p);
UNLOCK();
}
Expand Down
2 changes: 2 additions & 0 deletions mallocx.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ GC_API void * GC_CALL GC_realloc(void * p, size_t lb)
}
result = GC_generic_or_special_malloc((word)lb, obj_kind);
if (EXPECT(result != NULL, TRUE)) {
if(GC_is_uncollectable(p))
GC_set_uncollectable(result);
/* In case of shrink, it could also return original object. */
/* But this gives the client warning of imminent disaster. */
BCOPY(p, result, sz);
Expand Down
7 changes: 6 additions & 1 deletion mark.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,13 @@ GC_INNER void GC_clear_hdr_marks(hdr *hhdr)
/* No race as GC_realloc holds the allocator lock while updating hb_sz. */
last_bit = FINAL_MARK_BIT((size_t)hhdr->hb_sz);
# endif
unsigned i;
size_t sz = (size_t)hhdr->hb_sz;
unsigned n_marks = (unsigned)FINAL_MARK_BIT(sz);

BZERO(hhdr -> hb_marks, sizeof(hhdr->hb_marks));
for (i = 0; i <= n_marks; i += (unsigned)MARK_BIT_OFFSET(sz)) {
hhdr -> hb_marks[i] &= ~MARK_TAG;
}
set_mark_bit_from_hdr(hhdr, last_bit);
hhdr -> hb_n_marks = 0;
}
Expand Down
10 changes: 6 additions & 4 deletions reclaim.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,13 @@ STATIC ptr_t GC_reclaim_clear(struct hblk *hbp, const hdr *hhdr, word sz,
p = hbp -> hb_body;
plim = p + HBLKSIZE - sz;
for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz)) {
if (mark_bit_from_hdr(hhdr, bit_no)) {
if (mark_bit_from_hdr(hhdr, bit_no) || uncollectable_bit_from_hdr(hhdr, bit_no)) {
p += sz;
} else {
/* The object is available - put it on list. */
obj_link(p) = list;
list = p;
clear_uncollectable_bit_from_hdr(HDR(p), bit_no);
FREE_PROFILER_HOOK(p);
p = (ptr_t)GC_clear_block((word *)p, sz, pcount);
}
Expand All @@ -231,11 +232,12 @@ STATIC ptr_t GC_reclaim_uninit(struct hblk *hbp, const hdr *hhdr, word sz,
plim = (ptr_t)hbp + HBLKSIZE - sz;
for (bit_no = 0; ADDR_GE(plim, p);
bit_no += MARK_BIT_OFFSET(sz), p += sz) {
if (!mark_bit_from_hdr(hhdr, bit_no)) {
if (!mark_bit_from_hdr(hhdr, bit_no) && !uncollectable_bit_from_hdr(hhdr, bit_no)) {
n_bytes_found += sz;
/* The object is available - put it on list. */
obj_link(p) = list;
list = p;
clear_uncollectable_bit_from_hdr(HDR(p), bit_no);
FREE_PROFILER_HOOK(p);
}
}
Expand Down Expand Up @@ -293,7 +295,7 @@ STATIC void GC_reclaim_check(struct hblk *hbp, const hdr *hhdr, word sz)
plim = p + HBLKSIZE - sz;
for (bit_no = 0; ADDR_GE(plim, p);
bit_no += MARK_BIT_OFFSET(sz), p += sz) {
if (!mark_bit_from_hdr(hhdr, bit_no))
if (!mark_bit_from_hdr(hhdr, bit_no) && !uncollectable_bit_from_hdr(hhdr, bit_no))
GC_add_leaked(p);
}
}
Expand Down Expand Up @@ -866,7 +868,7 @@ STATIC void GC_CALLBACK GC_do_enumerate_reachable_objects(struct hblk *hbp,
}
/* Go through all objects in the block. */
for (bit_no = 0; ADDR_GE(plim, p); bit_no += MARK_BIT_OFFSET(sz), p += sz) {
if (mark_bit_from_hdr(hhdr, bit_no)) {
if (mark_bit_from_hdr(hhdr, bit_no) || uncollectable_bit_from_hdr(hhdr, bit_no)) {
((struct enumerate_reachable_s *)ped)->proc(p, sz,
((struct enumerate_reachable_s *)ped)->client_data);
}
Expand Down
Loading