Line data Source code
1 : /* Copyright 2025 Wikimedia Foundation 2 : * 3 : * Licensed under the Apache License, Version 2.0 (the "License"); 4 : * you may not use this file except in compliance with the License. 5 : * You may obtain a copy of the License at 6 : * 7 : * http://www.apache.org/licenses/LICENSE-2.0 8 : * 9 : * Unless required by applicable law or agreed to in writing, software 10 : * distributed under the License is distributed on an "AS IS" BASIS, 11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : * See the License for the specific language governing permissions and 13 : * limitations under the License. 14 : */ 15 : #ifndef TIMERLIB_TIMERLIB_H 16 : #define TIMERLIB_TIMERLIB_H 17 : 18 : #include "timerlib_config.h" 19 : 20 : /** 21 : * The function pointer type used for notifying the caller of timer events 22 : */ 23 : typedef void (timerlib_notify_function_t)(void *data, int overrun_count); 24 : 25 : #if defined(TIMERLIB_USE_POSIX) 26 : #include "timerlib_posix.h" 27 : #elif defined(TIMERLIB_USE_KQUEUE) 28 : #include "timerlib_kqueue.h" 29 : #else 30 : #error "No timer implementation available" 31 : #endif 32 : 33 : #define timerlib_abort(libfunc, error_number) timerlib_abort_func(__func__, (libfunc), (error_number)) 34 : 35 : //-------------------------------------------------------------------------------- 36 : // Timer functions 37 : //-------------------------------------------------------------------------------- 38 : 39 : /** 40 : * Initialize a new timer. 41 : * 42 : * Regardless of the return value, use timerlib_timer_destroy() to destroy 43 : * the structure. 44 : * 45 : * @param[out] timer Pointer to the timer object to be populated 46 : * @param clock May be TIMERLIB_REAL for wall-clock time, or TIMERLIB_CPU for CPU time 47 : * @param notify_function Function to be called when the timer expires 48 : * @param notify_data The first parameter sent to notify_function 49 : * @return TIMERLIB_SUCCESS if the timer was successfully initialized, TIMERLIB_FAILURE otherwise 50 : */ 51 : int timerlib_timer_init(timerlib_timer_t *timer, int clock, 52 : timerlib_notify_function_t *notify_function, void *notify_data); 53 : 54 : /** 55 : * Start a one-shot timer 56 : * 57 : * @param[in,out] timer 58 : * @param[in] duration How long before the timer expires 59 : * @return TIMERLIB_SUCCESS if the timer was successfully started, TIMERLIB_FAILURE otherwise 60 : */ 61 : int timerlib_timer_start_oneshot(timerlib_timer_t *timer, timerlib_timespec_t *duration); 62 : 63 : /** 64 : * Start a periodic timer 65 : * 66 : * @param[in,out] timer 67 : * @param[in] period The interval at which the timer should fire 68 : * @return TIMERLIB_SUCCESS if the timer was successfully started, TIMERLIB_FAILURE otherwise 69 : */ 70 : int timerlib_timer_start_periodic(timerlib_timer_t *timer, timerlib_timespec_t *period); 71 : 72 : /** 73 : * Start a generic timer 74 : * 75 : * @param[in,out] timer 76 : * @param[in] period The period at which the timer should fire, or zero for a one-shot timer 77 : * @param[in] initial The initial delay of the timer 78 : * @return TIMERLIB_SUCCESS if the timer was successfully started, TIMERLIB_FAILURE otherwise 79 : */ 80 : int timerlib_timer_start(timerlib_timer_t *timer, timerlib_timespec_t *period, timerlib_timespec_t *initial); 81 : 82 : /** 83 : * Stop a timer. 84 : * 85 : * @param[in,out] timer 86 : * @return TIMERLIB_SUCCESS if the timer was successfully stopped, TIMERLIB_FAILURE otherwise 87 : */ 88 : int timerlib_timer_stop(timerlib_timer_t *timer); 89 : 90 : /** 91 : * Clean up resources associated with a timer. 92 : * 93 : * If a timer callback is executing, wait until it returns. 94 : * 95 : * It is guaranteed that the callback will not be called again after this 96 : * function returns. 97 : * 98 : * @param[in,out] timer 99 : */ 100 : void timerlib_timer_destroy(timerlib_timer_t *timer); 101 : 102 : /** 103 : * Get the remaining time until the next scheduled expiratioh of a timer. 104 : * This is an estimate based on the last reported firing time of the timer and the configured period. 105 : * 106 : * @param[in] timer 107 : * @param[out] remaining Pointer to the timespec struct to be populated with the remaining time 108 : * @return TIMERLIB_SUCCESS or TIMERLIB_FAILURE 109 : */ 110 : int timerlib_timer_get_time(timerlib_timer_t *timer, timerlib_timespec_t *remaining); 111 : 112 : //-------------------------------------------------------------------------------- 113 : // Clock functions 114 : //-------------------------------------------------------------------------------- 115 : 116 : /** 117 : * Get the current time relative to some implementation-dependent epoch 118 : * @param clock Either TIMERLIB_REAL or TIMERLIB_CPU 119 : * @param[out] time Pointer to the timespec to be populated with the current time 120 : * @return TIMERLIB_SUCCESS or TIMERLIB_FAILURE 121 : */ 122 : int timerlib_clock_get_time(int clock, timerlib_timespec_t * time); 123 : 124 : //-------------------------------------------------------------------------------- 125 : // Timespec functions 126 : //-------------------------------------------------------------------------------- 127 : 128 : /** 129 : * A long billion 130 : */ 131 : #define TIMERLIB_BILLION_L 1000000000L 132 : 133 : /** 134 : * A long long billion 135 : */ 136 : #define TIMERLIB_BILLION_LL 1000000000LL 137 : 138 : /** 139 : * Determine if a timespec is zero 140 : * @param[in] ts 141 : * @return 1 if the seconds and nanoseconds parts are both zero, 0 otherwise 142 : */ 143 129 : static inline int timerlib_timespec_is_zero(timerlib_timespec_t *ts) 144 : { 145 129 : return ts->tv_sec == 0 && ts->tv_nsec == 0; 146 : } 147 : 148 : /** 149 : * Convert a timespec to a number of nanoseconds 150 : * 151 : * Overflow will silently wrap around after 585 years. 152 : * 153 : * @param[in] ts 154 : * @return The number of nanoseconds 155 : */ 156 69 : static inline uint64_t timerlib_timespec_to_ns(timerlib_timespec_t *ts) 157 : { 158 69 : return (uint64_t)ts->tv_nsec + (uint64_t)ts->tv_sec * TIMERLIB_BILLION_LL; 159 : } 160 : 161 : /** 162 : * Convert a timespec to a floating-point number of seconds 163 : * 164 : * Some precision will be lost if the timespec is larger than about 104 days. 165 : * 166 : * @param[in] ts 167 : * @return The number of seconds 168 : */ 169 3 : static inline double timerlib_timespec_to_double(timerlib_timespec_t *ts) 170 : { 171 3 : return timerlib_timespec_to_ns(ts) * 1e-9; 172 : } 173 : 174 : /** 175 : * Add two timespecs like a += b 176 : * 177 : * @param[in,out] a The destination and left operand 178 : * @param[in] b The right operand 179 : */ 180 : void timerlib_timespec_add(timerlib_timespec_t * a, const timerlib_timespec_t * b); 181 : 182 : /** 183 : * Subtract timespecs like a -= b 184 : * 185 : * @param[in,out] a The destination and left operand 186 : * @param[in] b The right operand 187 : */ 188 : void timerlib_timespec_subtract(timerlib_timespec_t * a, const timerlib_timespec_t * b); 189 : 190 : /** 191 : * Populate a timespec from a floating-point number of seconds 192 : * 193 : * @param[out] dest 194 : * @param[in] source 195 : */ 196 : void timerlib_timespec_from_double(timerlib_timespec_t * dest, double source); 197 : 198 : #endif