Skip to content
Snippets Groups Projects
Commit 37723c9e authored by Craig Tiller's avatar Craig Tiller
Browse files

Fix race condition

parent 0dd81003
No related branches found
No related tags found
No related merge requests found
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "src/core/lib/support/arena.h" #include "src/core/lib/support/arena.h"
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/atm.h> #include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/useful.h> #include <grpc/support/useful.h>
#define ROUND_UP_TO_ALIGNMENT_SIZE(x) \ #define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
...@@ -74,16 +75,16 @@ void *gpr_arena_alloc(gpr_arena *arena, size_t size) { ...@@ -74,16 +75,16 @@ void *gpr_arena_alloc(gpr_arena *arena, size_t size) {
size_t start = size_t start =
(size_t)gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size); (size_t)gpr_atm_no_barrier_fetch_add(&arena->size_so_far, size);
zone *z = &arena->initial_zone; 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); zone *next_z = (zone *)gpr_atm_acq_load(&z->next_atm);
while (next_z == NULL) { if (next_z == NULL) {
size_t next_z_size = GPR_MAX(2 * start, size); 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 = gpr_zalloc(sizeof(zone) + next_z_size);
next_z->size_begin = z->size_end; next_z->size_begin = z->size_end;
next_z->size_end = z->size_end + next_z_size; 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)) { if (!gpr_atm_rel_cas(&z->next_atm, (gpr_atm)NULL, (gpr_atm)next_z)) {
gpr_free(next_z); gpr_free(next_z);
next_z = NULL; next_z = (zone*)gpr_atm_acq_load(&z->next_atm);
} }
} }
z = next_z; z = next_z;
...@@ -91,5 +92,7 @@ void *gpr_arena_alloc(gpr_arena *arena, size_t size) { ...@@ -91,5 +92,7 @@ void *gpr_arena_alloc(gpr_arena *arena, size_t size) {
if (start + size > z->size_end) { if (start + size > z->size_end) {
return gpr_arena_alloc(arena, size); 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; return ((char *)(z + 1)) + start - z->size_begin;
} }
...@@ -76,6 +76,7 @@ static void test(const char *name, size_t init_size, const size_t *allocs, ...@@ -76,6 +76,7 @@ static void test(const char *name, size_t init_size, const size_t *allocs,
memset(ps[i], 1, allocs[i]); memset(ps[i], 1, allocs[i]);
} }
gpr_arena_destroy(a); gpr_arena_destroy(a);
gpr_free(ps);
} }
#define TEST(name, init_size, ...) \ #define TEST(name, init_size, ...) \
...@@ -99,6 +100,8 @@ static void concurrent_test_body(void *arg) { ...@@ -99,6 +100,8 @@ static void concurrent_test_body(void *arg) {
} }
static void concurrent_test(void) { static void concurrent_test(void) {
gpr_log(GPR_DEBUG, "concurrent_test");
concurrent_test_args args; concurrent_test_args args;
gpr_event_init(&args.ev_start); gpr_event_init(&args.ev_start);
args.arena = gpr_arena_create(1024); args.arena = gpr_arena_create(1024);
...@@ -107,7 +110,7 @@ static void concurrent_test(void) { ...@@ -107,7 +110,7 @@ static void concurrent_test(void) {
for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
gpr_thd_options opt = gpr_thd_options_default(); 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); gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt);
} }
...@@ -116,6 +119,8 @@ static void concurrent_test(void) { ...@@ -116,6 +119,8 @@ static void concurrent_test(void) {
for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) { for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
gpr_thd_join(thds[i]); gpr_thd_join(thds[i]);
} }
gpr_arena_destroy(args.arena);
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment