Skip to content

Commit

Permalink
Add memalign and posix_memalign methods for buffered finalization
Browse files Browse the repository at this point in the history
The Rust compiler uses these methods instead of generic malloc under
certain conditions and without support we can get rustc assertion errors
in standard library methods which expect certain alignment requirements.

This uses the same allocation semantics from existing `GC_memalign` and
`GC_posix_memalign` definitions inside mallocx.c
  • Loading branch information
jacob-hughes committed May 9, 2024
1 parent 7c30dbc commit 49fdfc2
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
50 changes: 50 additions & 0 deletions fnlz_mlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

#ifdef ENABLE_DISCLAIM

#ifndef MSWINCE
# include <errno.h>
#endif

#include "gc/gc_disclaim.h"
#include "private/dbg_mlc.h" /* for oh type */

Expand Down Expand Up @@ -213,6 +217,52 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_buffered_finalize_malloc(size_t lb)
return (word *)op;
}

GC_API GC_ATTR_MALLOC void * GC_CALL GC_buffered_finalize_memalign(size_t align, size_t lb)
{
size_t offset;
ptr_t result;
size_t align_m1 = align - 1;

/* Check the alignment argument. */
if (EXPECT(0 == align || (align & align_m1) != 0, FALSE)) return NULL;
if (align <= GC_GRANULE_BYTES) return GC_buffered_finalize_malloc(lb);

if (align >= HBLKSIZE/2 || lb >= HBLKSIZE/2) {
return GC_clear_stack(GC_generic_malloc_aligned(lb, GC_fin_q_kind,
0 /* flags */, align_m1));
}

result = (ptr_t)GC_buffered_finalize_malloc(SIZET_SAT_ADD(lb, align_m1));
offset = (size_t)(word)result & align_m1;
if (offset != 0) {
offset = align - offset;
if (!GC_all_interior_pointers) {
GC_STATIC_ASSERT(VALID_OFFSET_SZ <= HBLKSIZE);
GC_ASSERT(offset < VALID_OFFSET_SZ);
GC_register_displacement(offset);
}
result += offset;
}
GC_ASSERT(((word)result & align_m1) == 0);
return result;
}

GC_API int GC_CALL GC_buffered_finalize_posix_memalign(void **memptr, size_t align, size_t lb)
{
size_t align_minus_one = align - 1; /* to workaround a cppcheck warning */

/* Check alignment properly. */
if (EXPECT(align < sizeof(void *)
|| (align_minus_one & align) != 0, FALSE)) {
return EINVAL;
}

if ((*memptr = GC_buffered_finalize_memalign(align, lb)) == NULL) {
return ENOMEM;
}
return 0;
}


GC_API void GC_CALL GC_init_buffered_finalization(void)
{
Expand Down
6 changes: 6 additions & 0 deletions include/gc/gc_disclaim.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ GC_API void GC_CALL GC_init_buffered_finalization(void);
GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
GC_buffered_finalize_malloc(size_t);

GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(2) void * GC_CALL
GC_buffered_finalize_memalign(size_t /* align */, size_t /* lb */);

GC_API int GC_CALL GC_buffered_finalize_posix_memalign(void ** /* memptr */, size_t /* align */,
size_t /* lb */) GC_ATTR_NONNULL(1);

GC_API void GC_CALL GC_finalize_objects(void);

#ifdef __cplusplus
Expand Down
29 changes: 29 additions & 0 deletions tests/gctest.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@
# define INIT_PERF_MEASUREMENT GC_start_performance_measurement()
#endif

# ifdef BUFFERED_FINALIZATION
# include "gc/gc_disclaim.h"
# endif

#define GC_COND_INIT() \
INIT_FORK_SUPPORT; INIT_MANUAL_VDB_ALLOWED; INIT_PAGES_EXECUTABLE; \
GC_OPT_INIT; CHECK_GCLIB_VERSION; \
Expand Down Expand Up @@ -1670,6 +1674,31 @@ static void run_one_test(void)
NOOP1_PTR(p);
AO_fetch_and_add1(&collectable_count);
}
# ifdef BUFFERED_FINALIZATION
{
size_t i;
void *p;

GC_init();

p = GC_buffered_finalize_malloc(17);
CHECK_OUT_OF_MEMORY(p);
AO_fetch_and_add1(&collectable_count);

for (i = sizeof(GC_word); i <= HBLKSIZE * 4; i *= 2) {
p = checkOOM(GC_buffered_finalize_memalign(i, 17));
AO_fetch_and_add1(&collectable_count);
if ((GC_word)p % i != 0 || *(int *)p != 0) {
GC_printf("GC_buffered_finalize_posix_memalign(%u,17) produced incorrect result: %p\n",
(unsigned)i, p);
FAIL;
}
}
(void)GC_buffered_finalize_posix_memalign(&p, 64, 1);
CHECK_OUT_OF_MEMORY(p);
AO_fetch_and_add1(&collectable_count);
}
# endif
# ifndef GC_NO_VALLOC
{
void *p = checkOOM(GC_valloc(78));
Expand Down

0 comments on commit 49fdfc2

Please sign in to comment.