XenevaOS
Loading...
Searching...
No Matches
timer.h
Go to the documentation of this file.
1#ifndef __LINUX_TIMER_H__
2#define __LINUX_TIMER_H__
3
4#include <linux/container_of.h> /* container_of -- timer_container_of below */
5
6struct timer_list {
7 void (*function)(struct timer_list* t);
8 unsigned long expires; /* in jiffies */
9 void* data; /* private context */
11};
12
13/*
14 * timer_container_of(ptr, timer_member, field) -- recover the struct owning
15 * a timer_list from the timer callback's argument. mainline spells it the
16 * same way, in include/linux/timer.h.
17 *
18 * The three arguments look like a plain container_of() with an extra one,
19 * and the difference matters: container_of()'s first argument is the pointer
20 * *to the member*, whereas here it is the pointer *to the container* -- and
21 * the container is the variable being declared. So `vblank` in
22 *
23 * struct drm_vblank_crtc *vblank = timer_container_of(vblank, t,
24 * disable_timer);
25 *
26 * is read before it exists, but only for its type. That is why the expansion
27 * takes __typeof__(*ptr) rather than deriving the type from the member, and
28 * why the second argument is what gets passed through to container_of():
29 * there the static_assert checks that the pointer points at a `field`, and
30 * `t` does.
31 *
32 * __typeof__ rather than typeof because this target is not in GNU mode by
33 * default.
34 */
35#define timer_container_of(ptr, timer_member, field) \
36 container_of(timer_member, __typeof__(*(ptr)), field)
37
38/*
39 * Jiffies -- derived from the ARM generic timer, not counted by a tick.
40 *
41 * Nothing in Xeneva increments a tick counter: there is no timer IRQ calling
42 * a scheduler tick, so an `extern volatile unsigned long jiffies` would link
43 * to a variable that never moves, and every `time_after(jiffies, timeout)` a
44 * driver writes would then be false forever -- a polling loop that never
45 * notices its deadline, which reads as a hang rather than a timeout. Reading
46 * the same counter that udelay() burns against keeps comparisons honest with
47 * no tick to service, at HZ (250) resolution.
48 *
49 * It is an object-like macro, so `jiffies++` and `&jiffies` do not compile.
50 * Nothing in the tree does either -- the uses are reads (8250_port.c,
51 * n_tty.c, serial_core.c) -- and a compile error is the right answer if that
52 * changes, rather than a silently wrong increment.
53 */
54unsigned long dcl_jiffies_now(void);
55#define jiffies (dcl_jiffies_now())
56
57#define HZ 250 /* ticks per second � tune to your timer IRQ */
58#define msecs_to_jiffies(ms) ((ms) * HZ / 1000)
59#define jiffies_to_msecs(j) ((j) * 1000 / HZ)
60#define time_after(a, b) ((long)((b) - (a)) < 0)
61
62/*
63 * nsecs_to_jiffies(n) -- the conversion uart_poll_timeout() makes
64 * (serial_core.h:1315) to turn a frame time into a polling deadline.
65 *
66 * Truncating division by the nanoseconds-per-tick, which is div_u64()'s
67 * behaviour upstream: mainline rounds only in nsecs_to_jiffies64(), and
68 * matching the 64-bit one here would change a deadline by a tick in a
69 * function whose caller already does `max(..., 1UL)` to keep it from hitting
70 * zero. The round trip is exact at HZ 250: NSEC_PER_SEC / HZ is 4,000,000,
71 * an exact divisor of the second, so nothing accumulates.
72 */
73/*
74 * A macro, and the reason is the include order in <linux/kernel.h>: it pulls
75 * this header in at line 100 and only defines NSEC_PER_SEC at line 281, so a
76 * function body written here would be checked against a NSEC_PER_SEC that
77 * does not exist yet -- including through this file's own include of
78 * kernel.h, which the guard has already emptied. Expanding at the use site
79 * (serial_core.h:1315) instead, where kernel.h has finished, is the whole
80 * difference; `n` appears exactly once below, so there is no double
81 * evaluation for the macro form to introduce.
82 */
83#define nsecs_to_jiffies(n) ((unsigned long)((n) / (NSEC_PER_SEC / HZ)))
84
85/*
86 * nsecs_to_jiffies64(n) -- the 64-bit form drm_syncobj.c waits with (:442, a
87 * submit timeout, and :1220, an absolute deadline) and mainline keeps in
88 * <linux/jiffies.h>. A macro, and for the same include-order reason
89 * nsecs_to_jiffies above is one: <linux/kernel.h> pulls this header in before
90 * it defines NSEC_PER_SEC, so the division has to be spelled at the call
91 * site, where kernel.h has finished. At HZ 250 the divisor is exact
92 * (NSEC_PER_SEC / HZ == 4000000), which is mainline's own common case
93 * (`div_u64(n, NSEC_PER_SEC / HZ)` in kernel/time/time.c) with an ordinary
94 * 64-bit division; `n` is read once.
95 */
96#define nsecs_to_jiffies64(n) ((u64)((n) / (NSEC_PER_SEC / HZ)))
97
98#define time_before(a, b) time_after(b, a)
99#define time_after_eq(a, b) ((long)((a) - (b)) >= 0)
100
101#define timer_setup(t, fn, flags) do { \
102 (t)->function = (fn); \
103 (t)->pending = 0; \
104 (t)->data = NULL; \
105 (t)->expires = 0; \
106} while (0)
107
108/*
109 * No setup_timer() here, on purpose.
110 *
111 * It was in this header as a "legacy init form DWC2 may use", and mainline
112 * has not had the macro since timer_setup() replaced it -- so nothing here
113 * needed it, and keeping it broke a file that did: mainline's
114 * serial_8250.h:131 declares a *field* named setup_timer
115 *
116 * void (*setup_timer)(struct uart_8250_port *);
117 *
118 * and a function-like macro named setup_timer turns that declaration, and
119 * every call of it (`up->ops->setup_timer(up)` at 8250_port.c:2322), into a
120 * macro invocation with too few arguments. The fix is not to rename the
121 * field -- that would edit a vendored file -- it is for DCL not to invent a
122 * macro mainline removed.
123 *
124 * If something genuinely needs the legacy form, it will ask for it by name
125 * and can have it back then, under a name that does not shadow driver fields.
126 */
127
128/* On bare metal � you need a real timer queue for these */
129/* Stub for bring-up: call immediately */
130static inline void add_timer(struct timer_list* t) {
131 t->pending = 1;
132 /* TODO: insert into your timer queue */
133}
134
135static inline int mod_timer(struct timer_list* t, unsigned long expires) {
136 t->expires = expires;
137 t->pending = 1;
138 /* TODO: update in your timer queue */
139 return 0;
140}
141
142static inline int del_timer(struct timer_list* t) {
143 int was_pending = t->pending;
144 t->pending = 0;
145 return was_pending;
146}
147
148static inline int del_timer_sync(struct timer_list* t) {
149 return del_timer(t);
150}
151
152/*
153 * timer_delete_sync() -- the name v7.2 gives that operation (mainline:
154 * include/linux/timer.h declares it, kernel/time/timer.c owns it). The one
155 * user here is drm_vblank.c:533, which discards the result; forwarding to
156 * del_timer_sync() keeps a single body for one operation rather than letting
157 * the old and new spelling drift. There is no handler to synchronise with,
158 * because no timer IRQ runs one -- see the note on add_timer() below.
159 */
160static inline int timer_delete(struct timer_list* t) {
161 return del_timer(t);
162}
163
164static inline int timer_delete_sync(struct timer_list* t) {
165 return del_timer_sync(t);
166}
167
168static inline int timer_pending(const struct timer_list* t) {
169 return t->pending;
170}
171
172/* Helper to get owning struct from timer pointer */
173#define from_timer(var, callback_timer, timer_fieldname) \
174 container_of(callback_timer, typeof(*var), timer_fieldname)
175
176#endif /* __LINUX_TIMER_H__ */
XETime t
Definition main.cpp:53
unsigned long dcl_jiffies_now(void)
Definition timer.h:6
void * data
Definition timer.h:9
int pending
Definition timer.h:10
void(* function)(struct timer_list *t)
Definition timer.h:7
unsigned long expires
Definition timer.h:8