Commit 23e72d41 authored by Rusty Russell's avatar Rusty Russell

timer: add hook for allocation functions.

malloc and free aren't for everyone.
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 580457bd
#define CCAN_TIMER_DEBUG
/* Include the C files directly. */
#include <ccan/timer/timer.c>
#include <ccan/tap/tap.h>
static void *test_alloc(size_t len, void *arg)
{
(*(size_t *)arg)++;
return malloc(len);
}
static void test_free(const void *p, void *arg)
{
if (p) {
(*(size_t *)arg)--;
free((void *)p);
}
}
static struct timemono timemono_from_nsec(unsigned long long nsec)
{
struct timemono epoch = { { 0, 0 } };
return timemono_add(epoch, time_from_nsec(nsec));
}
int main(void)
{
struct timers timers;
struct timer t[64];
size_t num_allocs = 0;
const struct timemono epoch = { { 0, 0 } };
plan_tests(7);
timers_set_allocator(test_alloc, test_free, &num_allocs);
timers_init(&timers, epoch);
timer_init(&t[0]);
timer_addmono(&timers, &t[0],
timemono_from_nsec(TIMER_GRANULARITY << TIMER_LEVEL_BITS));
timers_expire(&timers, timemono_from_nsec(1));
ok1(num_allocs == 1);
timer_del(&timers, &t[0]);
ok1(num_allocs == 1);
timers_cleanup(&timers);
ok1(num_allocs == 0);
/* Should restore defaults */
timers_set_allocator(NULL, NULL, NULL);
ok1(timer_alloc == timer_default_alloc);
ok1(timer_free == timer_default_free);
timers_init(&timers, epoch);
timer_addmono(&timers, &t[0],
timemono_from_nsec(TIMER_GRANULARITY << TIMER_LEVEL_BITS));
ok1(num_allocs == 0);
timers_cleanup(&timers);
ok1(num_allocs == 0);
/* This exits depending on whether all tests passed */
return exit_status();
}
......@@ -11,6 +11,33 @@ struct timer_level {
struct list_head list[PER_LEVEL];
};
static void *timer_default_alloc(size_t len, void *arg)
{
return malloc(len);
}
static void timer_default_free(const void *p, void *arg)
{
free((void *)p);
}
static void *(*timer_alloc)(size_t, void *) = timer_default_alloc;
static void (*timer_free)(const void *, void *) = timer_default_free;
static void *timer_arg;
void timers_set_allocator(void *(*alloc)(size_t len, void *arg),
void (*free)(const void *p, void *arg),
void *arg)
{
if (!alloc)
alloc = timer_default_alloc;
if (!free)
free = timer_default_free;
timer_alloc = alloc;
timer_free = free;
timer_arg = arg;
}
static uint64_t time_to_grains(struct timemono t)
{
return t.ts.tv_sec * ((uint64_t)1000000000 / TIMER_GRANULARITY)
......@@ -139,7 +166,7 @@ static void add_level(struct timers *timers, unsigned int level)
unsigned int i;
struct list_head from_far;
l = malloc(sizeof(*l));
l = timer_alloc(sizeof(*l), timer_arg);
if (!l)
return;
......@@ -520,5 +547,5 @@ void timers_cleanup(struct timers *timers)
unsigned int l;
for (l = 0; l < ARRAY_SIZE(timers->level); l++)
free(timers->level[l]);
timer_free(timers->level[l], timer_arg);
}
......@@ -162,6 +162,19 @@ struct timer *timers_expire(struct timers *timers, struct timemono expire);
*/
struct timers *timers_check(const struct timers *t, const char *abortstr);
/**
* timers_set_allocator - set malloc/free functions.
* @alloc: allocator to use
* @free: unallocator to use (@p is NULL or a return from @alloc)
* @arg: argument to pass.
*
* This replaces the underlying malloc/free with these allocators.
* Setting either one to NULL restores the default allocators.
*/
void timers_set_allocator(void *(*alloc)(size_t len, void *arg),
void (*free)(const void *p, void *arg),
void *arg);
#ifdef CCAN_TIMER_DEBUG
#include <stdio.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment