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
00045
00046 #define XNTIMER_SPARE0 0x01000000
00047 #define XNTIMER_SPARE1 0x02000000
00048 #define XNTIMER_SPARE2 0x04000000
00049 #define XNTIMER_SPARE3 0x08000000
00050 #define XNTIMER_SPARE4 0x10000000
00051 #define XNTIMER_SPARE5 0x20000000
00052 #define XNTIMER_SPARE6 0x40000000
00053 #define XNTIMER_SPARE7 0x80000000
00054
00055
00056 #define XNTIMER_LOPRIO (-999999999)
00057 #define XNTIMER_STDPRIO 0
00058 #define XNTIMER_HIPRIO 999999999
00059
00060 #define XNTIMER_KEEPER_ID 0
00061
00062 typedef struct {
00063 xnholder_t link;
00064 xnticks_t key;
00065 int prio;
00066
00067 #define link2tlholder(ln) container_of(ln, xntlholder_t, link)
00068
00069 } xntlholder_t;
00070
00071 #define xntlholder_date(h) ((h)->key)
00072 #define xntlholder_prio(h) ((h)->prio)
00073 #define xntlholder_init(h) inith(&(h)->link)
00074 #define xntlist_init(q) initq(q)
00075 #define xntlist_head(q) \
00076 ({ xnholder_t *_h = getheadq(q); \
00077 !_h ? NULL : link2tlholder(_h); \
00078 })
00079
00080 #define xntlist_next(q, h) \
00081 ({ xnholder_t *_h = nextq(q, &(h)->link); \
00082 !_h ? NULL : link2tlholder(_h); \
00083 })
00084
00085 static inline void xntlist_insert(xnqueue_t *q, xntlholder_t *holder)
00086 {
00087 xnholder_t *p;
00088
00089
00090
00091
00092
00093
00094 for (p = q->head.last; p != &q->head; p = p->last)
00095 if ((xnsticks_t) (holder->key - link2tlholder(p)->key) > 0 ||
00096 (holder->key == link2tlholder(p)->key &&
00097 holder->prio <= link2tlholder(p)->prio))
00098 break;
00099
00100 insertq(q,p->next,&holder->link);
00101 }
00102
00103 #define xntlist_remove(q, h) removeq((q),&(h)->link)
00104
00105 #if defined(CONFIG_XENO_OPT_TIMER_HEAP)
00106
00107 #include <nucleus/bheap.h>
00108
00109 typedef bheaph_t xntimerh_t;
00110
00111 #define xntimerh_date(h) bheaph_key(h)
00112 #define xntimerh_prio(h) bheaph_prio(h)
00113 #define xntimerh_init(h) bheaph_init(h)
00114
00115 typedef DECLARE_BHEAP_CONTAINER(xntimerq_t, CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY);
00116
00117 #define xntimerq_init(q) bheap_init((q), CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY)
00118 #define xntimerq_destroy(q) bheap_destroy(q)
00119 #define xntimerq_head(q) bheap_gethead(q)
00120 #define xntimerq_insert(q, h) bheap_insert((q),(h))
00121 #define xntimerq_remove(q, h) bheap_delete((q),(h))
00122
00123 typedef struct {} xntimerq_it_t;
00124
00125 #define xntimerq_it_begin(q, i) ((void) (i), bheap_gethead(q))
00126 #define xntimerq_it_next(q, i, h) ((void) (i), bheap_next((q),(h)))
00127
00128 #elif defined(CONFIG_XENO_OPT_TIMER_WHEEL)
00129
00130 typedef xntlholder_t xntimerh_t;
00131
00132 #define xntimerh_date(h) xntlholder_date(h)
00133 #define xntimerh_prio(h) xntlholder_prio(h)
00134 #define xntimerh_init(h) xntlholder_init(h)
00135
00136 typedef struct {
00137 unsigned date_shift;
00138 unsigned long long next_shot;
00139 unsigned long long shot_wrap;
00140 xnqueue_t bucket[XNTIMER_WHEELSIZE];
00141 } xntimerq_t;
00142
00143 typedef struct {
00144 unsigned bucket;
00145 } xntimerq_it_t;
00146
00147 static inline void xntimerq_init(xntimerq_t *q)
00148 {
00149 unsigned long long step_tsc;
00150 unsigned i;
00151
00152 step_tsc = xnarch_ns_to_tsc(CONFIG_XENO_OPT_TIMER_WHEEL_STEP);
00153
00154 for (q->date_shift = 0; (1 << q->date_shift) < step_tsc; q->date_shift++)
00155 ;
00156 q->next_shot = q->shot_wrap = ((~0ULL) >> q->date_shift) + 1;
00157 for (i = 0; i < sizeof(q->bucket)/sizeof(xnqueue_t); i++)
00158 xntlist_init(&q->bucket[i]);
00159 }
00160
00161 #define xntimerq_destroy(q) do { } while (0)
00162
00163 static inline xntlholder_t *xntimerq_head(xntimerq_t *q)
00164 {
00165 unsigned bucket = ((unsigned) q->next_shot) & XNTIMER_WHEELMASK;
00166 xntlholder_t *result;
00167 unsigned i;
00168
00169 if (q->next_shot == q->shot_wrap)
00170 return NULL;
00171
00172 result = xntlist_head(&q->bucket[bucket]);
00173
00174 if (result && (xntlholder_date(result) >> q->date_shift) == q->next_shot)
00175 return result;
00176
00177
00178
00179 for (i = (bucket + 1) & XNTIMER_WHEELMASK ;
00180 i != bucket; i = (i + 1) & XNTIMER_WHEELMASK) {
00181 xntlholder_t *candidate = xntlist_head(&q->bucket[i]);
00182
00183 if(++q->next_shot == q->shot_wrap)
00184 q->next_shot = 0;
00185
00186 if (!candidate)
00187 continue;
00188
00189 if ((xntlholder_date(candidate) >> q->date_shift) == q->next_shot)
00190 return candidate;
00191
00192 if (!result || (xnsticks_t) (xntlholder_date(candidate)
00193 - xntlholder_date(result)) < 0)
00194 result = candidate;
00195 }
00196
00197 if (result)
00198 q->next_shot = (xntlholder_date(result) >> q->date_shift);
00199 else
00200 q->next_shot = q->shot_wrap;
00201 return result;
00202 }
00203
00204 static inline void xntimerq_insert(xntimerq_t *q, xntimerh_t *h)
00205 {
00206 unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
00207 unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
00208
00209 if ((long long) (shifted_date - q->next_shot) < 0)
00210 q->next_shot = shifted_date;
00211 xntlist_insert(&q->bucket[bucket], h);
00212 }
00213
00214 static inline void xntimerq_remove(xntimerq_t *q, xntimerh_t *h)
00215 {
00216 unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
00217 unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
00218
00219 xntlist_remove(&q->bucket[bucket], h);
00220
00221 }
00222
00223 static inline xntimerh_t *xntimerq_it_begin(xntimerq_t *q, xntimerq_it_t *it)
00224 {
00225 xntimerh_t *holder = NULL;
00226
00227 for (it->bucket = 0; it->bucket < XNTIMER_WHEELSIZE; it->bucket++)
00228 if ((holder = xntlist_head(&q->bucket[it->bucket])))
00229 break;
00230
00231 return holder;
00232 }
00233
00234 static inline xntimerh_t *
00235 xntimerq_it_next(xntimerq_t *q, xntimerq_it_t *it, xntimerh_t *holder)
00236 {
00237 xntimerh_t *next = xntlist_next(&q->bucket[it->bucket], holder);
00238
00239 if (!next)
00240 for(it->bucket++; it->bucket < XNTIMER_WHEELSIZE; it->bucket++)
00241 if ((next = xntlist_head(&q->bucket[it->bucket])))
00242 break;
00243
00244 return next;
00245 }
00246
00247 #else
00248
00249 typedef xntlholder_t xntimerh_t;
00250
00251 #define xntimerh_date(h) xntlholder_date(h)
00252 #define xntimerh_prio(h) xntlholder_prio(h)
00253 #define xntimerh_init(h) xntlholder_init(h)
00254
00255 typedef xnqueue_t xntimerq_t;
00256
00257 #define xntimerq_init(q) xntlist_init(q)
00258 #define xntimerq_destroy(q) do { } while (0)
00259 #define xntimerq_head(q) xntlist_head(q)
00260 #define xntimerq_insert(q,h) xntlist_insert((q),(h))
00261 #define xntimerq_remove(q, h) xntlist_remove((q),(h))
00262
00263 typedef struct {} xntimerq_it_t;
00264
00265 #define xntimerq_it_begin(q,i) ((void) (i), xntlist_head(q))
00266 #define xntimerq_it_next(q,i,h) ((void) (i), xntlist_next((q),(h)))
00267
00268 #endif
00269
00270 struct xnsched;
00271
00272 typedef struct xntimer {
00273
00274 xntimerh_t aplink;
00275
00276 #define aplink2timer(ln) container_of(ln, xntimer_t, aplink)
00277
00278 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00279 xntbase_t *base;
00280
00281 xntlholder_t plink;
00282
00283 #define plink2timer(ln) container_of(ln, xntimer_t, plink)
00284 #endif
00285
00286 xnholder_t adjlink;
00287
00288 #define adjlink2timer(ln) container_of(ln, xntimer_t, adjlink)
00289
00290 xnflags_t status;
00291
00292 xnticks_t interval;
00293
00294 xnticks_t pexpect;
00295
00296 struct xnsched *sched;
00297
00298
00299 void (*handler)(struct xntimer *timer);
00300
00301 #ifdef CONFIG_XENO_OPT_STATS
00302 char name[XNOBJECT_NAME_LEN];
00303
00304 const char *handler_name;
00305
00306 xnholder_t tblink;
00307
00308 #define tblink2timer(ln) container_of(ln, xntimer_t, tblink)
00309 #endif
00310
00311 xnstat_counter_t scheduled;
00312
00313 xnstat_counter_t fired;
00314
00315 XNARCH_DECL_DISPLAY_CONTEXT();
00316
00317 } xntimer_t;
00318
00319 typedef struct xntimed_slave {
00320
00321 xntbase_t base;
00322
00323 struct percpu_cascade {
00324 xntimer_t timer;
00325 xnqueue_t wheel[XNTIMER_WHEELSIZE];
00326 } cascade[XNARCH_NR_CPUS];
00327
00328 #define timer2slave(t) \
00329 ((xntslave_t *)(((char *)t) - offsetof(xntslave_t, cascade[xnsched_cpu((t)->sched)].timer)))
00330 #define base2slave(b) \
00331 ((xntslave_t *)(((char *)b) - offsetof(xntslave_t, base)))
00332
00333 } xntslave_t;
00334
00335 #ifdef CONFIG_SMP
00336 #define xntimer_sched(t) ((t)->sched)
00337 #else
00338 #define xntimer_sched(t) xnpod_current_sched()
00339 #endif
00340 #define xntimer_interval(t) ((t)->interval)
00341 #define xntimer_set_cookie(t,c) ((t)->cookie = (c))
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 void __xntimer_init(xntimer_t *timer,
00395 xntbase_t *base,
00396 void (*handler)(xntimer_t *timer));
00397
00398 void xntimer_destroy(xntimer_t *timer);
00399
00400 static inline void xntimer_set_name(xntimer_t *timer, const char *name)
00401 {
00402 #ifdef CONFIG_XENO_OPT_STATS
00403 strncpy(timer->name, name, sizeof(timer->name));
00404 #endif
00405 }
00406
00411 #if defined(CONFIG_XENO_OPT_TIMING_PERIODIC) || defined(DOXYGEN_CPP)
00412
00465 static inline int xntimer_start(xntimer_t *timer,
00466 xnticks_t value, xnticks_t interval,
00467 xntmode_t mode)
00468 {
00469 return timer->base->ops->start_timer(timer, value, interval, mode);
00470 }
00471
00497 static inline void xntimer_stop(xntimer_t *timer)
00498 {
00499
00500
00501
00502
00503 if (!testbits(timer->status,XNTIMER_DEQUEUED))
00504 timer->base->ops->stop_timer(timer);
00505 }
00506
00539 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
00540 {
00541 if (!xntimer_running_p(timer))
00542 return XN_INFINITE;
00543
00544 return timer->base->ops->get_timer_date(timer);
00545 }
00546
00581 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
00582 {
00583 if (!xntimer_running_p(timer))
00584 return XN_INFINITE;
00585
00586 return timer->base->ops->get_timer_timeout(timer);
00587 }
00588
00620 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
00621 {
00622 return timer->base->ops->get_timer_interval(timer);
00623 }
00624
00625 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00626 {
00627 return timer->base->ops->get_timer_raw_expiry(timer);
00628 }
00629
00630 void xntslave_init(xntslave_t *slave);
00631
00632 void xntslave_destroy(xntslave_t *slave);
00633
00634 void xntslave_update(xntslave_t *slave,
00635 xnticks_t interval);
00636
00637 void xntslave_start(xntslave_t *slave,
00638 xnticks_t start,
00639 xnticks_t interval);
00640
00641 void xntslave_stop(xntslave_t *slave);
00642
00643 void xntslave_adjust(xntslave_t *slave, xnsticks_t delta);
00644
00645 #else
00646
00647 int xntimer_start_aperiodic(xntimer_t *timer,
00648 xnticks_t value,
00649 xnticks_t interval,
00650 xntmode_t mode);
00651
00652 void xntimer_stop_aperiodic(xntimer_t *timer);
00653
00654 xnticks_t xntimer_get_date_aperiodic(xntimer_t *timer);
00655
00656 xnticks_t xntimer_get_timeout_aperiodic(xntimer_t *timer);
00657
00658 xnticks_t xntimer_get_interval_aperiodic(xntimer_t *timer);
00659
00660 xnticks_t xntimer_get_raw_expiry_aperiodic(xntimer_t *timer);
00661
00662 static inline int xntimer_start(xntimer_t *timer,
00663 xnticks_t value, xnticks_t interval,
00664 xntmode_t mode)
00665 {
00666 return xntimer_start_aperiodic(timer, value, interval, mode);
00667 }
00668
00669 static inline void xntimer_stop(xntimer_t *timer)
00670 {
00671 if (!testbits(timer->status,XNTIMER_DEQUEUED))
00672 xntimer_stop_aperiodic(timer);
00673 }
00674
00675 static inline xnticks_t xntimer_get_date(xntimer_t *timer)
00676 {
00677 if (!xntimer_running_p(timer))
00678 return XN_INFINITE;
00679
00680 return xntimer_get_date_aperiodic(timer);
00681 }
00682
00683 static inline xnticks_t xntimer_get_timeout(xntimer_t *timer)
00684 {
00685 if (!xntimer_running_p(timer))
00686 return XN_INFINITE;
00687
00688 return xntimer_get_timeout_aperiodic(timer);
00689 }
00690
00691 static inline xnticks_t xntimer_get_interval(xntimer_t *timer)
00692 {
00693 return xntimer_get_interval_aperiodic(timer);
00694 }
00695
00696 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00697 {
00698 return xntimerh_date(&timer->aplink);
00699 }
00700
00701 #endif
00702
00705 unsigned long xntimer_get_overruns(xntimer_t *timer, xnticks_t now);
00706
00707 void xntimer_freeze(void);
00708
00709 void xntimer_tick_aperiodic(void);
00710
00711 void xntimer_tick_periodic(xntimer_t *timer);
00712
00713 void xntimer_tick_periodic_inner(xntslave_t *slave);
00714
00715 void xntimer_adjust_all_aperiodic(xnsticks_t delta);
00716
00717 #ifdef CONFIG_SMP
00718 int xntimer_migrate(xntimer_t *timer,
00719 struct xnsched *sched);
00720 #else
00721 #define xntimer_migrate(timer, sched) do { } while(0)
00722 #endif
00723
00724 #define xntimer_set_sched(timer, sched) xntimer_migrate(timer, sched)
00725
00726 #ifdef __cplusplus
00727 }
00728 #endif
00729
00730 #endif
00731
00732 #endif