39 ast_string_field_allocation allocation;
41 } __ast_string_field_empty_buffer;
43 ast_string_field __ast_string_field_empty = __ast_string_field_empty_buffer.string;
45 #define ALLOCATOR_OVERHEAD 48
47 static size_t optimal_alloc_size(
size_t size)
51 size += ALLOCATOR_OVERHEAD;
53 for (count = 1; size; size >>= 1, count++);
55 return (1 << count) - ALLOCATOR_OVERHEAD;
63 size_t size,
const char *file,
int lineno,
const char *func)
66 size_t alloc_size = optimal_alloc_size(
sizeof(*pool) + size);
68 pool = __ast_calloc(1, alloc_size, file, lineno, func);
73 pool->
prev = *pool_head;
74 pool->
size = alloc_size -
sizeof(*pool);
81 static void reset_field(
const char **p)
83 *p = __ast_string_field_empty;
105 const char *file,
int lineno,
const char *func)
113 switch (cleanup_type) {
128 if (*pool_head == NULL) {
129 ast_log(LOG_WARNING,
"trying to reset empty pool\n");
132 preserve = *pool_head;
144 if (cur != preserve) {
150 *pool_head = preserve;
152 preserve->
prev = NULL;
172 int needed,
const char *file,
int lineno,
const char *func)
174 const char **p = (
const char **) pool_head + 1;
175 size_t initial_vector_size = ((size_t) (((
char *)mgr) - ((
char *)p))) /
sizeof(*p);
189 *p++ = __ast_string_field_empty;
204 const char *file,
int lineno,
const char *func)
207 size_t space = (*pool_head)->size - (*pool_head)->used;
212 ast_assert(to_alloc %
ast_alignof(ast_string_field_allocation) == 0);
214 if (__builtin_expect(to_alloc > space, 0)) {
215 size_t new_size = (*pool_head)->size;
217 while (new_size < to_alloc) {
230 result = (*pool_head)->base + (*pool_head)->used;
231 (*pool_head)->used += to_alloc;
232 (*pool_head)->active += needed;
233 result +=
ast_alignof(ast_string_field_allocation);
244 size_t space = (*pool_head)->size - (*pool_head)->used;
254 (*pool_head)->used += grow;
255 (*pool_head)->active += grow;
262 const ast_string_field ptr)
266 if (ptr == __ast_string_field_empty) {
270 for (pool = pool_head, prev = NULL;
pool; prev =
pool, pool = pool->
prev) {
271 if ((ptr >= pool->base) && (ptr <= (pool->base + pool->size))) {
273 if (pool->active == 0) {
288 const char *format, va_list ap,
289 const char *file,
int lineno,
const char *func)
293 size_t space = (*pool_head)->size - (*pool_head)->used;
303 if (*ptr != __ast_string_field_empty) {
304 target = (
char *) *ptr;
313 target = (*pool_head)->base + (*pool_head)->used +
ast_alignof(ast_string_field_allocation);
314 if (space >
ast_alignof(ast_string_field_allocation)) {
315 available = space -
ast_alignof(ast_string_field_allocation);
322 res = vsnprintf(target, available, format, ap2);
330 __ast_string_field_release_active(*pool_head, *ptr);
331 *ptr = __ast_string_field_empty;
334 needed = (size_t)res + 1;
336 if (needed > available) {
341 target = (
char *) __ast_string_field_alloc_space(mgr, pool_head, needed, file, lineno, func);
345 vsprintf(target, format, ap);
347 __ast_string_field_release_active(*pool_head, *ptr);
349 }
else if (*ptr != target) {
353 __ast_string_field_release_active(*pool_head, *ptr);
355 ast_assert(needed < (ast_string_field_allocation)-1);
358 (*pool_head)->active += needed;
364 (*pool_head)->used +=
ast_align_for(grow, ast_string_field_allocation);
365 (*pool_head)->active += grow;
369 void __ast_string_field_ptr_build(
const char *file,
int lineno,
const char *func,
375 va_start(ap, format);
376 __ast_string_field_ptr_build_va(mgr, pool_head, ptr, format, ap, file, lineno, func);
380 void *__ast_calloc_with_stringfields(
unsigned int num_structs,
size_t struct_size,
381 size_t field_mgr_offset,
size_t field_mgr_pool_offset,
size_t pool_size,
382 const char *file,
int lineno,
const char *func)
387 size_t pool_size_needed =
sizeof(*pool) + pool_size;
388 size_t size_to_alloc = optimal_alloc_size(struct_size + pool_size_needed);
391 size_t initial_vector_size;
393 ast_assert(num_structs == 1);
395 allocation = __ast_calloc(num_structs, size_to_alloc, file, lineno, func);
400 mgr = allocation + field_mgr_offset;
402 pool = allocation + struct_size;
403 pool_head = allocation + field_mgr_pool_offset;
404 p = (
const char **) pool_head + 1;
405 initial_vector_size = ((size_t) (((
char *)mgr) - ((
char *)p))) /
sizeof(*p);
408 ast_free(allocation);
414 *p++ = __ast_string_field_empty;
419 pool->
size = size_to_alloc - struct_size -
sizeof(*pool);
443 const char *file,
int lineno,
const char *func)
452 __ast_string_field_release_active(copy_pool, *
AST_VECTOR_GET(dest, i));
457 if (__ast_string_field_ptr_set_by_fields(copy_pool, *copy_mgr,
AST_VECTOR_GET(dest, i),
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alignof(type)
Return the number of bytes used in the alignment of type.
struct ast_string_field_pool * embedded_pool
static pj_pool_t * pool
Global memory pool for configuration and timers.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
int __ast_string_field_free_memory(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, enum ast_stringfield_cleanup_type cleanup_type, const char *file, int lineno, const char *func)
Internal cleanup function.
struct ast_string_field_vector string_fields
static int add_string_pool(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, size_t size, const char *file, int lineno, const char *func)
add a new block to the pool. We can only allocate from the topmost pool, so the fields in *mgr reflec...
#define AST_STRING_FIELD_ALLOCATION(x)
Macro to provide access to the allocation field that lives immediately in front of a string field...
#define ast_make_room_for(offset, type)
Increase offset by the required alignment of type and make sure it is a multiple of said alignment...
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
int __ast_string_field_init(struct ast_string_field_mgr *mgr, struct ast_string_field_pool **pool_head, int needed, const char *file, int lineno, const char *func)
Internal initialization function.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
ast_stringfield_cleanup_type
struct ast_string_field_pool * prev
#define ast_align_for(offset, type)
Increase offset so it is a multiple of the required alignment of type.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
ast_string_field last_alloc
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.