No malloc for default alarm pool an pheap docs/cleanup (#143)
* Statically allocate the default timer pool (to avoid pulling in malloc); doxygen for pheap (and some function name changes) * fix comments
This commit is contained in:
committed by
graham sanderson
parent
0a22f704a6
commit
e730e03e7f
@ -33,26 +33,25 @@ typedef struct alarm_pool {
|
||||
} alarm_pool_t;
|
||||
|
||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||
static alarm_pool_t *default_alarm_pool;
|
||||
// To avoid bringing in calloc, we statically allocate the arrays and the heap
|
||||
PHEAP_DEFINE_STATIC(default_alarm_pool_heap, PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
|
||||
static alarm_pool_entry_t default_alarm_pool_entries[PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS];
|
||||
static uint8_t default_alarm_pool_entry_ids_high[PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS];
|
||||
|
||||
static alarm_pool_t default_alarm_pool = {
|
||||
.heap = &default_alarm_pool_heap,
|
||||
.entries = default_alarm_pool_entries,
|
||||
.entry_ids_high = default_alarm_pool_entry_ids_high,
|
||||
};
|
||||
|
||||
static inline bool default_alarm_pool_initialized(void) {
|
||||
return default_alarm_pool.lock != NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static alarm_pool_t *pools[NUM_TIMERS];
|
||||
static void alarm_pool_post_alloc_init(alarm_pool_t *pool, uint hardware_alarm_num);
|
||||
|
||||
void alarm_pool_init_default() {
|
||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||
// allow multiple calls for ease of use from host tests
|
||||
if (!default_alarm_pool) {
|
||||
default_alarm_pool = alarm_pool_create(PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM,
|
||||
PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||
alarm_pool_t *alarm_pool_get_default() {
|
||||
assert(default_alarm_pool);
|
||||
return default_alarm_pool;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline alarm_pool_entry_t *get_entry(alarm_pool_t *pool, pheap_node_id_t id) {
|
||||
assert(id && id <= pool->heap->max_nodes);
|
||||
@ -73,11 +72,30 @@ static inline alarm_id_t make_public_id(uint8_t id_high, pheap_node_id_t id) {
|
||||
return (alarm_id_t)(((uint)id_high << 8u * sizeof(id)) | id);
|
||||
}
|
||||
|
||||
void alarm_pool_init_default() {
|
||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||
// allow multiple calls for ease of use from host tests
|
||||
if (!default_alarm_pool_initialized()) {
|
||||
ph_post_alloc_init(default_alarm_pool.heap, PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS,
|
||||
timer_pool_entry_comparator, &default_alarm_pool);
|
||||
alarm_pool_post_alloc_init(&default_alarm_pool,
|
||||
PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||
alarm_pool_t *alarm_pool_get_default() {
|
||||
assert(default_alarm_pool_initialized());
|
||||
return &default_alarm_pool;
|
||||
}
|
||||
#endif
|
||||
|
||||
static pheap_node_id_t add_alarm_under_lock(alarm_pool_t *pool, absolute_time_t time, alarm_callback_t callback,
|
||||
void *user_data, pheap_node_id_t reuse_id, bool create_if_past, bool *missed) {
|
||||
pheap_node_id_t id;
|
||||
if (reuse_id) {
|
||||
assert(!ph_contains(pool->heap, reuse_id));
|
||||
assert(!ph_contains_node(pool->heap, reuse_id));
|
||||
id = reuse_id;
|
||||
} else {
|
||||
id = ph_new_node(pool->heap);
|
||||
@ -87,10 +105,10 @@ static pheap_node_id_t add_alarm_under_lock(alarm_pool_t *pool, absolute_time_t
|
||||
entry->target = time;
|
||||
entry->callback = callback;
|
||||
entry->user_data = user_data;
|
||||
if (id == ph_insert(pool->heap, id)) {
|
||||
if (id == ph_insert_node(pool->heap, id)) {
|
||||
bool is_missed = hardware_alarm_set_target(pool->hardware_alarm_num, time);
|
||||
if (is_missed && !create_if_past) {
|
||||
ph_delete(pool->heap, id);
|
||||
ph_remove_and_free_node(pool->heap, id);
|
||||
}
|
||||
if (missed) *missed = is_missed;
|
||||
}
|
||||
@ -114,8 +132,8 @@ static void alarm_pool_alarm_callback(uint alarm_num) {
|
||||
if (next_id) {
|
||||
alarm_pool_entry_t *entry = get_entry(pool, next_id);
|
||||
if (absolute_time_diff_us(now, entry->target) <= 0) {
|
||||
// we reserve the id in case we need to re-add the timer
|
||||
pheap_node_id_t __unused removed_id = ph_remove_head_reserve(pool->heap, true);
|
||||
// we don't free the id in case we need to re-add the timer
|
||||
pheap_node_id_t __unused removed_id = ph_remove_head(pool->heap, false);
|
||||
assert(removed_id == next_id); // will be true under lock
|
||||
target = entry->target;
|
||||
callback = entry->callback;
|
||||
@ -143,7 +161,7 @@ static void alarm_pool_alarm_callback(uint alarm_num) {
|
||||
true, NULL);
|
||||
} else {
|
||||
// need to return the id to the heap
|
||||
ph_add_to_free_list(pool->heap, next_id);
|
||||
ph_free_node(pool->heap, next_id);
|
||||
(*get_entry_id_high(pool, next_id))++; // we bump it for next use of id
|
||||
}
|
||||
pool->alarm_in_progress = 0;
|
||||
@ -155,20 +173,30 @@ static void alarm_pool_alarm_callback(uint alarm_num) {
|
||||
|
||||
// note the timer is create with IRQs on this core
|
||||
alarm_pool_t *alarm_pool_create(uint hardware_alarm_num, uint max_timers) {
|
||||
hardware_alarm_claim(hardware_alarm_num);
|
||||
hardware_alarm_cancel(hardware_alarm_num);
|
||||
hardware_alarm_set_callback(hardware_alarm_num, alarm_pool_alarm_callback);
|
||||
alarm_pool_t *pool = (alarm_pool_t *)malloc(sizeof(alarm_pool_t));
|
||||
pool->lock = spin_lock_instance(next_striped_spin_lock_num());
|
||||
alarm_pool_t *pool = (alarm_pool_t *) malloc(sizeof(alarm_pool_t));
|
||||
pool->heap = ph_create(max_timers, timer_pool_entry_comparator, pool);
|
||||
pool->entries = (alarm_pool_entry_t *)calloc(max_timers, sizeof(alarm_pool_entry_t));
|
||||
pool->entry_ids_high = (uint8_t *)calloc(max_timers, sizeof(uint8_t));
|
||||
pool->hardware_alarm_num = (uint8_t)hardware_alarm_num;
|
||||
pools[hardware_alarm_num] = pool;
|
||||
alarm_pool_post_alloc_init(pool, hardware_alarm_num);
|
||||
return pool;
|
||||
}
|
||||
|
||||
void alarm_pool_post_alloc_init(alarm_pool_t *pool, uint hardware_alarm_num) {
|
||||
hardware_alarm_claim(hardware_alarm_num);
|
||||
hardware_alarm_cancel(hardware_alarm_num);
|
||||
hardware_alarm_set_callback(hardware_alarm_num, alarm_pool_alarm_callback);
|
||||
pool->lock = spin_lock_instance(next_striped_spin_lock_num());
|
||||
pool->hardware_alarm_num = (uint8_t) hardware_alarm_num;
|
||||
pools[hardware_alarm_num] = pool;
|
||||
}
|
||||
|
||||
void alarm_pool_destroy(alarm_pool_t *pool) {
|
||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||
if (pool == &default_alarm_pool) {
|
||||
assert(false); // attempt to delete default alarm pool
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
assert(pools[pool->hardware_alarm_num] == pool);
|
||||
pools[pool->hardware_alarm_num] = NULL;
|
||||
// todo clear out timers
|
||||
@ -219,12 +247,12 @@ bool alarm_pool_cancel_alarm(alarm_pool_t *pool, alarm_id_t alarm_id) {
|
||||
bool rc = false;
|
||||
uint32_t save = spin_lock_blocking(pool->lock);
|
||||
pheap_node_id_t id = (pheap_node_id_t) alarm_id;
|
||||
if (ph_contains(pool->heap, id)) {
|
||||
if (ph_contains_node(pool->heap, id)) {
|
||||
assert(alarm_id != pool->alarm_in_progress); // it shouldn't be in the heap if it is in progress
|
||||
// check we have the right high value
|
||||
uint8_t id_high = (uint8_t)((uint)alarm_id >> 8u * sizeof(pheap_node_id_t));
|
||||
if (id_high == *get_entry_id_high(pool, id)) {
|
||||
rc = ph_delete(pool->heap, id);
|
||||
rc = ph_remove_and_free_node(pool->heap, id);
|
||||
// note we don't bother to remove the actual hardware alarm timeout...
|
||||
// it will either do callbacks or not depending on other alarms, and reset the next timeout itself
|
||||
assert(rc);
|
||||
|
Reference in New Issue
Block a user