23 #ifndef _XENO_NUCLEUS_TIMER_H
24 #define _XENO_NUCLEUS_TIMER_H
27 #include <nucleus/stat.h>
29 #if defined(__KERNEL__) || defined(__XENO_SIM__)
31 #ifndef CONFIG_XENO_OPT_DEBUG_TIMERS
32 #define CONFIG_XENO_OPT_DEBUG_TIMERS 0
35 #define XNTIMER_WHEELSIZE 64
36 #define XNTIMER_WHEELMASK (XNTIMER_WHEELSIZE - 1)
39 #define XNTIMER_DEQUEUED 0x00000001
40 #define XNTIMER_KILLED 0x00000002
41 #define XNTIMER_PERIODIC 0x00000004
42 #define XNTIMER_REALTIME 0x00000008
43 #define XNTIMER_FIRED 0x00000010
44 #define XNTIMER_NOBLCK 0x00000020
47 #define XNTIMER_SPARE0 0x01000000
48 #define XNTIMER_SPARE1 0x02000000
49 #define XNTIMER_SPARE2 0x04000000
50 #define XNTIMER_SPARE3 0x08000000
51 #define XNTIMER_SPARE4 0x10000000
52 #define XNTIMER_SPARE5 0x20000000
53 #define XNTIMER_SPARE6 0x40000000
54 #define XNTIMER_SPARE7 0x80000000
57 #define XNTIMER_LOPRIO (-999999999)
58 #define XNTIMER_STDPRIO 0
59 #define XNTIMER_HIPRIO 999999999
61 #define XNTIMER_KEEPER_ID 0
68 #define link2tlholder(ln) container_of(ln, xntlholder_t, link)
72 #define xntlholder_date(h) ((h)->key)
73 #define xntlholder_prio(h) ((h)->prio)
74 #define xntlholder_init(h) inith(&(h)->link)
75 #define xntlist_init(q) initq(q)
76 #define xntlist_head(q) \
77 ({ xnholder_t *_h = getheadq(q); \
78 !_h ? NULL : link2tlholder(_h); \
81 #define xntlist_next(q, h) \
82 ({ xnholder_t *_h = nextq(q, &(h)->link); \
83 !_h ? NULL : link2tlholder(_h); \
86 static inline void xntlist_insert(xnqueue_t *q, xntlholder_t *holder)
95 for (p = q->head.last; p != &q->head; p = p->last)
96 if ((xnsticks_t) (holder->key - link2tlholder(p)->key) > 0 ||
97 (holder->key == link2tlholder(p)->key &&
98 holder->prio <= link2tlholder(p)->prio))
101 insertq(q,p->next,&holder->link);
104 #define xntlist_remove(q, h) removeq((q),&(h)->link)
106 #if defined(CONFIG_XENO_OPT_TIMER_HEAP)
108 #include <nucleus/bheap.h>
110 typedef bheaph_t xntimerh_t;
112 #define xntimerh_date(h) bheaph_key(h)
113 #define xntimerh_prio(h) bheaph_prio(h)
114 #define xntimerh_init(h) bheaph_init(h)
116 typedef DECLARE_BHEAP_CONTAINER(xntimerq_t, CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY);
118 #define xntimerq_init(q) bheap_init((q), CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY)
119 #define xntimerq_destroy(q) bheap_destroy(q)
120 #define xntimerq_head(q) bheap_gethead(q)
121 #define xntimerq_insert(q, h) bheap_insert((q),(h))
122 #define xntimerq_remove(q, h) bheap_delete((q),(h))
124 typedef struct {} xntimerq_it_t;
126 #define xntimerq_it_begin(q, i) ((void) (i), bheap_gethead(q))
127 #define xntimerq_it_next(q, i, h) ((void) (i), bheap_next((q),(h)))
129 #elif defined(CONFIG_XENO_OPT_TIMER_WHEEL)
131 typedef xntlholder_t xntimerh_t;
133 #define xntimerh_date(h) xntlholder_date(h)
134 #define xntimerh_prio(h) xntlholder_prio(h)
135 #define xntimerh_init(h) xntlholder_init(h)
137 typedef struct xntimerq {
139 unsigned long long next_shot;
140 unsigned long long shot_wrap;
141 xnqueue_t bucket[XNTIMER_WHEELSIZE];
144 typedef struct xntimerq_it {
148 static inline void xntimerq_init(xntimerq_t *q)
150 unsigned long long step_tsc;
153 step_tsc = xnarch_ns_to_tsc(CONFIG_XENO_OPT_TIMER_WHEEL_STEP);
155 for (q->date_shift = 0; (1 << q->date_shift) < step_tsc; q->date_shift++)
157 q->next_shot = q->shot_wrap = ((~0ULL) >> q->date_shift) + 1;
158 for (i = 0; i <
sizeof(q->bucket)/
sizeof(xnqueue_t); i++)
159 xntlist_init(&q->bucket[i]);
162 #define xntimerq_destroy(q) do { } while (0)
164 static inline xntlholder_t *xntimerq_head(xntimerq_t *q)
166 unsigned bucket = ((unsigned) q->next_shot) & XNTIMER_WHEELMASK;
167 xntlholder_t *result;
170 if (q->next_shot == q->shot_wrap)
173 result = xntlist_head(&q->bucket[bucket]);
175 if (result && (xntlholder_date(result) >> q->date_shift) == q->next_shot)
180 for (i = (bucket + 1) & XNTIMER_WHEELMASK ;
181 i != bucket; i = (i + 1) & XNTIMER_WHEELMASK) {
182 xntlholder_t *candidate = xntlist_head(&q->bucket[i]);
184 if(++q->next_shot == q->shot_wrap)
190 if ((xntlholder_date(candidate) >> q->date_shift) == q->next_shot)
193 if (!result || (xnsticks_t) (xntlholder_date(candidate)
194 - xntlholder_date(result)) < 0)
199 q->next_shot = (xntlholder_date(result) >> q->date_shift);
201 q->next_shot = q->shot_wrap;
205 static inline void xntimerq_insert(xntimerq_t *q, xntimerh_t *h)
207 unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
208 unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
210 if ((
long long) (shifted_date - q->next_shot) < 0)
211 q->next_shot = shifted_date;
212 xntlist_insert(&q->bucket[bucket], h);
215 static inline void xntimerq_remove(xntimerq_t *q, xntimerh_t *h)
217 unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
218 unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
220 xntlist_remove(&q->bucket[bucket], h);
224 static inline xntimerh_t *xntimerq_it_begin(xntimerq_t *q, xntimerq_it_t *it)
226 xntimerh_t *holder = NULL;
228 for (it->bucket = 0; it->bucket < XNTIMER_WHEELSIZE; it->bucket++)
229 if ((holder = xntlist_head(&q->bucket[it->bucket])))
235 static inline xntimerh_t *
236 xntimerq_it_next(xntimerq_t *q, xntimerq_it_t *it, xntimerh_t *holder)
238 xntimerh_t *next = xntlist_next(&q->bucket[it->bucket], holder);
241 for(it->bucket++; it->bucket < XNTIMER_WHEELSIZE; it->bucket++)
242 if ((next = xntlist_head(&q->bucket[it->bucket])))
250 typedef xntlholder_t xntimerh_t;
252 #define xntimerh_date(h) xntlholder_date(h)
253 #define xntimerh_prio(h) xntlholder_prio(h)
254 #define xntimerh_init(h) xntlholder_init(h)
256 typedef xnqueue_t xntimerq_t;
258 #define xntimerq_init(q) xntlist_init(q)
259 #define xntimerq_destroy(q) do { } while (0)
260 #define xntimerq_head(q) xntlist_head(q)
261 #define xntimerq_insert(q,h) xntlist_insert((q),(h))
262 #define xntimerq_remove(q, h) xntlist_remove((q),(h))
264 typedef struct {} xntimerq_it_t;
266 #define xntimerq_it_begin(q,i) ((void) (i), xntlist_head(q))
267 #define xntimerq_it_next(q,i,h) ((void) (i), xntlist_next((q),(h)))
273 typedef struct xntimer {
277 #define aplink2timer(ln) container_of(ln, xntimer_t, aplink)
279 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
284 #define plink2timer(ln) container_of(ln, xntimer_t, plink)
289 #define adjlink2timer(ln) container_of(ln, xntimer_t, adjlink)
300 void (*handler)(
struct xntimer *timer);
302 #ifdef CONFIG_XENO_OPT_STATS
303 char name[XNOBJECT_NAME_LEN];
305 const char *handler_name;
309 #define tblink2timer(ln) container_of(ln, xntimer_t, tblink)
312 xnstat_counter_t scheduled;
314 xnstat_counter_t fired;
316 XNARCH_DECL_DISPLAY_CONTEXT();
320 typedef struct xntimed_slave {
324 struct percpu_cascade {
326 xnqueue_t wheel[XNTIMER_WHEELSIZE];
327 } cascade[XNARCH_NR_CPUS];
329 #define timer2slave(t) \
330 ((xntslave_t *)(((char *)t) - offsetof(xntslave_t, cascade[xnsched_cpu((t)->sched)].timer)))
331 #define base2slave(b) \
332 ((xntslave_t *)(((char *)b) - offsetof(xntslave_t, base)))
337 #define xntimer_sched(t) ((t)->sched)
339 #define xntimer_sched(t) xnpod_current_sched()
341 #define xntimer_interval(t) ((t)->interval)
342 #define xntimer_pexpect(t) ((t)->pexpect)
343 #define xntimer_pexpect_forward(t,delta) ((t)->pexpect += delta)
345 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
346 #define xntimer_base(t) ((t)->base)
347 #define xntimer_set_priority(t,p) \
349 xntimer_t *_t = (t); \
350 unsigned prio = (p); \
351 xntimerh_prio(&(_t)->aplink) = prio; \
352 xntlholder_prio(&(_t)->plink) = prio; \
355 #define xntimer_base(t) (&nktbase)
356 #define xntimer_set_priority(t,p) \
357 do { xntimerh_prio(&(t)->aplink) = (p); } while(0)
360 static inline int xntimer_active_p (xntimer_t *timer)
362 return timer->sched != NULL;
365 static inline int xntimer_running_p(xntimer_t *timer)
367 return !testbits(timer->status,XNTIMER_DEQUEUED);
370 static inline int xntimer_reload_p(xntimer_t *timer)
372 return testbits(timer->status,
373 XNTIMER_PERIODIC|XNTIMER_DEQUEUED|XNTIMER_KILLED) ==
374 (XNTIMER_PERIODIC|XNTIMER_DEQUEUED);
381 extern xntbops_t nktimer_ops_aperiodic,
382 nktimer_ops_periodic;
384 #ifdef CONFIG_XENO_OPT_STATS
385 #define xntimer_init(timer, base, handler) \
387 __xntimer_init(timer, base, handler); \
388 (timer)->handler_name = #handler; \
391 #define xntimer_init __xntimer_init
394 #define xntimer_init_noblock(timer, base, handler) \
396 xntimer_init(timer, base, handler); \
397 (timer)->status |= XNTIMER_NOBLCK; \
400 void __xntimer_init(
struct xntimer *timer,
401 struct xntbase *base,
402 void (*handler)(
struct xntimer *timer));
406 static inline void xntimer_set_name(xntimer_t *timer,
const char *name)
408 #ifdef CONFIG_XENO_OPT_STATS
409 strncpy(timer->name, name,
sizeof(timer->name));
413 void xntimer_next_local_shot(
struct xnsched *sched);
419 #if defined(CONFIG_XENO_OPT_TIMING_PERIODIC) || defined(DOXYGEN_CPP)
474 xnticks_t value, xnticks_t interval,
477 return timer->base->ops->start_timer(timer, value, interval, mode);
511 if (!testbits(timer->status,XNTIMER_DEQUEUED))
512 timer->base->ops->stop_timer(timer);
549 if (!xntimer_running_p(timer))
552 return timer->base->ops->get_timer_date(timer);
591 if (!xntimer_running_p(timer))
594 return timer->base->ops->get_timer_timeout(timer);
597 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
599 return timer->base->ops->get_timer_timeout(timer);
635 return timer->base->ops->get_timer_interval(timer);
638 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
640 return timer->base->ops->get_timer_raw_expiry(timer);
643 void xntslave_init(xntslave_t *slave);
645 void xntslave_destroy(xntslave_t *slave);
647 void xntslave_update(xntslave_t *slave,
650 void xntslave_start(xntslave_t *slave,
654 void xntslave_stop(xntslave_t *slave);
656 void xntslave_adjust(xntslave_t *slave, xnsticks_t delta);
660 int xntimer_start_aperiodic(xntimer_t *timer,
665 void xntimer_stop_aperiodic(xntimer_t *timer);
667 xnticks_t xntimer_get_date_aperiodic(xntimer_t *timer);
669 xnticks_t xntimer_get_timeout_aperiodic(xntimer_t *timer);
671 xnticks_t xntimer_get_interval_aperiodic(xntimer_t *timer);
673 xnticks_t xntimer_get_raw_expiry_aperiodic(xntimer_t *timer);
676 xnticks_t value, xnticks_t interval,
679 return xntimer_start_aperiodic(timer, value, interval, mode);
684 if (!testbits(timer->status,XNTIMER_DEQUEUED))
685 xntimer_stop_aperiodic(timer);
690 if (!xntimer_running_p(timer))
693 return xntimer_get_date_aperiodic(timer);
698 if (!xntimer_running_p(timer))
701 return xntimer_get_timeout_aperiodic(timer);
704 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
706 return xntimer_get_timeout_aperiodic(timer);
711 return xntimer_get_interval_aperiodic(timer);
714 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
716 return xntimerh_date(&timer->aplink);
723 void xntimer_init_proc(
void);
725 void xntimer_cleanup_proc(
void);
735 void xntimer_tick_periodic_inner(xntslave_t *slave);
737 void xntimer_adjust_all_aperiodic(xnsticks_t delta);
740 int xntimer_migrate(xntimer_t *timer,
743 #define xntimer_migrate(timer, sched) do { } while(0)
746 #define xntimer_set_sched(timer, sched) xntimer_migrate(timer, sched)
748 char *xntimer_format_time(xnticks_t value,
int periodic,
749 char *buf,
size_t bufsz);