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 {
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 {
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_set_cookie(t,c) ((t)->cookie = (c))
00343 #define xntimer_pexpect(t) ((t)->pexpect)
00344 #define xntimer_pexpect_forward(t,delta) ((t)->pexpect += delta)
00345
00346 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00347 #define xntimer_base(t) ((t)->base)
00348 #define xntimer_set_priority(t,p) \
00349 ({ \
00350 xntimer_t *_t = (t); \
00351 unsigned prio = (p); \
00352 xntimerh_prio(&(_t)->aplink) = prio; \
00353 xntlholder_prio(&(_t)->plink) = prio; \
00354 })
00355 #else
00356 #define xntimer_base(t) (&nktbase)
00357 #define xntimer_set_priority(t,p) \
00358 do { xntimerh_prio(&(t)->aplink) = (p); } while(0)
00359 #endif
00360
00361 static inline int xntimer_active_p (xntimer_t *timer)
00362 {
00363 return timer->sched != NULL;
00364 }
00365
00366 static inline int xntimer_running_p (xntimer_t *timer)
00367 {
00368 return !testbits(timer->status,XNTIMER_DEQUEUED);
00369 }
00370
00371 static inline int xntimer_reload_p(xntimer_t *timer)
00372 {
00373 return testbits(timer->status,
00374 XNTIMER_PERIODIC|XNTIMER_DEQUEUED|XNTIMER_KILLED) ==
00375 (XNTIMER_PERIODIC|XNTIMER_DEQUEUED);
00376 }
00377
00378 #ifdef __cplusplus
00379 extern "C" {
00380 #endif
00381
00382 extern xntbops_t nktimer_ops_aperiodic,
00383 nktimer_ops_periodic;
00384
00385 #ifdef CONFIG_XENO_OPT_STATS
00386 #define xntimer_init(timer, base, handler) \
00387 do { \
00388 __xntimer_init(timer, base, handler); \
00389 (timer)->handler_name = #handler; \
00390 } while (0)
00391 #else
00392 #define xntimer_init __xntimer_init
00393 #endif
00394
00395 void __xntimer_init(xntimer_t *timer,
00396 xntbase_t *base,
00397 void (*handler)(xntimer_t *timer));
00398
00399 void xntimer_destroy(xntimer_t *timer);
00400
00401 static inline void xntimer_set_name(xntimer_t *timer, const char *name)
00402 {
00403 #ifdef CONFIG_XENO_OPT_STATS
00404 strncpy(timer->name, name, sizeof(timer->name));
00405 #endif
00406 }
00407
00412 #if defined(CONFIG_XENO_OPT_TIMING_PERIODIC) || defined(DOXYGEN_CPP)
00413
00466 static inline int xntimer_start(xntimer_t *timer,
00467 xnticks_t value, xnticks_t interval,
00468 xntmode_t mode)
00469 {
00470 return timer->base->ops->start_timer(timer, value, interval, mode);
00471 }
00472
00498 static inline void xntimer_stop(xntimer_t *timer)
00499 {
00500
00501
00502
00503
00504 if (!testbits(timer->status,XNTIMER_DEQUEUED))
00505 timer->base->ops->stop_timer(timer);
00506 }
00507
00540 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
00541 {
00542 if (!xntimer_running_p(timer))
00543 return XN_INFINITE;
00544
00545 return timer->base->ops->get_timer_date(timer);
00546 }
00547
00582 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
00583 {
00584 if (!xntimer_running_p(timer))
00585 return XN_INFINITE;
00586
00587 return timer->base->ops->get_timer_timeout(timer);
00588 }
00589
00590 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
00591 {
00592 return timer->base->ops->get_timer_timeout(timer);
00593 }
00594
00626 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
00627 {
00628 return timer->base->ops->get_timer_interval(timer);
00629 }
00630
00631 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00632 {
00633 return timer->base->ops->get_timer_raw_expiry(timer);
00634 }
00635
00636 void xntslave_init(xntslave_t *slave);
00637
00638 void xntslave_destroy(xntslave_t *slave);
00639
00640 void xntslave_update(xntslave_t *slave,
00641 xnticks_t interval);
00642
00643 void xntslave_start(xntslave_t *slave,
00644 xnticks_t start,
00645 xnticks_t interval);
00646
00647 void xntslave_stop(xntslave_t *slave);
00648
00649 void xntslave_adjust(xntslave_t *slave, xnsticks_t delta);
00650
00651 #else
00652
00653 int xntimer_start_aperiodic(xntimer_t *timer,
00654 xnticks_t value,
00655 xnticks_t interval,
00656 xntmode_t mode);
00657
00658 void xntimer_stop_aperiodic(xntimer_t *timer);
00659
00660 xnticks_t xntimer_get_date_aperiodic(xntimer_t *timer);
00661
00662 xnticks_t xntimer_get_timeout_aperiodic(xntimer_t *timer);
00663
00664 xnticks_t xntimer_get_interval_aperiodic(xntimer_t *timer);
00665
00666 xnticks_t xntimer_get_raw_expiry_aperiodic(xntimer_t *timer);
00667
00668 static inline int xntimer_start(xntimer_t *timer,
00669 xnticks_t value, xnticks_t interval,
00670 xntmode_t mode)
00671 {
00672 return xntimer_start_aperiodic(timer, value, interval, mode);
00673 }
00674
00675 static inline void xntimer_stop(xntimer_t *timer)
00676 {
00677 if (!testbits(timer->status,XNTIMER_DEQUEUED))
00678 xntimer_stop_aperiodic(timer);
00679 }
00680
00681 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
00682 {
00683 if (!xntimer_running_p(timer))
00684 return XN_INFINITE;
00685
00686 return xntimer_get_date_aperiodic(timer);
00687 }
00688
00689 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
00690 {
00691 if (!xntimer_running_p(timer))
00692 return XN_INFINITE;
00693
00694 return xntimer_get_timeout_aperiodic(timer);
00695 }
00696
00697 static inline xnticks_t xntimer_get_timeout_stopped(xntimer_t *timer)
00698 {
00699 return xntimer_get_timeout_aperiodic(timer);
00700 }
00701
00702 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
00703 {
00704 return xntimer_get_interval_aperiodic(timer);
00705 }
00706
00707 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00708 {
00709 return xntimerh_date(&timer->aplink);
00710 }
00711
00712 #endif
00713
00716 unsigned long xntimer_get_overruns(xntimer_t *timer, xnticks_t now);
00717
00718 void xntimer_freeze(void);
00719
00720 void xntimer_tick_aperiodic(void);
00721
00722 void xntimer_tick_periodic(xntimer_t *timer);
00723
00724 void xntimer_tick_periodic_inner(xntslave_t *slave);
00725
00726 void xntimer_adjust_all_aperiodic(xnsticks_t delta);
00727
00728 #ifdef CONFIG_SMP
00729 int xntimer_migrate(xntimer_t *timer,
00730 struct xnsched *sched);
00731 #else
00732 #define xntimer_migrate(timer, sched) do { } while(0)
00733 #endif
00734
00735 #define xntimer_set_sched(timer, sched) xntimer_migrate(timer, sched)
00736
00737 #ifdef __cplusplus
00738 }
00739 #endif
00740
00741 #endif
00742
00743 #endif