Xenomai API  2.6.5
timer.h
Go to the documentation of this file.
1 
23 #ifndef _XENO_NUCLEUS_TIMER_H
24 #define _XENO_NUCLEUS_TIMER_H
25 
26 #include <nucleus/timebase.h>
27 #include <nucleus/stat.h>
28 
29 #if defined(__KERNEL__) || defined(__XENO_SIM__)
30 
31 #ifndef CONFIG_XENO_OPT_DEBUG_TIMERS
32 #define CONFIG_XENO_OPT_DEBUG_TIMERS 0
33 #endif
34 
35 #define XNTIMER_WHEELSIZE 64
36 #define XNTIMER_WHEELMASK (XNTIMER_WHEELSIZE - 1)
37 
38 /* Timer status */
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
45 
46 /* These flags are available to the real-time interfaces */
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
55 
56 /* Timer priorities */
57 #define XNTIMER_LOPRIO (-999999999)
58 #define XNTIMER_STDPRIO 0
59 #define XNTIMER_HIPRIO 999999999
60 
61 #define XNTIMER_KEEPER_ID 0
62 
63 typedef struct {
64  xnholder_t link;
65  xnticks_t key;
66  int prio;
67 
68 #define link2tlholder(ln) container_of(ln, xntlholder_t, link)
69 
70 } xntlholder_t;
71 
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); \
79  })
80 
81 #define xntlist_next(q, h) \
82  ({ xnholder_t *_h = nextq(q, &(h)->link); \
83  !_h ? NULL : link2tlholder(_h); \
84  })
85 
86 #define xntlist_second(q, h) xntlist_next((q),(h))
87 
88 static inline void xntlist_insert(xnqueue_t *q, xntlholder_t *holder)
89 {
90  xnholder_t *p;
91 
92  /* Insert the new timer at the proper place in the single
93  queue managed when running in aperiodic mode. O(N) here,
94  but users of the aperiodic mode need to pay a price for the
95  increased flexibility... */
96 
97  for (p = q->head.last; p != &q->head; p = p->last)
98  if ((xnsticks_t) (holder->key - link2tlholder(p)->key) > 0 ||
99  (holder->key == link2tlholder(p)->key &&
100  holder->prio <= link2tlholder(p)->prio))
101  break;
102 
103  insertq(q,p->next,&holder->link);
104 }
105 
106 #define xntlist_remove(q, h) removeq((q),&(h)->link)
107 
108 #if defined(CONFIG_XENO_OPT_TIMER_RBTREE)
109 
110 #include <linux/rbtree.h>
111 
112 typedef struct {
113  unsigned long long date;
114  unsigned prio;
115  struct rb_node link;
116 } xntimerh_t;
117 
118 #define xntimerh_date(h) ((h)->date)
119 #define xntimerh_prio(h) ((h)->prio)
120 #define xntimerh_init(h) do { } while (0)
121 
122 typedef struct {
123  struct rb_root root;
124  xntimerh_t *head;
125 } xntimerq_t;
126 
127 #define xntimerq_init(q) \
128  ({ \
129  xntimerq_t *_q = (q); \
130  _q->root = RB_ROOT; \
131  _q->head = NULL; \
132  })
133 
134 #define xntimerq_destroy(q) do { } while (0)
135 #define xntimerq_empty(q) ((q)->head != NULL)
136 
137 #define xntimerq_head(q) ((q)->head)
138 
139 #define xntimerq_next(q, h) \
140  ({ \
141  struct rb_node *_node = rb_next(&(h)->link); \
142  _node ? (container_of(_node, xntimerh_t, link)) : NULL; \
143  })
144 
145 #define xntimerq_second(q, h) xntimerq_next(q, h)
146 
147 void xntimerq_insert(xntimerq_t *q, xntimerh_t *holder);
148 
149 static inline void xntimerq_remove(xntimerq_t *q, xntimerh_t *holder)
150 {
151  if (holder == q->head)
152  q->head = xntimerq_second(q, holder);
153 
154  rb_erase(&holder->link, &q->root);
155 }
156 
157 typedef struct { } xntimerq_it_t;
158 
159 #define xntimerq_it_begin(q,i) ((void) (i), xntimerq_head(q))
160 #define xntimerq_it_next(q,i,h) ((void) (i), xntimerq_next((q),(h)))
161 
162 #else /* CONFIG_XENO_OPT_TIMER_LIST */
163 
164 typedef xntlholder_t xntimerh_t;
165 
166 #define xntimerh_date(h) xntlholder_date(h)
167 #define xntimerh_prio(h) xntlholder_prio(h)
168 #define xntimerh_init(h) xntlholder_init(h)
169 
170 typedef xnqueue_t xntimerq_t;
171 
172 #define xntimerq_init(q) xntlist_init(q)
173 #define xntimerq_destroy(q) do { } while (0)
174 #define xntimerq_head(q) xntlist_head(q)
175 #define xntimerq_second(q,h) xntlist_second((q),(h))
176 #define xntimerq_insert(q,h) xntlist_insert((q),(h))
177 #define xntimerq_remove(q, h) xntlist_remove((q),(h))
178 
179 typedef struct {} xntimerq_it_t;
180 
181 #define xntimerq_it_begin(q,i) ((void) (i), xntlist_head(q))
182 #define xntimerq_it_next(q,i,h) ((void) (i), xntlist_next((q),(h)))
183 
184 #endif /* CONFIG_XENO_OPT_TIMER_LIST */
185 
186 struct xnsched;
187 
188 typedef struct xntimer {
189 
190  xntimerh_t aplink; /* Link in aperiodic timers list. */
191 
192 #define aplink2timer(ln) container_of(ln, xntimer_t, aplink)
193 
194 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
195  xntbase_t *base; /* Time base. */
196 
197  xntlholder_t plink; /* Link in periodic timers wheel. */
198 
199 #define plink2timer(ln) container_of(ln, xntimer_t, plink)
200 #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */
201 
202  xnholder_t adjlink;
203 
204 #define adjlink2timer(ln) container_of(ln, xntimer_t, adjlink)
205 
206  xnflags_t status; /* !< Timer status. */
207 
208  xnticks_t interval; /* !< Periodic interval (in ticks, 0 == one shot). */
209 
210  xnticks_t pexpect; /* !< Date of next periodic release point (raw ticks). */
211 
212  struct xnsched *sched; /* !< Sched structure to which the timer is
213  attached. */
214 
215  void (*handler)(struct xntimer *timer); /* !< Timeout handler. */
216 
217 #ifdef CONFIG_XENO_OPT_STATS
218  char name[XNOBJECT_NAME_LEN]; /* !< Timer name to be displayed. */
219 
220  const char *handler_name; /* !< Handler name to be displayed. */
221 
222  xnholder_t tblink; /* !< Timer holder in timebase. */
223 
224 #define tblink2timer(ln) container_of(ln, xntimer_t, tblink)
225 #endif /* CONFIG_XENO_OPT_STATS */
226 
227  xnstat_counter_t scheduled; /* !< Number of timer schedules. */
228 
229  xnstat_counter_t fired; /* !< Number of timer events. */
230 
231  XNARCH_DECL_DISPLAY_CONTEXT();
232 
233 } xntimer_t;
234 
235 typedef struct xntimed_slave {
236 
237  xntbase_t base; /* !< Cascaded time base. */
238 
239  struct percpu_cascade {
240  xntimer_t timer; /* !< Cascading timer in master time base. */
241  xnqueue_t wheel[XNTIMER_WHEELSIZE];
242  } cascade[XNARCH_NR_CPUS];
243 
244 #define timer2slave(t) \
245  ((xntslave_t *)(((char *)t) - offsetof(xntslave_t, cascade[xnsched_cpu((t)->sched)].timer)))
246 #define base2slave(b) \
247  ((xntslave_t *)(((char *)b) - offsetof(xntslave_t, base)))
248 
249 } xntslave_t;
250 
251 #ifdef CONFIG_SMP
252 #define xntimer_sched(t) ((t)->sched)
253 #else /* !CONFIG_SMP */
254 #define xntimer_sched(t) xnpod_current_sched()
255 #endif /* !CONFIG_SMP */
256 #define xntimer_interval(t) ((t)->interval)
257 #define xntimer_pexpect(t) ((t)->pexpect)
258 #define xntimer_pexpect_forward(t,delta) ((t)->pexpect += delta)
259 
260 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
261 #define xntimer_base(t) ((t)->base)
262 #define xntimer_set_priority(t,p) \
263  ({ \
264  xntimer_t *_t = (t); \
265  unsigned prio = (p); \
266  xntimerh_prio(&(_t)->aplink) = prio; \
267  xntlholder_prio(&(_t)->plink) = prio; \
268  })
269 #else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
270 #define xntimer_base(t) (&nktbase)
271 #define xntimer_set_priority(t,p) \
272  do { xntimerh_prio(&(t)->aplink) = (p); } while(0)
273 #endif /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
274 
275 static inline int xntimer_active_p (xntimer_t *timer)
276 {
277  return timer->sched != NULL;
278 }
279 
280 static inline int xntimer_running_p(xntimer_t *timer)
281 {
282  return !testbits(timer->status,XNTIMER_DEQUEUED);
283 }
284 
285 static inline int xntimer_reload_p(xntimer_t *timer)
286 {
287  return testbits(timer->status,
288  XNTIMER_PERIODIC|XNTIMER_DEQUEUED|XNTIMER_KILLED) ==
289  (XNTIMER_PERIODIC|XNTIMER_DEQUEUED);
290 }
291 
292 #ifdef __cplusplus
293 extern "C" {
294 #endif
295 
296 extern xntbops_t nktimer_ops_aperiodic,
297  nktimer_ops_periodic;
298 
299 #ifdef CONFIG_XENO_OPT_STATS
300 #define xntimer_init(timer, base, handler) \
301  do { \
302  __xntimer_init(timer, base, handler); \
303  (timer)->handler_name = #handler; \
304  } while (0)
305 #else /* !CONFIG_XENO_OPT_STATS */
306 #define xntimer_init __xntimer_init
307 #endif /* !CONFIG_XENO_OPT_STATS */
308 
309 #define xntimer_init_noblock(timer, base, handler) \
310  do { \
311  xntimer_init(timer, base, handler); \
312  (timer)->status |= XNTIMER_NOBLCK; \
313  } while(0)
314 
315 void __xntimer_init(struct xntimer *timer,
316  struct xntbase *base,
317  void (*handler)(struct xntimer *timer));
318 
319 void xntimer_destroy(xntimer_t *timer);
320 
321 static inline void xntimer_set_name(xntimer_t *timer, const char *name)
322 {
323 #ifdef CONFIG_XENO_OPT_STATS
324  strncpy(timer->name, name, sizeof(timer->name));
325 #endif /* CONFIG_XENO_OPT_STATS */
326 }
327 
328 void xntimer_next_local_shot(struct xnsched *sched);
329 
334 #if defined(CONFIG_XENO_OPT_TIMING_PERIODIC) || defined(DOXYGEN_CPP)
335 
388 static inline int xntimer_start(xntimer_t *timer,
389  xnticks_t value, xnticks_t interval,
390  xntmode_t mode)
391 {
392  return timer->base->ops->start_timer(timer, value, interval, mode);
393 }
394 
420 static inline void xntimer_stop(xntimer_t *timer)
421 {
422  /* Careful: the do_timer_stop() helper is expected to preserve
423  the date field of the stopped timer, so that subsequent
424  calls to xntimer_get_timeout() would still work on such
425  timer as expected. */
426  if (!testbits(timer->status,XNTIMER_DEQUEUED))
427  timer->base->ops->stop_timer(timer);
428 }
429 
462 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
463 {
464  if (!xntimer_running_p(timer))
465  return XN_INFINITE;
466 
467  return timer->base->ops->get_timer_date(timer);
468 }
469 
504 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
505 {
506  if (!xntimer_running_p(timer))
507  return XN_INFINITE;
508 
509  return timer->base->ops->get_timer_timeout(timer);
510 }
511 
512 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
513 {
514  return timer->base->ops->get_timer_timeout(timer);
515 }
516 
548 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
549 {
550  return timer->base->ops->get_timer_interval(timer);
551 }
552 
553 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
554 {
555  return timer->base->ops->get_timer_raw_expiry(timer);
556 }
557 
558 void xntslave_init(xntslave_t *slave);
559 
560 void xntslave_destroy(xntslave_t *slave);
561 
562 void xntslave_update(xntslave_t *slave,
563  xnticks_t interval);
564 
565 void xntslave_start(xntslave_t *slave,
566  xnticks_t start,
567  xnticks_t interval);
568 
569 void xntslave_stop(xntslave_t *slave);
570 
571 void xntslave_adjust(xntslave_t *slave, xnsticks_t delta);
572 
573 #else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
574 
575 int xntimer_start_aperiodic(xntimer_t *timer,
576  xnticks_t value,
577  xnticks_t interval,
578  xntmode_t mode);
579 
580 void xntimer_stop_aperiodic(xntimer_t *timer);
581 
582 xnticks_t xntimer_get_date_aperiodic(xntimer_t *timer);
583 
584 xnticks_t xntimer_get_timeout_aperiodic(xntimer_t *timer);
585 
586 xnticks_t xntimer_get_interval_aperiodic(xntimer_t *timer);
587 
588 xnticks_t xntimer_get_raw_expiry_aperiodic(xntimer_t *timer);
589 
590 static inline int xntimer_start(xntimer_t *timer,
591  xnticks_t value, xnticks_t interval,
592  xntmode_t mode)
593 {
594  return xntimer_start_aperiodic(timer, value, interval, mode);
595 }
596 
597 static inline void xntimer_stop(xntimer_t *timer)
598 {
599  if (!testbits(timer->status,XNTIMER_DEQUEUED))
600  xntimer_stop_aperiodic(timer);
601 }
602 
603 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
604 {
605  if (!xntimer_running_p(timer))
606  return XN_INFINITE;
607 
608  return xntimer_get_date_aperiodic(timer);
609 }
610 
611 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
612 {
613  if (!xntimer_running_p(timer))
614  return XN_INFINITE;
615 
616  return xntimer_get_timeout_aperiodic(timer);
617 }
618 
619 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
620 {
621  return xntimer_get_timeout_aperiodic(timer);
622 }
623 
624 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
625 {
626  return xntimer_get_interval_aperiodic(timer);
627 }
628 
629 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
630 {
631  return xntimerh_date(&timer->aplink);
632 }
633 
634 #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */
635 
638 void xntimer_init_proc(void);
639 
640 void xntimer_cleanup_proc(void);
641 
642 unsigned long xntimer_get_overruns(xntimer_t *timer, xnticks_t now);
643 
644 void xntimer_freeze(void);
645 
646 void xntimer_tick_aperiodic(void);
647 
648 void xntimer_tick_periodic(xntimer_t *timer);
649 
650 void xntimer_tick_periodic_inner(xntslave_t *slave);
651 
652 void xntimer_adjust_all_aperiodic(xnsticks_t delta);
653 
654 #ifdef CONFIG_SMP
655 int xntimer_migrate(xntimer_t *timer,
656  struct xnsched *sched);
657 #else /* ! CONFIG_SMP */
658 #define xntimer_migrate(timer, sched) do { } while(0)
659 #endif /* CONFIG_SMP */
660 
661 #define xntimer_set_sched(timer, sched) xntimer_migrate(timer, sched)
662 
663 char *xntimer_format_time(xnticks_t value, int periodic,
664  char *buf, size_t bufsz);
665 #ifdef __cplusplus
666 }
667 #endif
668 
669 #endif /* __KERNEL__ || __XENO_SIM__ */
670 
671 #endif /* !_XENO_NUCLEUS_TIMER_H */
void xntimer_tick_aperiodic(void)
Process a timer tick for the aperiodic master time base.
Definition: timer.c:339
void xntimer_tick_periodic(xntimer_t *timer)
Process a timer tick for a slave periodic time base.
Definition: timer.c:606
static xnticks_t xntimer_get_interval(xntimer_t *timer)
Return the timer interval value.
Definition: timer.h:548
void xntimer_destroy(xntimer_t *timer)
Release a timer object.
Definition: timer.c:908
static xnticks_t xntimer_get_date(xntimer_t *timer)
Return the absolute expiration date.
Definition: timer.h:462
Scheduling information structure.
Definition: sched.h:66
static void xntimer_stop(xntimer_t *timer)
Disarm a timer.
Definition: timer.h:420
void xntimer_freeze(void)
Freeze all timers (from every time bases).
Definition: timer.c:1042
static int xntimer_start(xntimer_t *timer, xnticks_t value, xnticks_t interval, xntmode_t mode)
Arm a timer.
Definition: timer.h:388
unsigned long xntimer_get_overruns(xntimer_t *timer, xnticks_t now)
Get the count of overruns for the last tick.
Definition: timer.c:1007
static xnticks_t xntimer_get_timeout(xntimer_t *timer)
Return the relative expiration date.
Definition: timer.h:504