1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12#pragma once 13 14#include <stdint.h> 15#include <stdbool.h> 16#include <stdlib.h> 17#include <platsupport/io.h> 18#include <platsupport/time_manager.h> 19 20/* Multiplex absolute timeouts -> maps ids of a timeout to absolute timeouts and returns the 21 * next timeout due */ 22typedef struct { 23 /* absolute time this timeout should occur */ 24 uint64_t abs_time; 25 /* period this timeout should reoccur (0 if not periodic) */ 26 uint64_t period; 27 /* token to call callback with */ 28 uintptr_t token; 29 /* callback to call */ 30 timeout_cb_fn_t callback; 31} timeout_t; 32 33struct tqueue_node { 34 /* details of the timeout */ 35 timeout_t timeout; 36 /* is this timeout allocated? */ 37 bool allocated; 38 /* is this timeout in the callback queue? */ 39 bool active; 40 /* next ptr for queue */ 41 struct tqueue_node *next; 42}; 43typedef struct tqueue_node tqueue_node_t; 44 45typedef struct { 46 /* head of ordered list of timeouts */ 47 tqueue_node_t *queue; 48 /* id indexed array of timeouts */ 49 tqueue_node_t *array; 50 /* size of timeout array */ 51 int n; 52} tqueue_t; 53 54/* 55 * Alloc a new id for registering timeouts with tqueue_register. 56 * 57 * @param id pointer to store allocated id in. 58 * @return ENOMEM if there are no free ids, EINVAL if tq or id are NULL, 0 on success. 59 */ 60int tqueue_alloc_id(tqueue_t *tq, unsigned int *id); 61 62/* 63 * Alloc a specific id for registering timeouts with tqueue_register. 64 * 65 * @param id id to specifically allocate. Must be < size the timeout multiplexer 66 * was initialised with. 67 * @return ENOMEM if there are no free ids, 68 * EINVAL if tq is NULL or id is invalid, 69 * EADDRINUSE if id is already in use, 70 * or id are NULL, 0 on success. 71 */ 72int tqueue_alloc_id_at(tqueue_t *tq, unsigned int id); 73 74/* 75 * Free an id. This id can no longer be used to register timeouts with, and 76 * can be reallocated by tqueue_alloc_id. 77 * 78 * @param id an id allocated by tqueue_alloc_id 79 * @return EINVAL if tq is NULL or id is invalid (not allocated by tqueue_alloc_id), 0 on sucess. 80 */ 81int tqueue_free_id(tqueue_t *tq, unsigned int id); 82 83/* 84 * Register a timeout. The timeout callback will be called when tqueue_update is called and 85 * the abs_time in the timeout has passed. If the timeout has already passed, the callback will be called when 86 * tqueue_update is called. 87 * 88 * This function can be called from callbacks. 89 * 90 * @param id id to register timeout with. If the id already has a callback registered, override it. 91 * @param timeout populated details of the timeout. 92 * @return EINVAL if id or tq are invalid, 0 on success. 93 * 94 */ 95int tqueue_register(tqueue_t *tq, unsigned int id, timeout_t *timeout); 96 97/* 98 * Cancel a timeout. The id is still valid, but the callback will not be called. 99 * 100 * @param id id to cancel timeout for. 101 * @return EINVAL if id or tq are invalid, 0 on success. 102 */ 103int tqueue_cancel(tqueue_t *tq, unsigned int id); 104 105/* 106 * Call any callbacks where abs_time is >= curr_time. Return the next timeout due in next_time. Reenqueue 107 * any periodic callbacks. 108 * 109 * @param curr_time the time to check abs_time against for all timeouts. 110 * @param[out] next_time field to populate with next lowest time to be set after all callbacks called. 111 * If NULL, ignore. 112 * @return EINVAL if tq is invalid, 0 on sucess. 113 * 114 */ 115int tqueue_update(tqueue_t *tq, uint64_t curr_time, uint64_t *next_time); 116 117/* 118 * Get the smallest registered timeout. 119 * 120 * @param[out] next_time field to populate with next lowest time to be set. 121 * @return EINVAL if tq or next_time is NULL, 0 on success. 122 */ 123int tqueue_next(tqueue_t *tq, uint64_t *next_time); 124 125/* 126 * Initialise a statically sized timeout multiplexer. 127 * 128 * @param[out] tq pointer to memory to use to initialise timout mutiplexer. 129 * @param mops malloc ops to allocate timeout nodes with. Not stored for use beyond this function. 130 * @param size maximum number of ids that can be registered. 131 * @return 0 on success. 132 */ 133int tqueue_init_static(tqueue_t *tq, ps_malloc_ops_t *mops, int size); 134