Xenomai 3.3.2
Loading...
Searching...
No Matches
timer.h
1/*
2 * Copyright (C) 2001,2002,2003 Philippe Gerum <rpm@xenomai.org>.
3 *
4 * Xenomai is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * Xenomai is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Xenomai; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
18 */
19
20#ifndef _COBALT_KERNEL_TIMER_H
21#define _COBALT_KERNEL_TIMER_H
22
23#include <cobalt/kernel/clock.h>
24#include <cobalt/kernel/stat.h>
25#include <cobalt/kernel/list.h>
26#include <cobalt/kernel/assert.h>
27#include <cobalt/kernel/ancillaries.h>
28#include <asm/xenomai/wrappers.h>
29
34#define XN_INFINITE ((xnticks_t)0)
35#define XN_NONBLOCK ((xnticks_t)-1)
36
37/* Timer modes */
38typedef enum xntmode {
39 XN_RELATIVE,
40 XN_ABSOLUTE,
41 XN_REALTIME
42} xntmode_t;
43
44/* Timer status */
45#define XNTIMER_DEQUEUED 0x00000001
46#define XNTIMER_KILLED 0x00000002
47#define XNTIMER_PERIODIC 0x00000004
48#define XNTIMER_REALTIME 0x00000008
49#define XNTIMER_FIRED 0x00000010
50#define XNTIMER_RUNNING 0x00000020
51#define XNTIMER_KGRAVITY 0x00000040
52#define XNTIMER_UGRAVITY 0x00000080
53#define XNTIMER_IGRAVITY 0 /* most conservative */
54
55#define XNTIMER_GRAVITY_MASK (XNTIMER_KGRAVITY|XNTIMER_UGRAVITY)
56#define XNTIMER_INIT_MASK XNTIMER_GRAVITY_MASK
57
58/* These flags are available to the real-time interfaces */
59#define XNTIMER_SPARE0 0x01000000
60#define XNTIMER_SPARE1 0x02000000
61#define XNTIMER_SPARE2 0x04000000
62#define XNTIMER_SPARE3 0x08000000
63#define XNTIMER_SPARE4 0x10000000
64#define XNTIMER_SPARE5 0x20000000
65#define XNTIMER_SPARE6 0x40000000
66#define XNTIMER_SPARE7 0x80000000
67
68/* Timer priorities */
69#define XNTIMER_LOPRIO (-999999999)
70#define XNTIMER_STDPRIO 0
71#define XNTIMER_HIPRIO 999999999
72
73struct xntlholder {
74 struct list_head link;
75 xnticks_t key;
76 int prio;
77};
78
79#define xntlholder_date(h) ((h)->key)
80#define xntlholder_prio(h) ((h)->prio)
81#define xntlist_init(q) INIT_LIST_HEAD(q)
82#define xntlist_empty(q) list_empty(q)
83
84static inline struct xntlholder *xntlist_head(struct list_head *q)
85{
86 if (list_empty(q))
87 return NULL;
88
89 return list_first_entry(q, struct xntlholder, link);
90}
91
92static inline struct xntlholder *xntlist_next(struct list_head *q,
93 struct xntlholder *h)
94{
95 if (list_is_last(&h->link, q))
96 return NULL;
97
98 return list_entry(h->link.next, struct xntlholder, link);
99}
100
101static inline struct xntlholder *xntlist_second(struct list_head *q,
102 struct xntlholder *h)
103{
104 return xntlist_next(q, h);
105}
106
107static inline void xntlist_insert(struct list_head *q, struct xntlholder *holder)
108{
109 struct xntlholder *p;
110
111 if (list_empty(q)) {
112 list_add(&holder->link, q);
113 return;
114 }
115
116 /*
117 * Insert the new timer at the proper place in the single
118 * queue. O(N) here, but this is the price for the increased
119 * flexibility...
120 */
121 list_for_each_entry_reverse(p, q, link) {
122 if ((xnsticks_t) (holder->key - p->key) > 0 ||
123 (holder->key == p->key && holder->prio <= p->prio))
124 break;
125 }
126
127 list_add(&holder->link, &p->link);
128}
129
130#define xntlist_remove(q, h) \
131 do { \
132 (void)(q); \
133 list_del(&(h)->link); \
134 } while (0)
135
136#if defined(CONFIG_XENO_OPT_TIMER_RBTREE)
137
138#include <linux/rbtree.h>
139
140typedef struct {
141 unsigned long long date;
142 unsigned prio;
143 struct rb_node link;
144} xntimerh_t;
145
146#define xntimerh_date(h) ((h)->date)
147#define xntimerh_prio(h) ((h)->prio)
148#define xntimerh_init(h) do { } while (0)
149
150typedef struct {
151 struct rb_root root;
152 xntimerh_t *head;
153} xntimerq_t;
154
155#define xntimerq_init(q) \
156 ({ \
157 xntimerq_t *_q = (q); \
158 _q->root = RB_ROOT; \
159 _q->head = NULL; \
160 })
161
162#define xntimerq_destroy(q) do { } while (0)
163#define xntimerq_empty(q) ((q)->head == NULL)
164
165#define xntimerq_head(q) ((q)->head)
166
167#define xntimerq_next(q, h) \
168 ({ \
169 struct rb_node *_node = rb_next(&(h)->link); \
170 _node ? (container_of(_node, xntimerh_t, link)) : NULL; \
171 })
172
173#define xntimerq_second(q, h) xntimerq_next(q, h)
174
175void xntimerq_insert(xntimerq_t *q, xntimerh_t *holder);
176
177static inline void xntimerq_remove(xntimerq_t *q, xntimerh_t *holder)
178{
179 if (holder == q->head)
180 q->head = xntimerq_second(q, holder);
181
182 rb_erase(&holder->link, &q->root);
183}
184
185typedef struct { } xntimerq_it_t;
186
187#define xntimerq_it_begin(q,i) ((void) (i), xntimerq_head(q))
188#define xntimerq_it_next(q,i,h) ((void) (i), xntimerq_next((q),(h)))
189
190#else /* CONFIG_XENO_OPT_TIMER_LIST */
191
192typedef struct xntlholder xntimerh_t;
193
194#define xntimerh_date(h) xntlholder_date(h)
195#define xntimerh_prio(h) xntlholder_prio(h)
196#define xntimerh_init(h) do { } while (0)
197
198typedef struct list_head xntimerq_t;
199
200#define xntimerq_init(q) xntlist_init(q)
201#define xntimerq_destroy(q) do { } while (0)
202#define xntimerq_empty(q) xntlist_empty(q)
203#define xntimerq_head(q) xntlist_head(q)
204#define xntimerq_second(q, h) xntlist_second((q),(h))
205#define xntimerq_insert(q, h) xntlist_insert((q),(h))
206#define xntimerq_remove(q, h) xntlist_remove((q),(h))
207
208typedef struct { } xntimerq_it_t;
209
210#define xntimerq_it_begin(q,i) ((void) (i), xntlist_head(q))
211#define xntimerq_it_next(q,i,h) ((void) (i), xntlist_next((q),(h)))
212
213#endif /* CONFIG_XENO_OPT_TIMER_LIST */
214
215struct xnsched;
216
217struct xntimerdata {
218 xntimerq_t q;
219};
220
221static inline struct xntimerdata *
222xnclock_percpu_timerdata(struct xnclock *clock, int cpu)
223{
224 return per_cpu_ptr(clock->timerdata, cpu);
225}
226
227static inline struct xntimerdata *
228xnclock_this_timerdata(struct xnclock *clock)
229{
230 return raw_cpu_ptr(clock->timerdata);
231}
232
233struct xntimer {
234#ifdef CONFIG_XENO_OPT_EXTCLOCK
235 struct xnclock *clock;
236#endif
238 xntimerh_t aplink;
239 struct list_head adjlink;
241 unsigned long status;
243 xnticks_t interval;
245 xnticks_t interval_ns;
247 xnticks_t periodic_ticks;
249 xnticks_t start_date;
251 xnticks_t pexpect_ticks;
253 struct xnsched *sched;
255 void (*handler)(struct xntimer *timer);
256#ifdef CONFIG_XENO_OPT_STATS
257#ifdef CONFIG_XENO_OPT_EXTCLOCK
258 struct xnclock *tracker;
259#endif
261 char name[XNOBJECT_NAME_LEN];
263 struct list_head next_stat;
265 xnstat_counter_t scheduled;
267 xnstat_counter_t fired;
268#endif /* CONFIG_XENO_OPT_STATS */
269};
270
271#ifdef CONFIG_XENO_OPT_EXTCLOCK
272
273static inline struct xnclock *xntimer_clock(struct xntimer *timer)
274{
275 return timer->clock;
276}
277
278void xntimer_set_clock(struct xntimer *timer,
279 struct xnclock *newclock);
280
281#else /* !CONFIG_XENO_OPT_EXTCLOCK */
282
283static inline struct xnclock *xntimer_clock(struct xntimer *timer)
284{
285 return &nkclock;
286}
287
288static inline void xntimer_set_clock(struct xntimer *timer,
289 struct xnclock *newclock)
290{
291 XENO_BUG_ON(COBALT, newclock != &nkclock);
292}
293
294#endif /* !CONFIG_XENO_OPT_EXTCLOCK */
295
296#ifdef CONFIG_SMP
297static inline struct xnsched *xntimer_sched(struct xntimer *timer)
298{
299 return timer->sched;
300}
301#else /* !CONFIG_SMP */
302#define xntimer_sched(t) xnsched_current()
303#endif /* !CONFIG_SMP */
304
305#define xntimer_percpu_queue(__timer) \
306 ({ \
307 struct xntimerdata *tmd; \
308 int cpu = xnsched_cpu((__timer)->sched); \
309 tmd = xnclock_percpu_timerdata(xntimer_clock(__timer), cpu); \
310 &tmd->q; \
311 })
312
313static inline unsigned long xntimer_gravity(struct xntimer *timer)
314{
315 struct xnclock *clock = xntimer_clock(timer);
316
317 if (timer->status & XNTIMER_KGRAVITY)
318 return clock->gravity.kernel;
319
320 if (timer->status & XNTIMER_UGRAVITY)
321 return clock->gravity.user;
322
323 return clock->gravity.irq;
324}
325
326static inline void xntimer_update_date(struct xntimer *timer)
327{
328 xntimerh_date(&timer->aplink) = timer->start_date
329 + xnclock_ns_to_ticks(xntimer_clock(timer),
330 timer->periodic_ticks * timer->interval_ns)
331 - xntimer_gravity(timer);
332}
333
334static inline xnticks_t xntimer_pexpect(struct xntimer *timer)
335{
336 return timer->start_date +
337 xnclock_ns_to_ticks(xntimer_clock(timer),
338 timer->pexpect_ticks * timer->interval_ns);
339}
340
341static inline void xntimer_set_priority(struct xntimer *timer,
342 int prio)
343{
344 xntimerh_prio(&timer->aplink) = prio;
345}
346
347static inline int xntimer_active_p(struct xntimer *timer)
348{
349 return timer->sched != NULL;
350}
351
352static inline int xntimer_running_p(struct xntimer *timer)
353{
354 return (timer->status & XNTIMER_RUNNING) != 0;
355}
356
357static inline int xntimer_fired_p(struct xntimer *timer)
358{
359 return (timer->status & XNTIMER_FIRED) != 0;
360}
361
362static inline int xntimer_periodic_p(struct xntimer *timer)
363{
364 return (timer->status & XNTIMER_PERIODIC) != 0;
365}
366
367void __xntimer_init(struct xntimer *timer,
368 struct xnclock *clock,
369 void (*handler)(struct xntimer *timer),
370 struct xnsched *sched,
371 int flags);
372
373void xntimer_set_gravity(struct xntimer *timer,
374 int gravity);
375
376#ifdef CONFIG_XENO_OPT_STATS
377
378#define xntimer_init(__timer, __clock, __handler, __sched, __flags) \
379do { \
380 __xntimer_init(__timer, __clock, __handler, __sched, __flags); \
381 xntimer_set_name(__timer, #__handler); \
382} while (0)
383
384static inline void xntimer_reset_stats(struct xntimer *timer)
385{
386 xnstat_counter_set(&timer->scheduled, 0);
387 xnstat_counter_set(&timer->fired, 0);
388}
389
390static inline void xntimer_account_scheduled(struct xntimer *timer)
391{
392 xnstat_counter_inc(&timer->scheduled);
393}
394
395static inline void xntimer_account_fired(struct xntimer *timer)
396{
397 xnstat_counter_inc(&timer->fired);
398}
399
400static inline void xntimer_set_name(struct xntimer *timer, const char *name)
401{
402 knamecpy(timer->name, name);
403}
404
405#else /* !CONFIG_XENO_OPT_STATS */
406
407#define xntimer_init __xntimer_init
408
409static inline void xntimer_reset_stats(struct xntimer *timer) { }
410
411static inline void xntimer_account_scheduled(struct xntimer *timer) { }
412
413static inline void xntimer_account_fired(struct xntimer *timer) { }
414
415static inline void xntimer_set_name(struct xntimer *timer, const char *name) { }
416
417#endif /* !CONFIG_XENO_OPT_STATS */
418
419#if defined(CONFIG_XENO_OPT_EXTCLOCK) && defined(CONFIG_XENO_OPT_STATS)
420void xntimer_switch_tracking(struct xntimer *timer,
421 struct xnclock *newclock);
422#else
423static inline
424void xntimer_switch_tracking(struct xntimer *timer,
425 struct xnclock *newclock) { }
426#endif
427
428void xntimer_destroy(struct xntimer *timer);
429
445static inline xnticks_t xntimer_interval(struct xntimer *timer)
446{
447 return timer->interval_ns;
448}
449
450static inline xnticks_t xntimer_expiry(struct xntimer *timer)
451{
452 /* Real expiry date in ticks without anticipation (no gravity) */
453 return xntimerh_date(&timer->aplink) + xntimer_gravity(timer);
454}
455
456int xntimer_start(struct xntimer *timer,
457 xnticks_t value,
458 xnticks_t interval,
459 xntmode_t mode);
460
461void __xntimer_stop(struct xntimer *timer);
462
463xnticks_t xntimer_get_date(struct xntimer *timer);
464
465xnticks_t __xntimer_get_timeout(struct xntimer *timer);
466
467xnticks_t xntimer_get_interval(struct xntimer *timer);
468
469int xntimer_heading_p(struct xntimer *timer);
470
471static inline void xntimer_stop(struct xntimer *timer)
472{
473 if (timer->status & XNTIMER_RUNNING)
474 __xntimer_stop(timer);
475}
476
477static inline xnticks_t xntimer_get_timeout(struct xntimer *timer)
478{
479 if (!xntimer_running_p(timer))
480 return XN_INFINITE;
481
482 return __xntimer_get_timeout(timer);
483}
484
485static inline xnticks_t xntimer_get_timeout_stopped(struct xntimer *timer)
486{
487 return __xntimer_get_timeout(timer);
488}
489
490static inline void xntimer_enqueue(struct xntimer *timer,
491 xntimerq_t *q)
492{
493 xntimerq_insert(q, &timer->aplink);
494 timer->status &= ~XNTIMER_DEQUEUED;
495 xntimer_account_scheduled(timer);
496}
497
498static inline void xntimer_dequeue(struct xntimer *timer,
499 xntimerq_t *q)
500{
501 xntimerq_remove(q, &timer->aplink);
502 timer->status |= XNTIMER_DEQUEUED;
503}
504
505unsigned long long xntimer_get_overruns(struct xntimer *timer,
506 struct xnthread *waiter,
507 xnticks_t now);
508
509#ifdef CONFIG_SMP
510
511void __xntimer_migrate(struct xntimer *timer, struct xnsched *sched);
512
513static inline
514void xntimer_migrate(struct xntimer *timer, struct xnsched *sched)
515{ /* nklocked, IRQs off */
516 if (timer->sched != sched)
517 __xntimer_migrate(timer, sched);
518}
519
520void __xntimer_set_affinity(struct xntimer *timer,
521 struct xnsched *sched);
522
523static inline void xntimer_set_affinity(struct xntimer *timer,
524 struct xnsched *sched)
525{
526 if (sched != xntimer_sched(timer))
527 __xntimer_set_affinity(timer, sched);
528}
529
530#else /* ! CONFIG_SMP */
531
532static inline void xntimer_migrate(struct xntimer *timer,
533 struct xnsched *sched)
534{
535 timer->sched = sched;
536}
537
538static inline void xntimer_set_affinity(struct xntimer *timer,
539 struct xnsched *sched)
540{
541 xntimer_migrate(timer, sched);
542}
543
544#endif /* CONFIG_SMP */
545
546char *xntimer_format_time(xnticks_t ns,
547 char *buf, size_t bufsz);
548
551#endif /* !_COBALT_KERNEL_TIMER_H */
unsigned long long xntimer_get_overruns(struct xntimer *timer, struct xnthread *waiter, xnticks_t now)
Get the count of overruns for the last tick.
Definition timer.c:612
xnticks_t xntimer_get_date(struct xntimer *timer)
Return the absolute expiration date.
Definition timer.c:247
int xntimer_start(struct xntimer *timer, xnticks_t value, xnticks_t interval, xntmode_t mode)
Arm a timer.
Definition timer.c:114
static void xntimer_stop(struct xntimer *timer)
Disarm a timer.
Definition timer.h:471
void __xntimer_migrate(struct xntimer *timer, struct xnsched *sched)
Migrate a timer.
Definition timer.c:507
void xntimer_destroy(struct xntimer *timer)
Release a timer object.
Definition timer.c:473
static xnticks_t xntimer_interval(struct xntimer *timer)
Return the timer interval value.
Definition timer.h:445
static xnticks_t xntimer_get_timeout(struct xntimer *timer)
Return the relative expiration date.
Definition timer.h:477
Scheduling information structure.
Definition sched.h:64