|  | @@ -17,11 +17,19 @@
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "src/core/lib/gpr/arena.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <string.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  #include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/atm.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/log.h>
 | 
	
		
			
				|  |  |  #include <grpc/support/useful.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// TODO(roth): We currently assume that all callers need alignment of 16
 | 
	
		
			
				|  |  | +// bytes, which may be wrong in some cases.  As part of converting the
 | 
	
		
			
				|  |  | +// arena API to C++, we should consider replacing gpr_arena_alloc() with a
 | 
	
		
			
				|  |  | +// template that takes the type of the value being allocated, which
 | 
	
		
			
				|  |  | +// would allow us to use the alignment actually needed by the caller.
 | 
	
		
			
				|  |  |  #define ROUND_UP_TO_ALIGNMENT_SIZE(x) \
 | 
	
		
			
				|  |  |    (((x) + GPR_MAX_ALIGNMENT - 1u) & ~(GPR_MAX_ALIGNMENT - 1u))
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -36,9 +44,16 @@ struct gpr_arena {
 | 
	
		
			
				|  |  |    zone initial_zone;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static void* zalloc_aligned(size_t size) {
 | 
	
		
			
				|  |  | +  void* ptr = gpr_malloc_aligned(size, GPR_MAX_ALIGNMENT);
 | 
	
		
			
				|  |  | +  memset(ptr, 0, size);
 | 
	
		
			
				|  |  | +  return ptr;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  gpr_arena* gpr_arena_create(size_t initial_size) {
 | 
	
		
			
				|  |  |    initial_size = ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
 | 
	
		
			
				|  |  | -  gpr_arena* a = (gpr_arena*)gpr_zalloc(sizeof(gpr_arena) + initial_size);
 | 
	
		
			
				|  |  | +  gpr_arena* a = (gpr_arena*)zalloc_aligned(
 | 
	
		
			
				|  |  | +      ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size);
 | 
	
		
			
				|  |  |    a->initial_zone.size_end = initial_size;
 | 
	
		
			
				|  |  |    return a;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -46,10 +61,10 @@ gpr_arena* gpr_arena_create(size_t initial_size) {
 | 
	
		
			
				|  |  |  size_t gpr_arena_destroy(gpr_arena* arena) {
 | 
	
		
			
				|  |  |    gpr_atm size = gpr_atm_no_barrier_load(&arena->size_so_far);
 | 
	
		
			
				|  |  |    zone* z = (zone*)gpr_atm_no_barrier_load(&arena->initial_zone.next_atm);
 | 
	
		
			
				|  |  | -  gpr_free(arena);
 | 
	
		
			
				|  |  | +  gpr_free_aligned(arena);
 | 
	
		
			
				|  |  |    while (z) {
 | 
	
		
			
				|  |  |      zone* next_z = (zone*)gpr_atm_no_barrier_load(&z->next_atm);
 | 
	
		
			
				|  |  | -    gpr_free(z);
 | 
	
		
			
				|  |  | +    gpr_free_aligned(z);
 | 
	
		
			
				|  |  |      z = next_z;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    return (size_t)size;
 | 
	
	
		
			
				|  | @@ -64,11 +79,12 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
 | 
	
		
			
				|  |  |      zone* next_z = (zone*)gpr_atm_acq_load(&z->next_atm);
 | 
	
		
			
				|  |  |      if (next_z == nullptr) {
 | 
	
		
			
				|  |  |        size_t next_z_size = (size_t)gpr_atm_no_barrier_load(&arena->size_so_far);
 | 
	
		
			
				|  |  | -      next_z = (zone*)gpr_zalloc(sizeof(zone) + next_z_size);
 | 
	
		
			
				|  |  | +      next_z = (zone*)zalloc_aligned(ROUND_UP_TO_ALIGNMENT_SIZE(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);
 | 
	
		
			
				|  |  | +        gpr_free_aligned(next_z);
 | 
	
		
			
				|  |  |          next_z = (zone*)gpr_atm_acq_load(&z->next_atm);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -79,5 +95,8 @@ void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    GPR_ASSERT(start >= z->size_begin);
 | 
	
		
			
				|  |  |    GPR_ASSERT(start + size <= z->size_end);
 | 
	
		
			
				|  |  | -  return ((char*)(z + 1)) + start - z->size_begin;
 | 
	
		
			
				|  |  | +  char* ptr = (z == &arena->initial_zone)
 | 
	
		
			
				|  |  | +                  ? (char*)arena + ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena))
 | 
	
		
			
				|  |  | +                  : (char*)z + ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
 | 
	
		
			
				|  |  | +  return ptr + start - z->size_begin;
 | 
	
		
			
				|  |  |  }
 |