Xenomai  3.0-rc3
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/ancillaries.h>
27 
32 #define XN_INFINITE ((xnticks_t)0)
33 #define XN_NONBLOCK ((xnticks_t)-1)
34 
35 /* Timer modes */
36 typedef enum xntmode {
37  XN_RELATIVE,
38  XN_ABSOLUTE,
39  XN_REALTIME
40 } xntmode_t;
41 
42 /* Timer status */
43 #define XNTIMER_DEQUEUED 0x00000001
44 #define XNTIMER_KILLED 0x00000002
45 #define XNTIMER_PERIODIC 0x00000004
46 #define XNTIMER_REALTIME 0x00000008
47 #define XNTIMER_FIRED 0x00000010
48 #define XNTIMER_NOBLCK 0x00000020
49 #define XNTIMER_RUNNING 0x00000040
50 #define XNTIMER_KGRAVITY 0x00000080
51 #define XNTIMER_UGRAVITY 0x00000100
52 #define XNTIMER_IGRAVITY 0 /* most conservative */
53 
54 #define XNTIMER_GRAVITY_MASK (XNTIMER_KGRAVITY|XNTIMER_UGRAVITY)
55 #define XNTIMER_INIT_MASK (XNTIMER_GRAVITY_MASK|XNTIMER_NOBLCK)
56 
57 /* These flags are available to the real-time interfaces */
58 #define XNTIMER_SPARE0 0x01000000
59 #define XNTIMER_SPARE1 0x02000000
60 #define XNTIMER_SPARE2 0x04000000
61 #define XNTIMER_SPARE3 0x08000000
62 #define XNTIMER_SPARE4 0x10000000
63 #define XNTIMER_SPARE5 0x20000000
64 #define XNTIMER_SPARE6 0x40000000
65 #define XNTIMER_SPARE7 0x80000000
66 
67 /* Timer priorities */
68 #define XNTIMER_LOPRIO (-999999999)
69 #define XNTIMER_STDPRIO 0
70 #define XNTIMER_HIPRIO 999999999
71 
72 struct xntlholder {
73  struct list_head link;
74  xnticks_t key;
75  int prio;
76 };
77 
78 #define xntlholder_date(h) ((h)->key)
79 #define xntlholder_prio(h) ((h)->prio)
80 #define xntlist_init(q) INIT_LIST_HEAD(q)
81 #define xntlist_empty(q) list_empty(q)
82 #define xntlist_head(q) \
83  ({ \
84  struct xntlholder *h = list_empty(q) ? NULL : \
85  list_first_entry(q, struct xntlholder, link); \
86  h; \
87  })
88 
89 #define xntlist_next(q, h) \
90  ({ \
91  struct xntlholder *_h = list_is_last(&h->link, q) ? NULL : \
92  list_entry(h->link.next, struct xntlholder, link); \
93  _h; \
94  })
95 
96 static inline void xntlist_insert(struct list_head *q, struct xntlholder *holder)
97 {
98  struct xntlholder *p;
99 
100  if (list_empty(q)) {
101  list_add(&holder->link, q);
102  return;
103  }
104 
105  /*
106  * Insert the new timer at the proper place in the single
107  * queue. O(N) here, but this is the price for the increased
108  * flexibility...
109  */
110  list_for_each_entry_reverse(p, q, link) {
111  if ((xnsticks_t) (holder->key - p->key) > 0 ||
112  (holder->key == p->key && holder->prio <= p->prio))
113  break;
114  }
115 
116  list_add(&holder->link, &p->link);
117 }
118 
119 #define xntlist_remove(q, h) \
120  do { \
121  (void)(q); \
122  list_del(&(h)->link); \
123  } while (0)
124 
125 #if defined(CONFIG_XENO_OPT_TIMER_HEAP)
126 
127 #include <cobalt/kernel/bheap.h>
128 
129 typedef bheaph_t xntimerh_t;
130 
131 #define xntimerh_date(h) bheaph_key(h)
132 #define xntimerh_prio(h) bheaph_prio(h)
133 #define xntimerh_init(h) bheaph_init(h)
134 
135 typedef DECLARE_BHEAP_CONTAINER(xntimerq_t, CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY);
136 
137 #define xntimerq_init(q) bheap_init((q), CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY)
138 #define xntimerq_destroy(q) bheap_destroy(q)
139 #define xntimerq_empty(q) bheap_empty(q)
140 #define xntimerq_head(q) bheap_gethead(q)
141 #define xntimerq_insert(q, h) bheap_insert((q),(h))
142 #define xntimerq_remove(q, h) bheap_delete((q),(h))
143 
144 typedef struct {} xntimerq_it_t;
145 
146 #define xntimerq_it_begin(q, i) ((void) (i), bheap_gethead(q))
147 #define xntimerq_it_next(q, i, h) ((void) (i), bheap_next((q),(h)))
148 
149 #else /* CONFIG_XENO_OPT_TIMER_LIST */
150 
151 typedef struct xntlholder xntimerh_t;
152 
153 #define xntimerh_date(h) xntlholder_date(h)
154 #define xntimerh_prio(h) xntlholder_prio(h)
155 #define xntimerh_init(h) do { } while (0)
156 
157 typedef struct list_head xntimerq_t;
158 
159 #define xntimerq_init(q) xntlist_init(q)
160 #define xntimerq_destroy(q) do { } while (0)
161 #define xntimerq_empty(q) xntlist_empty(q)
162 #define xntimerq_head(q) xntlist_head(q)
163 #define xntimerq_insert(q,h) xntlist_insert((q),(h))
164 #define xntimerq_remove(q, h) xntlist_remove((q),(h))
165 
166 typedef struct { } xntimerq_it_t;
167 
168 #define xntimerq_it_begin(q,i) ((void) (i), xntlist_head(q))
169 #define xntimerq_it_next(q,i,h) ((void) (i), xntlist_next((q),(h)))
170 
171 #endif /* CONFIG_XENO_OPT_TIMER_LIST */
172 
173 struct xnsched;
174 
175 struct xntimerdata {
176  xntimerq_t q;
177 };
178 
179 static inline struct xntimerdata *
180 xnclock_percpu_timerdata(struct xnclock *clock, int cpu)
181 {
182  return per_cpu_ptr(clock->timerdata, cpu);
183 }
184 
185 static inline struct xntimerdata *
186 xnclock_this_timerdata(struct xnclock *clock)
187 {
188  return __this_cpu_ptr(clock->timerdata);
189 }
190 
191 struct xntimer {
192 #ifdef CONFIG_XENO_OPT_EXTCLOCK
193  struct xnclock *clock;
194 #endif
195 
196  xntimerh_t aplink;
197  struct list_head adjlink;
199  unsigned long status;
201  xnticks_t interval;
203  xnticks_t interval_ns;
205  xnticks_t periodic_ticks;
207  xnticks_t start_date;
209  xnticks_t pexpect_ticks;
211  struct xnsched *sched;
213  void (*handler)(struct xntimer *timer);
214 #ifdef CONFIG_XENO_OPT_STATS
215 #ifdef CONFIG_XENO_OPT_EXTCLOCK
216  struct xnclock *tracker;
217 #endif
218 
219  char name[XNOBJECT_NAME_LEN];
221  struct list_head next_stat;
223  xnstat_counter_t scheduled;
225  xnstat_counter_t fired;
226 #endif /* CONFIG_XENO_OPT_STATS */
227 };
228 
229 #ifdef CONFIG_XENO_OPT_EXTCLOCK
230 
231 static inline struct xnclock *xntimer_clock(struct xntimer *timer)
232 {
233  return timer->clock;
234 }
235 
236 #else /* !CONFIG_XENO_OPT_EXTCLOCK */
237 
238 static inline struct xnclock *xntimer_clock(struct xntimer *timer)
239 {
240  return &nkclock;
241 }
242 
243 #endif /* !CONFIG_XENO_OPT_EXTCLOCK */
244 
245 #ifdef CONFIG_SMP
246 static inline struct xnsched *xntimer_sched(struct xntimer *timer)
247 {
248  return timer->sched;
249 }
250 #else /* !CONFIG_SMP */
251 #define xntimer_sched(t) xnsched_current()
252 #endif /* !CONFIG_SMP */
253 
254 #define xntimer_percpu_queue(__timer) \
255  ({ \
256  struct xntimerdata *tmd; \
257  int cpu = xnsched_cpu((__timer)->sched); \
258  tmd = xnclock_percpu_timerdata(xntimer_clock(__timer), cpu); \
259  &tmd->q; \
260  })
261 
262 static inline xntimerq_t *xntimer_this_queue(struct xntimer *timer)
263 {
264  struct xntimerdata *tmd;
265 
266  tmd = xnclock_this_timerdata(xntimer_clock(timer));
267 
268  return &tmd->q;
269 }
270 
271 static inline unsigned long xntimer_gravity(struct xntimer *timer)
272 {
273  struct xnclock *clock = xntimer_clock(timer);
274 
275  if (timer->status & XNTIMER_KGRAVITY)
276  return clock->gravity.kernel;
277 
278  if (timer->status & XNTIMER_UGRAVITY)
279  return clock->gravity.user;
280 
281  return clock->gravity.irq;
282 }
283 
284 static inline void xntimer_update_date(struct xntimer *timer)
285 {
286  xntimerh_date(&timer->aplink) = timer->start_date
287  + xnclock_ns_to_ticks(xntimer_clock(timer),
288  timer->periodic_ticks * timer->interval_ns)
289  - xntimer_gravity(timer);
290 }
291 
292 static inline xnticks_t xntimer_pexpect(struct xntimer *timer)
293 {
294  return timer->start_date +
295  xnclock_ns_to_ticks(xntimer_clock(timer),
296  timer->pexpect_ticks * timer->interval_ns);
297 }
298 
299 static inline void xntimer_set_priority(struct xntimer *timer,
300  int prio)
301 {
302  xntimerh_prio(&timer->aplink) = prio;
303 }
304 
305 static inline int xntimer_active_p(struct xntimer *timer)
306 {
307  return timer->sched != NULL;
308 }
309 
310 static inline int xntimer_running_p(struct xntimer *timer)
311 {
312  return (timer->status & XNTIMER_RUNNING) != 0;
313 }
314 
315 static inline int xntimer_fired_p(struct xntimer *timer)
316 {
317  return (timer->status & XNTIMER_FIRED) != 0;
318 }
319 
320 static inline int xntimer_periodic_p(struct xntimer *timer)
321 {
322  return (timer->status & XNTIMER_PERIODIC) != 0;
323 }
324 
325 void __xntimer_init(struct xntimer *timer,
326  struct xnclock *clock,
327  void (*handler)(struct xntimer *timer),
328  struct xnsched *sched,
329  int flags);
330 
331 void xntimer_set_gravity(struct xntimer *timer,
332  int gravity);
333 
334 #ifdef CONFIG_XENO_OPT_STATS
335 
336 #define xntimer_init(__timer, __clock, __handler, __sched, __flags) \
337 do { \
338  __xntimer_init(__timer, __clock, __handler, __sched, __flags); \
339  xntimer_set_name(__timer, #__handler); \
340 } while (0)
341 
342 static inline void xntimer_reset_stats(struct xntimer *timer)
343 {
344  xnstat_counter_set(&timer->scheduled, 0);
345  xnstat_counter_set(&timer->fired, 0);
346 }
347 
348 static inline void xntimer_account_scheduled(struct xntimer *timer)
349 {
350  xnstat_counter_inc(&timer->scheduled);
351 }
352 
353 static inline void xntimer_account_fired(struct xntimer *timer)
354 {
355  xnstat_counter_inc(&timer->fired);
356 }
357 
358 static inline void xntimer_set_name(struct xntimer *timer, const char *name)
359 {
360  knamecpy(timer->name, name);
361 }
362 
363 #else /* !CONFIG_XENO_OPT_STATS */
364 
365 #define xntimer_init __xntimer_init
366 
367 static inline void xntimer_reset_stats(struct xntimer *timer) { }
368 
369 static inline void xntimer_account_scheduled(struct xntimer *timer) { }
370 
371 static inline void xntimer_account_fired(struct xntimer *timer) { }
372 
373 static inline void xntimer_set_name(struct xntimer *timer, const char *name) { }
374 
375 #endif /* !CONFIG_XENO_OPT_STATS */
376 
377 #if defined(CONFIG_XENO_OPT_EXTCLOCK) && defined(CONFIG_XENO_OPT_STATS)
378 void xntimer_switch_tracking(struct xntimer *timer,
379  struct xnclock *newclock);
380 #else
381 static inline
382 void xntimer_switch_tracking(struct xntimer *timer,
383  struct xnclock *newclock) { }
384 #endif
385 
386 void xntimer_destroy(struct xntimer *timer);
387 
403 static inline xnticks_t xntimer_interval(struct xntimer *timer)
404 {
405  return timer->interval_ns;
406 }
407 
408 static inline xnticks_t xntimer_expiry(struct xntimer *timer)
409 {
410  /* Real expiry date in ticks without anticipation (no gravity) */
411  return xntimerh_date(&timer->aplink) + xntimer_gravity(timer);
412 }
413 
414 int xntimer_start(struct xntimer *timer,
415  xnticks_t value,
416  xnticks_t interval,
417  xntmode_t mode);
418 
419 void __xntimer_stop(struct xntimer *timer);
420 
421 xnticks_t xntimer_get_date(struct xntimer *timer);
422 
423 xnticks_t xntimer_get_timeout(struct xntimer *timer);
424 
425 xnticks_t xntimer_get_interval(struct xntimer *timer);
426 
427 int xntimer_heading_p(struct xntimer *timer);
428 
429 static inline void xntimer_stop(struct xntimer *timer)
430 {
431  if (timer->status & XNTIMER_RUNNING)
432  __xntimer_stop(timer);
433 }
434 
435 static inline xnticks_t xntimer_get_timeout_stopped(struct xntimer *timer)
436 {
437  return xntimer_get_timeout(timer);
438 }
439 
440 static inline void xntimer_enqueue(struct xntimer *timer,
441  xntimerq_t *q)
442 {
443  xntimerq_insert(q, &timer->aplink);
444  timer->status &= ~XNTIMER_DEQUEUED;
445  xntimer_account_scheduled(timer);
446 }
447 
448 static inline void xntimer_dequeue(struct xntimer *timer,
449  xntimerq_t *q)
450 {
451  xntimerq_remove(q, &timer->aplink);
452  timer->status |= XNTIMER_DEQUEUED;
453 }
454 
457 unsigned long long xntimer_get_overruns(struct xntimer *timer, xnticks_t now);
458 
459 #ifdef CONFIG_SMP
460 
461 void __xntimer_migrate(struct xntimer *timer, struct xnsched *sched);
462 
463 static inline
464 void xntimer_migrate(struct xntimer *timer, struct xnsched *sched)
465 { /* nklocked, IRQs off */
466  if (timer->sched != sched)
467  __xntimer_migrate(timer, sched);
468 }
469 
470 int xntimer_setup_ipi(void);
471 
472 void xntimer_release_ipi(void);
473 
474 #else /* ! CONFIG_SMP */
475 
476 static inline void xntimer_migrate(struct xntimer *timer,
477  struct xnsched *sched)
478 { }
479 
480 static inline int xntimer_setup_ipi(void)
481 {
482  return 0;
483 }
484 
485 static inline void xntimer_release_ipi(void) { }
486 
487 #endif /* CONFIG_SMP */
488 
489 static inline void xntimer_set_sched(struct xntimer *timer,
490  struct xnsched *sched)
491 {
492  xntimer_migrate(timer, sched);
493 }
494 
495 char *xntimer_format_time(xnticks_t ns,
496  char *buf, size_t bufsz);
497 
498 int xntimer_grab_hardware(void);
499 
500 void xntimer_release_hardware(void);
501 
504 #endif /* !_COBALT_KERNEL_TIMER_H */
xnticks_t xntimer_get_timeout(struct xntimer *timer)
Return the relative expiration date.
Definition: timer.c:266
xnticks_t xntimer_get_date(struct xntimer *timer)
Return the absolute expiration date.
Definition: timer.c:239
void __xntimer_migrate(struct xntimer *timer, struct xnsched *sched)
Migrate a timer.
Definition: timer.c:464
Scheduling information structure.
Definition: sched.h:58
int xntimer_start(struct xntimer *timer, xnticks_t value, xnticks_t interval, xntmode_t mode)
Arm a timer.
Definition: timer.c:101
void xntimer_destroy(struct xntimer *timer)
Release a timer object.
Definition: timer.c:430
unsigned long long xntimer_get_overruns(struct xntimer *timer, xnticks_t now)
Get the count of overruns for the last tick.
Definition: timer.c:519
void xntimer_release_hardware(void)
Release hardware timers.
Definition: timer.c:822
static xnticks_t xntimer_interval(struct xntimer *timer)
Return the timer interval value.
Definition: timer.h:403
static void xntimer_stop(struct xntimer *timer)
Disarm a timer.
Definition: timer.h:429
int xntimer_grab_hardware(void)
Grab the hardware timer on all real-time CPUs.
Definition: timer.c:725