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