summaryrefslogtreecommitdiff
path: root/firmware/kernel/timeout.c
diff options
context:
space:
mode:
authorThomas Martitz <kugel@rockbox.org>2013-12-04 17:06:17 +0100
committerThomas Martitz <kugel@rockbox.org>2014-03-03 18:11:57 +0100
commit382d1861af12741af4ff235b9d18f179c0adc4c5 (patch)
tree26166c130d2889bb1ae1082e8f7aba103534f49e /firmware/kernel/timeout.c
parent8bae5f2644b5d5759499fbf1066b9c35c6f859ad (diff)
downloadrockbox-382d1861af12741af4ff235b9d18f179c0adc4c5.tar.gz
rockbox-382d1861af12741af4ff235b9d18f179c0adc4c5.zip
kernel: Break out kernel primitives into separate files and move to separate dir.
No code changed, just shuffling stuff around. This should make it easier to build only select parts kernel and use different implementations. Change-Id: Ie1f00f93008833ce38419d760afd70062c5e22b5
Diffstat (limited to 'firmware/kernel/timeout.c')
-rw-r--r--firmware/kernel/timeout.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/firmware/kernel/timeout.c b/firmware/kernel/timeout.c
new file mode 100644
index 0000000000..8039e56ffb
--- /dev/null
+++ b/firmware/kernel/timeout.c
@@ -0,0 +1,97 @@
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}