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
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
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
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
00091
00092
00093
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
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
00179
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
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
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
00270
00271 struct xnsched;
00272
00273 typedef struct xntimer {
00274
00275 xntimerh_t aplink;
00276
00277 #define aplink2timer(ln) container_of(ln, xntimer_t, aplink)
00278
00279 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00280 xntbase_t *base;
00281
00282 xntlholder_t plink;
00283
00284 #define plink2timer(ln) container_of(ln, xntimer_t, plink)
00285 #endif
00286
00287 xnholder_t adjlink;
00288
00289 #define adjlink2timer(ln) container_of(ln, xntimer_t, adjlink)
00290
00291 xnflags_t status;
00292
00293 xnticks_t interval;
00294
00295 xnticks_t pexpect;
00296
00297 struct xnsched *sched;
00298
00299
00300 void (*handler)(struct xntimer *timer);
00301
00302 #ifdef CONFIG_XENO_OPT_STATS
00303 char name[XNOBJECT_NAME_LEN];
00304
00305 const char *handler_name;
00306
00307 xnholder_t tblink;
00308
00309 #define tblink2timer(ln) container_of(ln, xntimer_t, tblink)
00310 #endif
00311
00312 xnstat_counter_t scheduled;
00313
00314 xnstat_counter_t fired;
00315
00316 XNARCH_DECL_DISPLAY_CONTEXT();
00317
00318 } xntimer_t;
00319
00320 typedef struct xntimed_slave {
00321
00322 xntbase_t base;
00323
00324 struct percpu_cascade {
00325 xntimer_t timer;
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
00339 #define xntimer_sched(t) xnpod_current_sched()
00340 #endif
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
00355 #define xntimer_base(t) (&nktbase)
00356 #define xntimer_set_priority(t,p) \
00357 do { xntimerh_prio(&(t)->aplink) = (p); } while(0)
00358 #endif
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
00391 #define xntimer_init __xntimer_init
00392 #endif
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
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
00508
00509
00510
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
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
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
00743 #define xntimer_migrate(timer, sched) do { } while(0)
00744 #endif
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
00755
00756 #endif