Xenomai API  2.5.6.1
include/nucleus/timer.h
Go to the documentation of this file.
00001 
00023 #ifndef _XENO_NUCLEUS_TIMER_H
00024 #define _XENO_NUCLEUS_TIMER_H
00025 
00026 #include <nucleus/timebase.h>
00027 #include <nucleus/stat.h>
00028 
00029 #if defined(__KERNEL__) || defined(__XENO_SIM__)
00030 
00031 #ifndef CONFIG_XENO_OPT_DEBUG_TIMERS
00032 #define CONFIG_XENO_OPT_DEBUG_TIMERS  0
00033 #endif
00034 
00035 #define XNTIMER_WHEELSIZE 64
00036 #define XNTIMER_WHEELMASK (XNTIMER_WHEELSIZE - 1)
00037 
00038 /* Timer status */
00039 #define XNTIMER_DEQUEUED  0x00000001
00040 #define XNTIMER_KILLED    0x00000002
00041 #define XNTIMER_PERIODIC  0x00000004
00042 #define XNTIMER_REALTIME  0x00000008
00043 #define XNTIMER_FIRED     0x00000010
00044 #define XNTIMER_NOBLCK    0x00000020
00045 
00046 /* These flags are available to the real-time interfaces */
00047 #define XNTIMER_SPARE0  0x01000000
00048 #define XNTIMER_SPARE1  0x02000000
00049 #define XNTIMER_SPARE2  0x04000000
00050 #define XNTIMER_SPARE3  0x08000000
00051 #define XNTIMER_SPARE4  0x10000000
00052 #define XNTIMER_SPARE5  0x20000000
00053 #define XNTIMER_SPARE6  0x40000000
00054 #define XNTIMER_SPARE7  0x80000000
00055 
00056 /* Timer priorities */
00057 #define XNTIMER_LOPRIO  (-999999999)
00058 #define XNTIMER_STDPRIO 0
00059 #define XNTIMER_HIPRIO  999999999
00060 
00061 #define XNTIMER_KEEPER_ID 0
00062 
00063 typedef struct {
00064         xnholder_t link;
00065         xnticks_t key;
00066         int prio;
00067 
00068 #define link2tlholder(ln)       container_of(ln, xntlholder_t, link)
00069 
00070 } xntlholder_t;
00071 
00072 #define xntlholder_date(h)      ((h)->key)
00073 #define xntlholder_prio(h)      ((h)->prio)
00074 #define xntlholder_init(h)      inith(&(h)->link)
00075 #define xntlist_init(q) initq(q)
00076 #define xntlist_head(q)                 \
00077         ({ xnholder_t *_h = getheadq(q);        \
00078                 !_h ? NULL : link2tlholder(_h); \
00079         })
00080 
00081 #define xntlist_next(q, h) \
00082         ({ xnholder_t *_h = nextq(q, &(h)->link);       \
00083                 !_h ? NULL : link2tlholder(_h);         \
00084         })
00085 
00086 static inline void xntlist_insert(xnqueue_t *q, xntlholder_t *holder)
00087 {
00088         xnholder_t *p;
00089 
00090         /* Insert the new timer at the proper place in the single
00091            queue managed when running in aperiodic mode. O(N) here,
00092            but users of the aperiodic mode need to pay a price for the
00093            increased flexibility... */
00094 
00095         for (p = q->head.last; p != &q->head; p = p->last)
00096                 if ((xnsticks_t) (holder->key - link2tlholder(p)->key) > 0 ||
00097                     (holder->key == link2tlholder(p)->key &&
00098                      holder->prio <= link2tlholder(p)->prio))
00099                         break;
00100 
00101         insertq(q,p->next,&holder->link);
00102 }
00103 
00104 #define xntlist_remove(q, h)  removeq((q),&(h)->link)
00105 
00106 #if defined(CONFIG_XENO_OPT_TIMER_HEAP)
00107 
00108 #include <nucleus/bheap.h>
00109 
00110 typedef bheaph_t xntimerh_t;
00111 
00112 #define xntimerh_date(h)          bheaph_key(h)
00113 #define xntimerh_prio(h)          bheaph_prio(h)
00114 #define xntimerh_init(h)          bheaph_init(h)
00115 
00116 typedef DECLARE_BHEAP_CONTAINER(xntimerq_t, CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY);
00117 
00118 #define xntimerq_init(q)          bheap_init((q), CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY)
00119 #define xntimerq_destroy(q)       bheap_destroy(q)
00120 #define xntimerq_head(q)          bheap_gethead(q)
00121 #define xntimerq_insert(q, h)     bheap_insert((q),(h))
00122 #define xntimerq_remove(q, h)     bheap_delete((q),(h))
00123 
00124 typedef struct {} xntimerq_it_t;
00125 
00126 #define xntimerq_it_begin(q, i)   ((void) (i), bheap_gethead(q))
00127 #define xntimerq_it_next(q, i, h) ((void) (i), bheap_next((q),(h)))
00128 
00129 #elif defined(CONFIG_XENO_OPT_TIMER_WHEEL)
00130 
00131 typedef xntlholder_t xntimerh_t;
00132 
00133 #define xntimerh_date(h)       xntlholder_date(h)
00134 #define xntimerh_prio(h)       xntlholder_prio(h)
00135 #define xntimerh_init(h)       xntlholder_init(h)
00136 
00137 typedef struct xntimerq {
00138         unsigned date_shift;
00139         unsigned long long next_shot;
00140         unsigned long long shot_wrap;
00141         xnqueue_t bucket[XNTIMER_WHEELSIZE];
00142 } xntimerq_t;
00143 
00144 typedef struct xntimerq_it {
00145         unsigned bucket;
00146 } xntimerq_it_t;
00147 
00148 static inline void xntimerq_init(xntimerq_t *q)
00149 {
00150         unsigned long long step_tsc;
00151         unsigned i;
00152 
00153         step_tsc = xnarch_ns_to_tsc(CONFIG_XENO_OPT_TIMER_WHEEL_STEP);
00154         /* q->date_shift = fls(step_tsc); */
00155         for (q->date_shift = 0; (1 << q->date_shift) < step_tsc; q->date_shift++)
00156                 ;
00157         q->next_shot = q->shot_wrap = ((~0ULL) >> q->date_shift) + 1;
00158         for (i = 0; i < sizeof(q->bucket)/sizeof(xnqueue_t); i++)
00159                 xntlist_init(&q->bucket[i]);
00160 }
00161 
00162 #define xntimerq_destroy(q)    do { } while (0)
00163 
00164 static inline xntlholder_t *xntimerq_head(xntimerq_t *q)
00165 {
00166         unsigned bucket = ((unsigned) q->next_shot) & XNTIMER_WHEELMASK;
00167         xntlholder_t *result;
00168         unsigned i;
00169 
00170         if (q->next_shot == q->shot_wrap)
00171                 return NULL;
00172 
00173         result = xntlist_head(&q->bucket[bucket]);
00174 
00175         if (result && (xntlholder_date(result) >> q->date_shift) == q->next_shot)
00176                 return result;
00177 
00178         /* We could not find the next timer in the first bucket, iterate over
00179            the other buckets. */
00180         for (i = (bucket + 1) & XNTIMER_WHEELMASK ;
00181              i != bucket; i = (i + 1) & XNTIMER_WHEELMASK) {
00182                 xntlholder_t *candidate = xntlist_head(&q->bucket[i]);
00183 
00184                 if(++q->next_shot == q->shot_wrap)
00185                         q->next_shot = 0;
00186 
00187                 if (!candidate)
00188                         continue;
00189 
00190                 if ((xntlholder_date(candidate) >> q->date_shift) == q->next_shot)
00191                         return candidate;
00192 
00193                 if (!result || (xnsticks_t) (xntlholder_date(candidate)
00194                                              - xntlholder_date(result)) < 0)
00195                         result = candidate;
00196         }
00197 
00198         if (result)
00199                 q->next_shot = (xntlholder_date(result) >> q->date_shift);
00200         else
00201                 q->next_shot = q->shot_wrap;
00202         return result;
00203 }
00204 
00205 static inline void xntimerq_insert(xntimerq_t *q, xntimerh_t *h)
00206 {
00207         unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
00208         unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
00209 
00210         if ((long long) (shifted_date - q->next_shot) < 0)
00211                 q->next_shot = shifted_date;
00212         xntlist_insert(&q->bucket[bucket], h);
00213 }
00214 
00215 static inline void xntimerq_remove(xntimerq_t *q, xntimerh_t *h)
00216 {
00217         unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
00218         unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
00219 
00220         xntlist_remove(&q->bucket[bucket], h);
00221         /* Do not attempt to update q->next_shot, xntimerq_head will recover. */
00222 }
00223 
00224 static inline xntimerh_t *xntimerq_it_begin(xntimerq_t *q, xntimerq_it_t *it)
00225 {
00226         xntimerh_t *holder = NULL;
00227 
00228         for (it->bucket = 0; it->bucket < XNTIMER_WHEELSIZE; it->bucket++)
00229                 if ((holder = xntlist_head(&q->bucket[it->bucket])))
00230                         break;
00231 
00232         return holder;
00233 }
00234 
00235 static inline xntimerh_t *
00236 xntimerq_it_next(xntimerq_t *q, xntimerq_it_t *it, xntimerh_t *holder)
00237 {
00238         xntimerh_t *next = xntlist_next(&q->bucket[it->bucket], holder);
00239 
00240         if (!next)
00241                 for(it->bucket++; it->bucket < XNTIMER_WHEELSIZE; it->bucket++)
00242                         if ((next = xntlist_head(&q->bucket[it->bucket])))
00243                                 break;
00244 
00245         return next;
00246 }
00247 
00248 #else /* CONFIG_XENO_OPT_TIMER_LIST */
00249 
00250 typedef xntlholder_t xntimerh_t;
00251 
00252 #define xntimerh_date(h)        xntlholder_date(h)
00253 #define xntimerh_prio(h)        xntlholder_prio(h)
00254 #define xntimerh_init(h)        xntlholder_init(h)
00255 
00256 typedef xnqueue_t xntimerq_t;
00257 
00258 #define xntimerq_init(q)        xntlist_init(q)
00259 #define xntimerq_destroy(q)     do { } while (0)
00260 #define xntimerq_head(q)        xntlist_head(q)
00261 #define xntimerq_insert(q,h)    xntlist_insert((q),(h))
00262 #define xntimerq_remove(q, h)   xntlist_remove((q),(h))
00263 
00264 typedef struct {} xntimerq_it_t;
00265 
00266 #define xntimerq_it_begin(q,i)  ((void) (i), xntlist_head(q))
00267 #define xntimerq_it_next(q,i,h) ((void) (i), xntlist_next((q),(h)))
00268 
00269 #endif /* CONFIG_XENO_OPT_TIMER_LIST */
00270 
00271 struct xnsched;
00272 
00273 typedef struct xntimer {
00274 
00275         xntimerh_t aplink;      /* Link in aperiodic timers list. */
00276 
00277 #define aplink2timer(ln) container_of(ln, xntimer_t, aplink)
00278 
00279 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00280         xntbase_t *base;        /* Time base. */
00281 
00282         xntlholder_t plink;     /* Link in periodic timers wheel. */
00283 
00284 #define plink2timer(ln) container_of(ln, xntimer_t, plink)
00285 #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */
00286 
00287         xnholder_t adjlink;
00288 
00289 #define adjlink2timer(ln) container_of(ln, xntimer_t, adjlink)
00290 
00291         xnflags_t status;       /* !< Timer status. */
00292 
00293         xnticks_t interval;     /* !< Periodic interval (in ticks, 0 == one shot). */
00294 
00295         xnticks_t pexpect;      /* !< Date of next periodic release point (raw ticks). */
00296 
00297         struct xnsched *sched;  /* !< Sched structure to which the timer is
00298                                    attached. */
00299 
00300         void (*handler)(struct xntimer *timer); /* !< Timeout handler. */
00301 
00302 #ifdef CONFIG_XENO_OPT_STATS
00303         char name[XNOBJECT_NAME_LEN]; /* !< Timer name to be displayed. */
00304 
00305         const char *handler_name; /* !< Handler name to be displayed. */
00306 
00307         xnholder_t tblink;      /* !< Timer holder in timebase. */
00308 
00309 #define tblink2timer(ln)        container_of(ln, xntimer_t, tblink)
00310 #endif /* CONFIG_XENO_OPT_STATS */
00311 
00312         xnstat_counter_t scheduled; /* !< Number of timer schedules. */
00313 
00314         xnstat_counter_t fired; /* !< Number of timer events. */
00315 
00316         XNARCH_DECL_DISPLAY_CONTEXT();
00317 
00318 } xntimer_t;
00319 
00320 typedef struct xntimed_slave {
00321 
00322         xntbase_t base;         /* !< Cascaded time base. */
00323 
00324         struct percpu_cascade {
00325                 xntimer_t timer; /* !< Cascading timer in master time base. */
00326                 xnqueue_t wheel[XNTIMER_WHEELSIZE]; 
00327         } cascade[XNARCH_NR_CPUS];
00328 
00329 #define timer2slave(t) \
00330     ((xntslave_t *)(((char *)t) - offsetof(xntslave_t, cascade[xnsched_cpu((t)->sched)].timer)))
00331 #define base2slave(b) \
00332     ((xntslave_t *)(((char *)b) - offsetof(xntslave_t, base)))
00333 
00334 } xntslave_t;
00335 
00336 #ifdef CONFIG_SMP
00337 #define xntimer_sched(t)        ((t)->sched)
00338 #else /* !CONFIG_SMP */
00339 #define xntimer_sched(t)        xnpod_current_sched()
00340 #endif /* !CONFIG_SMP */
00341 #define xntimer_interval(t)     ((t)->interval)
00342 #define xntimer_pexpect(t)      ((t)->pexpect)
00343 #define xntimer_pexpect_forward(t,delta) ((t)->pexpect += delta)
00344 
00345 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00346 #define xntimer_base(t)         ((t)->base)
00347 #define xntimer_set_priority(t,p)                               \
00348         ({                                                      \
00349                 xntimer_t *_t = (t);                            \
00350                 unsigned prio = (p);                            \
00351                 xntimerh_prio(&(_t)->aplink) = prio;            \
00352                 xntlholder_prio(&(_t)->plink) = prio;           \
00353         })
00354 #else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
00355 #define xntimer_base(t)         (&nktbase)
00356 #define xntimer_set_priority(t,p)                               \
00357         do { xntimerh_prio(&(t)->aplink) = (p); } while(0)
00358 #endif /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
00359 
00360 static inline int xntimer_active_p (xntimer_t *timer)
00361 {
00362         return timer->sched != NULL;
00363 }
00364 
00365 static inline int xntimer_running_p(xntimer_t *timer)
00366 {
00367         return !testbits(timer->status,XNTIMER_DEQUEUED);
00368 }
00369 
00370 static inline int xntimer_reload_p(xntimer_t *timer)
00371 {
00372         return testbits(timer->status,
00373                         XNTIMER_PERIODIC|XNTIMER_DEQUEUED|XNTIMER_KILLED) ==
00374                 (XNTIMER_PERIODIC|XNTIMER_DEQUEUED);
00375 }
00376 
00377 #ifdef __cplusplus
00378 extern "C" {
00379 #endif
00380 
00381 extern xntbops_t nktimer_ops_aperiodic,
00382                  nktimer_ops_periodic;
00383 
00384 #ifdef CONFIG_XENO_OPT_STATS
00385 #define xntimer_init(timer, base, handler)              \
00386         do {                                            \
00387                 __xntimer_init(timer, base, handler);   \
00388                 (timer)->handler_name = #handler;       \
00389         } while (0)
00390 #else /* !CONFIG_XENO_OPT_STATS */
00391 #define xntimer_init    __xntimer_init
00392 #endif /* !CONFIG_XENO_OPT_STATS */
00393 
00394 #define xntimer_init_noblock(timer, base, handler)      \
00395         do {                                            \
00396                 xntimer_init(timer, base, handler);     \
00397                 (timer)->status |= XNTIMER_NOBLCK;      \
00398         } while(0)
00399 
00400 void __xntimer_init(struct xntimer *timer,
00401                     struct xntbase *base,
00402                     void (*handler)(struct xntimer *timer));
00403 
00404 void xntimer_destroy(xntimer_t *timer);
00405 
00406 static inline void xntimer_set_name(xntimer_t *timer, const char *name)
00407 {
00408 #ifdef CONFIG_XENO_OPT_STATS
00409         strncpy(timer->name, name, sizeof(timer->name));
00410 #endif /* CONFIG_XENO_OPT_STATS */
00411 }
00412 
00413 void xntimer_next_local_shot(struct xnsched *sched);
00414 
00419 #if defined(CONFIG_XENO_OPT_TIMING_PERIODIC) || defined(DOXYGEN_CPP)
00420 
00473 static inline int xntimer_start(xntimer_t *timer,
00474                                 xnticks_t value, xnticks_t interval,
00475                                 xntmode_t mode)
00476 {
00477         return timer->base->ops->start_timer(timer, value, interval, mode);
00478 }
00479 
00505 static inline void xntimer_stop(xntimer_t *timer)
00506 {
00507         /* Careful: the do_timer_stop() helper is expected to preserve
00508            the date field of the stopped timer, so that subsequent
00509            calls to xntimer_get_timeout() would still work on such
00510            timer as expected. */
00511         if (!testbits(timer->status,XNTIMER_DEQUEUED))
00512                 timer->base->ops->stop_timer(timer);
00513 }
00514 
00547 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
00548 {
00549         if (!xntimer_running_p(timer))
00550                 return XN_INFINITE;
00551 
00552         return timer->base->ops->get_timer_date(timer);
00553 }
00554 
00589 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
00590 {
00591         if (!xntimer_running_p(timer))
00592                 return XN_INFINITE;
00593 
00594         return timer->base->ops->get_timer_timeout(timer);
00595 }
00596 
00597 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
00598 {
00599         return timer->base->ops->get_timer_timeout(timer);
00600 }
00601 
00633 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
00634 {
00635         return timer->base->ops->get_timer_interval(timer);
00636 }
00637 
00638 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00639 {
00640         return timer->base->ops->get_timer_raw_expiry(timer);
00641 }
00642 
00643 void xntslave_init(xntslave_t *slave);
00644 
00645 void xntslave_destroy(xntslave_t *slave);
00646 
00647 void xntslave_update(xntslave_t *slave,
00648                      xnticks_t interval);
00649 
00650 void xntslave_start(xntslave_t *slave,
00651                     xnticks_t start,
00652                     xnticks_t interval);
00653 
00654 void xntslave_stop(xntslave_t *slave);
00655 
00656 void xntslave_adjust(xntslave_t *slave, xnsticks_t delta);
00657 
00658 #else /* !CONFIG_XENO_OPT_TIMING_PERIODIC */
00659 
00660 int xntimer_start_aperiodic(xntimer_t *timer,
00661                             xnticks_t value,
00662                             xnticks_t interval,
00663                             xntmode_t mode);
00664 
00665 void xntimer_stop_aperiodic(xntimer_t *timer);
00666 
00667 xnticks_t xntimer_get_date_aperiodic(xntimer_t *timer);
00668 
00669 xnticks_t xntimer_get_timeout_aperiodic(xntimer_t *timer);
00670 
00671 xnticks_t xntimer_get_interval_aperiodic(xntimer_t *timer);
00672 
00673 xnticks_t xntimer_get_raw_expiry_aperiodic(xntimer_t *timer);
00674 
00675 static inline int xntimer_start(xntimer_t *timer,
00676                                 xnticks_t value, xnticks_t interval,
00677                                 xntmode_t mode)
00678 {
00679         return xntimer_start_aperiodic(timer, value, interval, mode);
00680 }
00681 
00682 static inline void xntimer_stop(xntimer_t *timer)
00683 {
00684         if (!testbits(timer->status,XNTIMER_DEQUEUED))
00685                 xntimer_stop_aperiodic(timer);
00686 }
00687 
00688 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
00689 {
00690         if (!xntimer_running_p(timer))
00691                 return XN_INFINITE;
00692 
00693         return xntimer_get_date_aperiodic(timer);
00694 }
00695 
00696 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
00697 {
00698         if (!xntimer_running_p(timer))
00699                 return XN_INFINITE;
00700 
00701         return xntimer_get_timeout_aperiodic(timer);
00702 }
00703 
00704 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
00705 {
00706         return xntimer_get_timeout_aperiodic(timer);
00707 }
00708 
00709 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
00710 {
00711         return xntimer_get_interval_aperiodic(timer);
00712 }
00713 
00714 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00715 {
00716         return xntimerh_date(&timer->aplink);
00717 }
00718 
00719 #endif /* CONFIG_XENO_OPT_TIMING_PERIODIC */
00720 
00723 void xntimer_init_proc(void);
00724 
00725 void xntimer_cleanup_proc(void);
00726 
00727 unsigned long xntimer_get_overruns(xntimer_t *timer, xnticks_t now);
00728 
00729 void xntimer_freeze(void);
00730 
00731 void xntimer_tick_aperiodic(void);
00732 
00733 void xntimer_tick_periodic(xntimer_t *timer);
00734 
00735 void xntimer_tick_periodic_inner(xntslave_t *slave);
00736 
00737 void xntimer_adjust_all_aperiodic(xnsticks_t delta);
00738 
00739 #ifdef CONFIG_SMP
00740 int xntimer_migrate(xntimer_t *timer,
00741                     struct xnsched *sched);
00742 #else /* ! CONFIG_SMP */
00743 #define xntimer_migrate(timer, sched)           do { } while(0)
00744 #endif /* CONFIG_SMP */
00745 
00746 #define xntimer_set_sched(timer, sched) xntimer_migrate(timer, sched)
00747 
00748 char *xntimer_format_time(xnticks_t value, int periodic,
00749                           char *buf, size_t bufsz);
00750 #ifdef __cplusplus
00751 }
00752 #endif
00753 
00754 #endif /* __KERNEL__ || __XENO_SIM__ */
00755 
00756 #endif /* !_XENO_NUCLEUS_TIMER_H */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines