00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _XENO_NUCLEUS_TIMER_H
00021 #define _XENO_NUCLEUS_TIMER_H
00022
00023 #include <nucleus/queue.h>
00024
00025 #if defined(__KERNEL__) || defined(__XENO_SIM__)
00026
00027 #if defined(CONFIG_XENO_OPT_TIMING_PERIODIC) \
00028 || defined(CONFIG_XENO_OPT_TIMER_WHEEL)
00029
00030 #define XNTIMER_WHEELSIZE 64
00031 #define XNTIMER_WHEELMASK (XNTIMER_WHEELSIZE - 1)
00032 #endif
00033
00034 #define XNTIMER_DEQUEUED 0x00000001
00035 #define XNTIMER_KILLED 0x00000002
00036
00037
00038 #define XNTIMER_SPARE0 0x01000000
00039 #define XNTIMER_SPARE1 0x02000000
00040 #define XNTIMER_SPARE2 0x04000000
00041 #define XNTIMER_SPARE3 0x08000000
00042 #define XNTIMER_SPARE4 0x10000000
00043 #define XNTIMER_SPARE5 0x20000000
00044 #define XNTIMER_SPARE6 0x40000000
00045 #define XNTIMER_SPARE7 0x80000000
00046
00047 #define XNTIMER_LOPRIO (-999999999)
00048 #define XNTIMER_STDPRIO 0
00049 #define XNTIMER_HIPRIO 999999999
00050
00051 #define XNTIMER_KEEPER_ID 0
00052
00053 typedef struct {
00054 xnholder_t link;
00055 xnticks_t key;
00056 int prio;
00057
00058 #define link2tlholder(laddr) \
00059 ((xntlholder_t *)(((char *)laddr) - offsetof(xntlholder_t, link)))
00060
00061 } xntlholder_t;
00062 #define xntlholder_date(h) ((h)->key)
00063 #define xntlholder_prio(h) ((h)->prio)
00064 #define xntlholder_init(h) inith(&(h)->link)
00065 #define xntlist_init(q) initq(q)
00066 #define xntlist_head(q) \
00067 ({ xnholder_t *_h = getheadq(q); \
00068 !_h ? NULL : link2tlholder(_h); \
00069 })
00070
00071 static inline void xntlist_insert(xnqueue_t *q, xntlholder_t *holder)
00072 {
00073 xnholder_t *p;
00074
00075
00076
00077
00078
00079
00080 for (p = q->head.last; p != &q->head; p = p->last)
00081 if (holder->key > link2tlholder(p)->key ||
00082 (holder->key == link2tlholder(p)->key &&
00083 holder->prio <= link2tlholder(p)->prio))
00084 break;
00085
00086 insertq(q,p->next,&holder->link);
00087 }
00088
00089 #define xntlist_remove(q, h) removeq((q),&(h)->link)
00090
00091 #if defined(CONFIG_XENO_OPT_TIMER_HEAP)
00092 #include <nucleus/bheap.h>
00093 typedef bheaph_t xntimerh_t;
00094 #define xntimerh_date(h) bheaph_key(h)
00095 #define xntimerh_prio(h) bheaph_prio(h)
00096 #define xntimerh_init(h) bheaph_init(h)
00097 typedef DECLARE_BHEAP_CONTAINER(xntimerq_t, CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY);
00098 #define xntimerq_init(q) bheap_init((q), CONFIG_XENO_OPT_TIMER_HEAP_CAPACITY)
00099 #define xntimerq_destroy(q) bheap_destroy(q)
00100 #define xntimerq_head(q) bheap_gethead(q)
00101 #define xntimerq_insert(q, h) bheap_insert((q),(h))
00102 #define xntimerq_remove(q, h) bheap_delete((q),(h))
00103
00104 #elif defined(CONFIG_XENO_OPT_TIMER_WHEEL)
00105 typedef xntlholder_t xntimerh_t;
00106 #define xntimerh_date(h) xntlholder_date(h)
00107 #define xntimerh_prio(h) xntlholder_prio(h)
00108 #define xntimerh_init(h) xntlholder_init(h)
00109 typedef struct {
00110 unsigned date_shift;
00111 unsigned long long next_shot;
00112 unsigned long long shot_wrap;
00113 xnqueue_t bucket[XNTIMER_WHEELSIZE];
00114 } xntimerq_t;
00115
00116 static inline void xntimerq_init(xntimerq_t *q)
00117 {
00118 unsigned long long step_tsc;
00119 unsigned i;
00120
00121 step_tsc = xnarch_ns_to_tsc(CONFIG_XENO_OPT_TIMER_WHEEL_STEP);
00122
00123 for (q->date_shift = 0; (1 << q->date_shift) < step_tsc; q->date_shift++)
00124 ;
00125 q->next_shot = q->shot_wrap = ((~0ULL) >> q->date_shift) + 1;
00126 for (i = 0; i < sizeof(q->bucket)/sizeof(xnqueue_t); i++)
00127 xntlist_init(&q->bucket[i]);
00128 }
00129
00130 #define xntimerq_destroy(q) do { } while (0)
00131
00132 static inline xntlholder_t *xntimerq_head(xntimerq_t *q)
00133 {
00134 unsigned bucket = ((unsigned) q->next_shot) & XNTIMER_WHEELMASK;
00135 xntlholder_t *result;
00136 unsigned i;
00137
00138 if (q->next_shot == q->shot_wrap)
00139 return NULL;
00140
00141 result = xntlist_head(&q->bucket[bucket]);
00142
00143 if (result && (xntlholder_date(result) >> q->date_shift) == q->next_shot)
00144 return result;
00145
00146
00147
00148 for (i = (bucket + 1) & XNTIMER_WHEELMASK ;
00149 i != bucket; i = (i + 1) & XNTIMER_WHEELMASK) {
00150 xntlholder_t *candidate = xntlist_head(&q->bucket[i]);
00151
00152 if(++q->next_shot == q->shot_wrap)
00153 q->next_shot = 0;
00154
00155 if (!candidate)
00156 continue;
00157
00158 if ((xntlholder_date(candidate) >> q->date_shift) == q->next_shot)
00159 return candidate;
00160
00161 if (!result
00162 || xntlholder_date(candidate) < xntlholder_date(result))
00163 result = candidate;
00164 }
00165
00166 if (result)
00167 q->next_shot = (xntlholder_date(result) >> q->date_shift);
00168 else
00169 q->next_shot = q->shot_wrap;
00170 return result;
00171 }
00172
00173 static inline void xntimerq_insert(xntimerq_t *q, xntimerh_t *h)
00174 {
00175 unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
00176 unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
00177
00178 if (shifted_date < q->next_shot)
00179 q->next_shot = shifted_date;
00180 xntlist_insert(&q->bucket[bucket], h);
00181 }
00182
00183 static inline void xntimerq_remove(xntimerq_t *q, xntimerh_t *h)
00184 {
00185 unsigned long long shifted_date = xntlholder_date(h) >> q->date_shift;
00186 unsigned bucket = ((unsigned) shifted_date) & XNTIMER_WHEELMASK;
00187
00188 xntlist_remove(&q->bucket[bucket], h);
00189
00190 }
00191
00192 #else
00193 typedef xntlholder_t xntimerh_t;
00194 #define xntimerh_date(h) xntlholder_date(h)
00195 #define xntimerh_prio(h) xntlholder_prio(h)
00196 #define xntimerh_init(h) xntlholder_init(h)
00197 typedef xnqueue_t xntimerq_t;
00198 #define xntimerq_init(q) xntlist_init(q)
00199 #define xntimerq_destroy(q) do { } while (0)
00200 #define xntimerq_head(q) xntlist_head(q)
00201 #define xntimerq_insert(q,h) xntlist_insert((q),(h))
00202 #define xntimerq_remove(q, h) xntlist_remove((q),(h))
00203
00204 #endif
00205
00206 struct xnsched;
00207
00208 typedef struct xntimer {
00209
00210 xntimerh_t aplink;
00211
00212 #define aplink2timer(laddr) \
00213 ((xntimer_t *)(((char *)(laddr)) - (int)(&((xntimer_t *)0)->aplink)))
00214
00215 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00216 xntlholder_t plink;
00217
00218 #define plink2timer(laddr) \
00219 ((xntimer_t *)(((char *)(laddr)) - (int)(&((xntimer_t *)0)->plink)))
00220 #endif
00221
00222 xnflags_t status;
00223
00224 xnticks_t interval;
00225
00226 struct xnsched *sched;
00227
00228
00229 void (*handler)(struct xntimer *timer);
00230
00231 XNARCH_DECL_DISPLAY_CONTEXT();
00232
00233 } xntimer_t;
00234
00235 #if defined(CONFIG_SMP)
00236 #define xntimer_sched(t) ((t)->sched)
00237 #else
00238 #define xntimer_sched(t) xnpod_current_sched()
00239 #endif
00240 #define xntimer_interval(t) ((t)->interval)
00241 #define xntimer_set_cookie(t,c) ((t)->cookie = (c))
00242
00243 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00244 #define xntimer_set_priority(t,p) ({ \
00245 xntimer_t *_t = (t); \
00246 unsigned prio = (p); \
00247 xntimerh_prio(&(_t)->aplink) = prio; \
00248 xntlholder_prio(&(_t)->plink) = prio; \
00249 })
00250 #else
00251 #define xntimer_set_priority(t,p) (xntimerh_prio(&(t)->aplink) = (p))
00252 #endif
00253
00254 static inline int xntimer_active_p (xntimer_t *timer)
00255 {
00256 return timer->sched != NULL;
00257 }
00258
00259 static inline int xntimer_running_p (xntimer_t *timer)
00260 {
00261 return !testbits(timer->status,XNTIMER_DEQUEUED);
00262 }
00263
00264 typedef struct xntmops {
00265
00266 void (*do_tick)(void);
00267 xnticks_t (*get_jiffies)(void);
00268 xnticks_t (*get_raw_clock)(void);
00269 void (*do_timer_start)(xntimer_t *timer,
00270 xnticks_t value,
00271 xnticks_t interval);
00272 void (*do_timer_stop)(xntimer_t *timer);
00273 xnticks_t (*get_timer_date)(xntimer_t *timer);
00274 xnticks_t (*get_timer_timeout)(xntimer_t *timer);
00275 xnticks_t (*get_timer_interval)(xntimer_t *timer);
00276 xnticks_t (*get_timer_raw_expiry)(xntimer_t *timer);
00277 void (*set_timer_remote)(xntimer_t *timer);
00278 const char *(*get_type)(void);
00279 void (*freeze)(void);
00280
00281 } xntmops_t;
00282
00283 #ifdef __cplusplus
00284 extern "C" {
00285 #endif
00286
00287 extern xntmops_t *nktimer;
00288
00289 void xntimer_init(xntimer_t *timer,
00290 void (*handler)(xntimer_t *timer));
00291
00292 void xntimer_destroy(xntimer_t *timer);
00293
00335 static inline void xntimer_start(xntimer_t *timer,
00336 xnticks_t value, xnticks_t interval)
00337 {
00338 nktimer->do_timer_start(timer, value, interval);
00339 }
00340
00366 static inline void xntimer_stop(xntimer_t *timer)
00367 {
00368
00369
00370
00371
00372 if (!testbits(timer->status,XNTIMER_DEQUEUED))
00373 nktimer->do_timer_stop(timer);
00374 }
00375
00376 static inline xnticks_t xntimer_get_jiffies(void)
00377 {
00378 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00379 return nktimer->get_jiffies();
00380 #else
00381 return xnarch_get_cpu_time();
00382 #endif
00383 }
00384
00385 static inline xnticks_t xntimer_get_rawclock(void)
00386 {
00387 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00388 return nktimer->get_raw_clock();
00389 #else
00390 return xnarch_get_cpu_tsc();
00391 #endif
00392 }
00393
00394 static inline xnticks_t xntimer_get_raw_expiry (xntimer_t *timer)
00395 {
00396 #ifdef CONFIG_XENO_OPT_TIMING_PERIODIC
00397 return nktimer->get_timer_raw_expiry(timer);
00398 #else
00399 return xntimerh_date(&timer->aplink);
00400 #endif
00401 }
00402
00403 void xntimer_freeze(void);
00404
00405 xnticks_t xntimer_get_date(xntimer_t *timer);
00406
00407 xnticks_t xntimer_get_timeout(xntimer_t *timer);
00408
00409 xnticks_t xntimer_get_interval(xntimer_t *timer);
00410
00411 void xntimer_set_periodic_mode(void);
00412
00413 void xntimer_set_aperiodic_mode(void);
00414
00415 #if defined(CONFIG_SMP)
00416 int xntimer_set_sched(xntimer_t *timer, struct xnsched *sched);
00417 #else
00418 #define xntimer_set_sched(timer,sched)
00419 #endif
00420
00421 #ifdef __cplusplus
00422 }
00423 #endif
00424
00425 #endif
00426
00427 #endif