diff --git a/src/core/lib/support/arena.c b/src/core/lib/support/arena.c index faceb1a1eb3..b5c32b20416 100644 --- a/src/core/lib/support/arena.c +++ b/src/core/lib/support/arena.c @@ -34,6 +34,7 @@ #include "src/core/lib/support/arena.h" #include #include +#include #include #define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ @@ -74,16 +75,16 @@ void *gpr_arena_alloc(gpr_arena *arena, size_t size) { size_t start = (size_t)gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size); zone *z = &arena->initial_zone; - while (start > z->size_begin) { + while (start > z->size_end) { zone *next_z = (zone *)gpr_atm_acq_load(&z->next_atm); - while (next_z == NULL) { - size_t next_z_size = GPR_MAX(2 * start, size); + if (next_z == NULL) { + size_t next_z_size = GPR_MAX((size_t)gpr_atm_no_barrier_load(&arena->size_so_far), size); next_z = gpr_zalloc(sizeof(zone) + next_z_size); next_z->size_begin = z->size_end; next_z->size_end = z->size_end + next_z_size; if (!gpr_atm_rel_cas(&z->next_atm, (gpr_atm)NULL, (gpr_atm)next_z)) { gpr_free(next_z); - next_z = NULL; + next_z = (zone*)gpr_atm_acq_load(&z->next_atm); } } z = next_z; @@ -91,5 +92,7 @@ void *gpr_arena_alloc(gpr_arena *arena, size_t size) { if (start + size > z->size_end) { return gpr_arena_alloc(arena, size); } + GPR_ASSERT(start >= z->size_begin); + GPR_ASSERT(start + size <= z->size_end); return ((char *)(z + 1)) + start - z->size_begin; } diff --git a/test/core/support/arena_test.c b/test/core/support/arena_test.c index 3e21867bcff..35b2bbd1b10 100644 --- a/test/core/support/arena_test.c +++ b/test/core/support/arena_test.c @@ -76,6 +76,7 @@ static void test(const char *name, size_t init_size, const size_t *allocs, memset(ps[i], 1, allocs[i]); } gpr_arena_destroy(a); + gpr_free(ps); } #define TEST(name, init_size, ...) \ @@ -99,6 +100,8 @@ static void concurrent_test_body(void *arg) { } static void concurrent_test(void) { + gpr_log(GPR_DEBUG, "concurrent_test"); + concurrent_test_args args; gpr_event_init(&args.ev_start); args.arena = gpr_arena_create(1024); @@ -107,7 +110,7 @@ static void concurrent_test(void) { for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { gpr_thd_options opt = gpr_thd_options_default(); - gpr_thd_options_is_joinable(&opt); + gpr_thd_options_set_joinable(&opt); gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt); } @@ -116,6 +119,8 @@ static void concurrent_test(void) { for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { gpr_thd_join(thds[i]); } + + gpr_arena_destroy(args.arena); } int main(int argc, char *argv[]) {