/** Helper: allocate a new memarea chunk of around <b>chunk_size</b> bytes. */ static memarea_chunk_t * alloc_chunk(size_t sz, int freelist_ok) { tor_assert(sz < SIZE_T_CEILING); if (freelist && freelist_ok) { memarea_chunk_t *res = freelist; freelist = res->next_chunk; res->next_chunk = NULL; --freelist_len; CHECK_SENTINEL(res); return res; } else { size_t chunk_size = freelist_ok ? CHUNK_SIZE : sz; memarea_chunk_t *res; chunk_size += SENTINEL_LEN; res = tor_malloc(chunk_size); res->next_chunk = NULL; res->mem_size = chunk_size - CHUNK_HEADER_SIZE - SENTINEL_LEN; res->next_mem = res->U_MEM; tor_assert(res->next_mem+res->mem_size+SENTINEL_LEN == ((char*)res)+chunk_size); tor_assert(realign_pointer(res->next_mem) == res->next_mem); SET_SENTINEL(res); return res; } }
/** Return a pointer to a chunk of memory in <b>area</b> of at least <b>sz</b> * bytes. <b>sz</b> should be significantly smaller than the area's chunk * size, though we can deal if it isn't. */ void * memarea_alloc(memarea_t *area, size_t sz) { memarea_chunk_t *chunk = area->first; char *result; tor_assert(chunk); if (sz == 0) sz = 1; if (chunk->next_mem+sz > chunk->u.mem+chunk->mem_size) { if (sz+CHUNK_HEADER_SIZE >= CHUNK_SIZE) { /* This allocation is too big. Stick it in a special chunk, and put * that chunk second in the list. */ memarea_chunk_t *new_chunk = alloc_chunk(sz+CHUNK_HEADER_SIZE, 0); new_chunk->next_chunk = chunk->next_chunk; chunk->next_chunk = new_chunk; chunk = new_chunk; } else { memarea_chunk_t *new_chunk = alloc_chunk(CHUNK_SIZE, 1); new_chunk->next_chunk = chunk; area->first = chunk = new_chunk; } tor_assert(chunk->mem_size >= sz); } result = chunk->next_mem; chunk->next_mem = chunk->next_mem + sz; // XXXX021 remove these once bug 930 is solved. tor_assert(chunk->next_mem >= chunk->u.mem); tor_assert(chunk->next_mem <= chunk->u.mem+chunk->mem_size); chunk->next_mem = realign_pointer(chunk->next_mem); return result; }
/** Assert that <b>area</b> is okay. */ void memarea_assert_ok(memarea_t *area) { memarea_chunk_t *chunk; tor_assert(area->first); for (chunk = area->first; chunk; chunk = chunk->next_chunk) { tor_assert(chunk->next_mem >= chunk->u.mem); tor_assert(chunk->next_mem <= (char*) realign_pointer(chunk->u.mem+chunk->mem_size)); } }
/** Assert that <b>area</b> is okay. */ void memarea_assert_ok(memarea_t *area) { memarea_chunk_t *chunk; tor_assert(area->first); for (chunk = area->first; chunk; chunk = chunk->next_chunk) { CHECK_SENTINEL(chunk); tor_assert(chunk->next_mem >= chunk->U_MEM); tor_assert(chunk->next_mem <= (char*) realign_pointer(chunk->U_MEM+chunk->mem_size)); } }
/** Helper: allocate a new memarea chunk of around <b>chunk_size</b> bytes. */ static memarea_chunk_t * alloc_chunk(size_t sz) { tor_assert(sz < SIZE_T_CEILING); size_t chunk_size = sz < CHUNK_SIZE ? CHUNK_SIZE : sz; memarea_chunk_t *res; chunk_size += SENTINEL_LEN; res = tor_malloc(chunk_size); res->next_chunk = NULL; res->mem_size = chunk_size - CHUNK_HEADER_SIZE - SENTINEL_LEN; res->next_mem = res->U_MEM; tor_assert(res->next_mem+res->mem_size+SENTINEL_LEN == ((char*)res)+chunk_size); tor_assert(realign_pointer(res->next_mem) == res->next_mem); SET_SENTINEL(res); return res; }
/** Helper: allocate a new memarea chunk of around <b>chunk_size</b> bytes. */ static memarea_chunk_t * alloc_chunk(size_t sz, int freelist_ok) { if (freelist && freelist_ok) { memarea_chunk_t *res = freelist; freelist = res->next_chunk; res->next_chunk = NULL; --freelist_len; return res; } else { size_t chunk_size = freelist_ok ? CHUNK_SIZE : sz; memarea_chunk_t *res = tor_malloc_roundup(&chunk_size); res->next_chunk = NULL; res->mem_size = chunk_size - CHUNK_HEADER_SIZE; res->next_mem = res->u.mem; tor_assert(res->next_mem+res->mem_size == ((char*)res)+chunk_size); tor_assert(realign_pointer(res->next_mem) == res->next_mem); return res; } }
/** Return a pointer to a chunk of memory in <b>area</b> of at least <b>sz</b> * bytes. <b>sz</b> should be significantly smaller than the area's chunk * size, though we can deal if it isn't. */ void * memarea_alloc(memarea_t *area, size_t sz) { memarea_chunk_t *chunk = area->first; char *result; tor_assert(chunk); CHECK_SENTINEL(chunk); tor_assert(sz < SIZE_T_CEILING); if (sz == 0) sz = 1; if (chunk->next_mem+sz > chunk->U_MEM+chunk->mem_size) { if (sz+CHUNK_HEADER_SIZE >= CHUNK_SIZE) { /* This allocation is too big. Stick it in a special chunk, and put * that chunk second in the list. */ memarea_chunk_t *new_chunk = alloc_chunk(sz+CHUNK_HEADER_SIZE, 0); new_chunk->next_chunk = chunk->next_chunk; chunk->next_chunk = new_chunk; chunk = new_chunk; } else { memarea_chunk_t *new_chunk = alloc_chunk(CHUNK_SIZE, 1); new_chunk->next_chunk = chunk; area->first = chunk = new_chunk; } tor_assert(chunk->mem_size >= sz); } result = chunk->next_mem; chunk->next_mem = chunk->next_mem + sz; /* Reinstate these if bug 930 ever comes back tor_assert(chunk->next_mem >= chunk->U_MEM); tor_assert(chunk->next_mem <= chunk->U_MEM+chunk->mem_size); */ chunk->next_mem = realign_pointer(chunk->next_mem); return result; }