A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 97 lines 2.5 kB view raw
1 2/**************************************************************************** 3 * Tick-based interval timers/one-shots - be mindful this is not really 4 * intended for continuous timers but for events that need to run for a short 5 * time and be cancelled without further software intervention. 6 ****************************************************************************/ 7 8#include "config.h" 9#include "system.h" /* TIME_AFTER */ 10#include "kernel.h" 11#include "timeout.h" 12#include "general.h" 13 14/* list of active timeout events */ 15static struct timeout *tmo_list[MAX_NUM_TIMEOUTS+1]; 16 17/* timeout tick task - calls event handlers when they expire 18 * Event handlers may alter expiration, callback and data during operation. 19 */ 20static void timeout_tick(void) 21{ 22 unsigned long tick = current_tick; 23 struct timeout **p = tmo_list; 24 struct timeout *curr; 25 26 for(curr = *p; curr != NULL; curr = *(++p)) 27 { 28 int ticks; 29 30 if(TIME_BEFORE(tick, curr->expires)) 31 continue; 32 33 /* this event has expired - call callback */ 34 ticks = curr->callback(curr); 35 if(ticks > 0) 36 { 37 curr->expires = tick + ticks; /* reload */ 38 } 39 else 40 { 41 timeout_cancel(curr); /* cancel */ 42 } 43 } 44} 45 46/* Cancels a timeout callback - can be called from the ISR */ 47void timeout_cancel(struct timeout *tmo) 48{ 49 int oldlevel = disable_irq_save(); 50 int rc = remove_array_ptr((void **)tmo_list, tmo); 51 52 if(rc >= 0 && *tmo_list == NULL) 53 { 54 tick_remove_task(timeout_tick); /* Last one - remove task */ 55 } 56 57 restore_irq(oldlevel); 58} 59 60/* Adds a timeout callback - calling with an active timeout resets the 61 interval - can be called from the ISR */ 62void timeout_register(struct timeout *tmo, timeout_cb_type callback, 63 int ticks, intptr_t data) 64{ 65 int oldlevel; 66 void **arr, **p; 67 68 if(tmo == NULL) 69 return; 70 71 oldlevel = disable_irq_save(); 72 73 /* See if this one is already registered */ 74 arr = (void **)tmo_list; 75 p = find_array_ptr(arr, tmo); 76 77 if(p - arr < MAX_NUM_TIMEOUTS) 78 { 79 /* Vacancy */ 80 if(*p == NULL) 81 { 82 /* Not present */ 83 if(*tmo_list == NULL) 84 { 85 tick_add_task(timeout_tick); /* First one - add task */ 86 } 87 88 *p = tmo; 89 } 90 91 tmo->callback = callback; 92 tmo->data = data; 93 tmo->expires = current_tick + ticks; 94 } 95 96 restore_irq(oldlevel); 97}