24RCSID(
"$Id: cecafa57af391478aa6aaabed4e9b5ed94b7aab9 $")
26#include <freeradius-devel/util/atexit.h>
27#include <freeradius-devel/util/debug.h>
28#include <freeradius-devel/util/dlist.h>
29#include <freeradius-devel/util/syserror.h>
54 tmp = talloc(NULL,
bool);
55 null_ctx = talloc_parent(tmp);
67 talloc_set_destructor(d->
ds, NULL);
79 talloc_set_destructor(ds->
d, NULL);
115 memcpy(&d->
uctx, &uctx,
sizeof(d->
uctx));
141 talloc_set_destructor(d->
ds, NULL);
145 talloc_set_destructor(d, NULL);
203 rounded =
ROUND_UP(size, alignment);
204 if (rounded == 0) rounded = alignment;
206 array_size = rounded + alignment;
207 array = talloc_array(ctx,
uint8_t, array_size);
213 next = (
void *)
ROUND_UP((uintptr_t)array, alignment);
233 pool = talloc_pool(NULL, 1024);
239 chunk = talloc_size(pool, 1);
240 if (
unlikely(chunk == NULL))
goto oom;
246 if (!
fr_cond_assert((chunk > pool) && ((uintptr_t)chunk < ((uintptr_t)pool + 1024)))) {
260 t_hdr_size = (uintptr_t)chunk - (uintptr_t)pool;
273 static pthread_once_t once_control = PTHREAD_ONCE_INIT;
310 size_t rounded, alloced, page_size = (
size_t)getpagesize();
316 if (hdr_size < 0)
return NULL;
318 size += (hdr_size * headers);
328 if (size % page_size == 0) {
331 rounded =
ROUND_UP(size, page_size);
340 alloced = rounded + page_size;
341 pool = talloc_pool(ctx, alloced);
353 if ((uintptr_t)pool % page_size != 0) {
357 next = (
void *)
ROUND_UP((uintptr_t)pool, page_size);
363 pad_size = ((uintptr_t)next - (uintptr_t)pool);
364 if (pad_size > (
size_t) hdr_size) {
365 pad_size -= hdr_size;
370 padding = talloc_size(pool, pad_size);
371 if (!
fr_cond_assert(((uintptr_t)padding + (uintptr_t)pad_size) >= (uintptr_t)next)) {
385 fr_assert(((uintptr_t)*start % page_size) == 0);
392 fr_assert(((uintptr_t)*end_len % page_size) == 0);
402 fr_assert(((uintptr_t)*start + *end_len) <= ((uintptr_t)pool + alloced));
420 size_t old_size = talloc_get_size(ptr);
423 void *
new = _talloc_realloc_array(ctx, ptr, elem_size,
count,
name);
424 if (!
new)
return NULL;
426 new_size = talloc_array_length((
uint8_t *)
new);
427 if (new_size > old_size) {
428 memset((
uint8_t *)
new + old_size, 0, new_size - old_size);
477 talloc_set_type(
n,
char);
501 talloc_set_type(
n,
char);
528 talloc_set_type(
n,
char);
551 n = talloc_vasprintf(ctx,
fmt, ap);
554 talloc_set_type(
n,
char);
576 n = talloc_vasprintf(ctx,
fmt, ap);
578 talloc_set_type(
n,
char);
592 size_t inlen = talloc_array_length(
in);
596 p = talloc_array(ctx,
char,
inlen);
621 p = talloc_array(ctx,
char,
inlen + 1);
651 to_len = talloc_array_length(to);
652 if (to[to_len - 1] ==
'\0') to_len--;
655 n = talloc_realloc_size(ctx, to, to_len + from_len + 1);
657 fr_strerror_printf(
"Extending bstr buffer to %zu bytes failed", to_len + from_len + 1);
661 memcpy(
n + to_len, from, from_len);
662 n[to_len + from_len] =
'\0';
663 talloc_set_type(
n,
char);
686 n = talloc_array(ctx,
char,
inlen + 1);
692 n = talloc_realloc_size(ctx,
in,
inlen + 1);
696 talloc_set_type(
n,
char);
719 va_list ap_val, ap_len;
722 size_t to_len, total_len = 0;
725 if (!to)
return NULL;
728 va_copy(ap_len, ap_val);
735 for (i = 0; i < argc; i++) {
738 arg = va_arg(ap_len,
char *);
747 if (total_len == to_len) {
753 out = talloc_realloc(ctx, to,
char, total_len + 1);
754 if (!
out)
goto finish;
761 for (i = 0; i < argc; i++) {
765 arg = va_arg(ap_val,
char *);
797 a_len = talloc_array_length(a);
798 b_len = talloc_array_length(b);
800 if (a_len > b_len)
return +1;
801 if (a_len < b_len)
return -1;
803 return memcmp(a, b, a_len);
824 memcpy(&to_free, &ptr,
sizeof(to_free));
826 ref_count = talloc_reference_count(to_free);
827 if (ref_count == 0) {
830 talloc_unlink(talloc_parent(ptr), to_free);
831 if (talloc_reference_count(to_free) == 0)
talloc_free(to_free);
857 if (!array)
return NULL;
859 len = talloc_array_length(array);
860 ctx = talloc_parent(array);
861 size = talloc_get_size(array) / talloc_array_length(array);
863 new = _talloc_realloc_array(ctx, array, size, len + 1, talloc_get_name(array));
864 if (!
new)
return NULL;
876 talloc_set_destructor(af, NULL);
static int const char * fmt
unsigned int fr_atexit_global_disarm(bool uctx_scope, fr_atexit_t func, void const *uctx)
Remove a specific global destructor (without executing it)
#define fr_atexit_thread_local_disarm(...)
#define fr_atexit_global(_func, _uctx)
Add a free function to the global free list.
#define fr_atexit_thread_local(_name, _free, _uctx)
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
void ** talloc_array_null_terminate(void **array)
Add a NULL pointer to an array of pointers.
static int _talloc_destructor_fire(fr_talloc_destructor_t *d)
Called with the fire_ctx is freed.
char * talloc_bstrdup(TALLOC_CTX *ctx, char const *in)
Binary safe strdup function.
static int _talloc_link_ctx_free(UNUSED void *parent, void *child)
static TALLOC_CTX * global_ctx
static int _autofree_on_exit(void *af)
Callback to free the autofree ctx on global exit.
char * talloc_typed_vasprintf(TALLOC_CTX *ctx, char const *fmt, va_list ap)
Call talloc vasprintf, setting the type on the new chunk correctly.
fr_talloc_destructor_t * talloc_destructor_add(TALLOC_CTX *fire_ctx, TALLOC_CTX *disarm_ctx, fr_talloc_free_func_t func, void const *uctx)
Add an additional destructor to a talloc chunk.
char * talloc_typed_strdup_buffer(TALLOC_CTX *ctx, char const *p)
Call talloc_strndup, setting the type on the new chunk correctly.
ssize_t talloc_hdr_size(void)
Calculate the size of the talloc chunk header.
TALLOC_CTX * talloc_autofree_context_global(void)
static int _autofree_thread_local_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
char * talloc_buffer_append_variadic_buffer(TALLOC_CTX *ctx, char *to, int argc,...)
Concatenate to + ...
void * _talloc_realloc_zero(const void *ctx, void *ptr, size_t elem_size, unsigned count, const char *name)
Version of talloc_realloc which zeroes out freshly allocated memory.
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
TALLOC_CTX * talloc_aligned_array(TALLOC_CTX *ctx, void **start, size_t alignment, size_t size)
Return a page aligned talloc memory array.
static int _talloc_destructor_disarm(fr_talloc_destructor_disarm_t *ds)
Called when the disarm_ctx ctx is freed.
int talloc_link_ctx(TALLOC_CTX *parent, TALLOC_CTX *child)
Link two different parent and child contexts, so the child is freed before the parent.
static void _talloc_hdr_size(void)
Calculate the size of talloc chunk headers, once, on startup.
uint8_t * talloc_typed_memdup(TALLOC_CTX *ctx, uint8_t const *in, size_t inlen)
Call talloc_memdup, setting the type on the new chunk correctly.
static _Thread_local TALLOC_CTX * thread_local_ctx
char * talloc_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
static size_t t_hdr_size
How big the chunk header is.
void * talloc_null_ctx(void)
Retrieve the current talloc NULL ctx.
TALLOC_CTX * talloc_page_aligned_pool(TALLOC_CTX *ctx, void **start, size_t *end_len, unsigned int headers, size_t size)
Return a page aligned talloc memory pool.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
void talloc_free_data(void *data)
A wrapper that can be passed to tree or hash alloc functions that take a fr_free_t.
int talloc_decrease_ref_count(void const *ptr)
Decrease the reference count on a ptr.
char * talloc_typed_strndup(TALLOC_CTX *ctx, char const *p, size_t len)
Call talloc_strndup, setting the type on the new chunk correctly.
TALLOC_CTX * talloc_autofree_context_thread_local(void)
Get a thread-safe autofreed ctx that will be freed when the thread or process exits.
char * talloc_bstr_append(TALLOC_CTX *ctx, char *to, char const *from, size_t from_len)
Append a bstr to a bstr.
void talloc_destructor_disarm(fr_talloc_destructor_t *d)
Disarm a destructor and free all memory allocated in the trigger ctxs.
int talloc_memcmp_bstr(char const *a, char const *b)
Compares two talloced char arrays with memcmp.
static int _autofree_global_destructor(TALLOC_CTX *af)
Ensures in the autofree ctx is manually freed, things don't explode atexit.
#define talloc_strndup(_ctx, _str, _len)
fr_talloc_free_func_t func
Free function.
static TALLOC_CTX * talloc_init_const(char const *name)
Allocate a top level chunk with a constant name.
fr_talloc_destructor_t * d
Destructor to disarm.
void * uctx
uctx to pass to free function.
int(* fr_talloc_free_func_t)(void *fire_ctx, void *uctx)
fr_talloc_destructor_disarm_t * ds
Chunk to free.
#define talloc_strdup(_ctx, _str)
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
Structure to record a destructor to disarm if a child talloc chunk is freed.
Structure to record a destructor operation on a specific talloc chunk.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out