1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #ifndef _linux_POSIX_TIMERS_H |
3 | #define _linux_POSIX_TIMERS_H |
4 | |
5 | #include <linux/alarmtimer.h> |
6 | #include <linux/list.h> |
7 | #include <linux/mutex.h> |
8 | #include <linux/pid.h> |
9 | #include <linux/posix-timers_types.h> |
10 | #include <linux/rcuref.h> |
11 | #include <linux/spinlock.h> |
12 | #include <linux/timerqueue.h> |
13 | |
14 | struct kernel_siginfo; |
15 | struct task_struct; |
16 | struct sigqueue; |
17 | struct k_itimer; |
18 | |
19 | static inline clockid_t make_process_cpuclock(const unsigned int pid, |
20 | const clockid_t clock) |
21 | { |
22 | return ((~pid) << 3) | clock; |
23 | } |
24 | static inline clockid_t make_thread_cpuclock(const unsigned int tid, |
25 | const clockid_t clock) |
26 | { |
27 | return make_process_cpuclock(pid: tid, clock: clock | CPUCLOCK_PERTHREAD_MASK); |
28 | } |
29 | |
30 | static inline clockid_t fd_to_clockid(const int fd) |
31 | { |
32 | return make_process_cpuclock(pid: (unsigned int) fd, CLOCKFD); |
33 | } |
34 | |
35 | static inline int clockid_to_fd(const clockid_t clk) |
36 | { |
37 | return ~(clk >> 3); |
38 | } |
39 | |
40 | #ifdef CONFIG_POSIX_TIMERS |
41 | |
42 | #include <linux/signal_types.h> |
43 | |
44 | /** |
45 | * cpu_timer - Posix CPU timer representation for k_itimer |
46 | * @node: timerqueue node to queue in the task/sig |
47 | * @head: timerqueue head on which this timer is queued |
48 | * @pid: Pointer to target task PID |
49 | * @elist: List head for the expiry list |
50 | * @firing: Timer is currently firing |
51 | * @nanosleep: Timer is used for nanosleep and is not a regular posix-timer |
52 | * @handling: Pointer to the task which handles expiry |
53 | */ |
54 | struct cpu_timer { |
55 | struct timerqueue_node node; |
56 | struct timerqueue_head *head; |
57 | struct pid *pid; |
58 | struct list_head elist; |
59 | bool firing; |
60 | bool nanosleep; |
61 | struct task_struct __rcu *handling; |
62 | }; |
63 | |
64 | static inline bool cpu_timer_enqueue(struct timerqueue_head *head, |
65 | struct cpu_timer *ctmr) |
66 | { |
67 | ctmr->head = head; |
68 | return timerqueue_add(head, node: &ctmr->node); |
69 | } |
70 | |
71 | static inline bool cpu_timer_queued(struct cpu_timer *ctmr) |
72 | { |
73 | return !!ctmr->head; |
74 | } |
75 | |
76 | static inline bool cpu_timer_dequeue(struct cpu_timer *ctmr) |
77 | { |
78 | if (cpu_timer_queued(ctmr)) { |
79 | timerqueue_del(head: ctmr->head, node: &ctmr->node); |
80 | ctmr->head = NULL; |
81 | return true; |
82 | } |
83 | return false; |
84 | } |
85 | |
86 | static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr) |
87 | { |
88 | return ctmr->node.expires; |
89 | } |
90 | |
91 | static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp) |
92 | { |
93 | ctmr->node.expires = exp; |
94 | } |
95 | |
96 | static inline void posix_cputimers_init(struct posix_cputimers *pct) |
97 | { |
98 | memset(pct, 0, sizeof(*pct)); |
99 | pct->bases[0].nextevt = U64_MAX; |
100 | pct->bases[1].nextevt = U64_MAX; |
101 | pct->bases[2].nextevt = U64_MAX; |
102 | } |
103 | |
104 | void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit); |
105 | |
106 | static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct, |
107 | u64 runtime) |
108 | { |
109 | pct->bases[CPUCLOCK_SCHED].nextevt = runtime; |
110 | } |
111 | |
112 | void posixtimer_rearm_itimer(struct task_struct *p); |
113 | bool posixtimer_init_sigqueue(struct sigqueue *q); |
114 | void posixtimer_send_sigqueue(struct k_itimer *tmr); |
115 | bool posixtimer_deliver_signal(struct kernel_siginfo *info, struct sigqueue *timer_sigq); |
116 | void posixtimer_free_timer(struct k_itimer *timer); |
117 | long posixtimer_create_prctl(unsigned long ctrl); |
118 | |
119 | /* Init task static initializer */ |
120 | #define INIT_CPU_TIMERBASE(b) { \ |
121 | .nextevt = U64_MAX, \ |
122 | } |
123 | |
124 | #define INIT_CPU_TIMERBASES(b) { \ |
125 | INIT_CPU_TIMERBASE(b[0]), \ |
126 | INIT_CPU_TIMERBASE(b[1]), \ |
127 | INIT_CPU_TIMERBASE(b[2]), \ |
128 | } |
129 | |
130 | #define INIT_CPU_TIMERS(s) \ |
131 | .posix_cputimers = { \ |
132 | .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ |
133 | }, |
134 | #else |
135 | struct cpu_timer { }; |
136 | #define INIT_CPU_TIMERS(s) |
137 | static inline void posix_cputimers_init(struct posix_cputimers *pct) { } |
138 | static inline void posix_cputimers_group_init(struct posix_cputimers *pct, |
139 | u64 cpu_limit) { } |
140 | static inline void posixtimer_rearm_itimer(struct task_struct *p) { } |
141 | static inline bool posixtimer_deliver_signal(struct kernel_siginfo *info, |
142 | struct sigqueue *timer_sigq) { return false; } |
143 | static inline void posixtimer_free_timer(struct k_itimer *timer) { } |
144 | static inline long posixtimer_create_prctl(unsigned long ctrl) { return -EINVAL; } |
145 | #endif |
146 | |
147 | #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK |
148 | void clear_posix_cputimers_work(struct task_struct *p); |
149 | void posix_cputimers_init_work(void); |
150 | #else |
151 | static inline void clear_posix_cputimers_work(struct task_struct *p) { } |
152 | static inline void posix_cputimers_init_work(void) { } |
153 | #endif |
154 | |
155 | /** |
156 | * struct k_itimer - POSIX.1b interval timer structure. |
157 | * @list: List node for binding the timer to tsk::signal::posix_timers |
158 | * @ignored_list: List node for tracking ignored timers in tsk::signal::ignored_posix_timers |
159 | * @t_hash: Entry in the posix timer hash table |
160 | * @it_lock: Lock protecting the timer |
161 | * @kclock: Pointer to the k_clock struct handling this timer |
162 | * @it_clock: The posix timer clock id |
163 | * @it_id: The posix timer id for identifying the timer |
164 | * @it_status: The status of the timer |
165 | * @it_sig_periodic: The periodic status at signal delivery |
166 | * @it_overrun: The overrun counter for pending signals |
167 | * @it_overrun_last: The overrun at the time of the last delivered signal |
168 | * @it_signal_seq: Sequence count to control signal delivery |
169 | * @it_sigqueue_seq: The sequence count at the point where the signal was queued |
170 | * @it_sigev_notify: The notify word of sigevent struct for signal delivery |
171 | * @it_interval: The interval for periodic timers |
172 | * @it_signal: Pointer to the creators signal struct |
173 | * @it_pid: The pid of the process/task targeted by the signal |
174 | * @it_process: The task to wakeup on clock_nanosleep (CPU timers) |
175 | * @rcuref: Reference count for life time management |
176 | * @sigq: Embedded sigqueue |
177 | * @it: Union representing the various posix timer type |
178 | * internals. |
179 | * @rcu: RCU head for freeing the timer. |
180 | */ |
181 | struct k_itimer { |
182 | /* 1st cacheline contains read-mostly fields */ |
183 | struct hlist_node t_hash; |
184 | struct hlist_node list; |
185 | timer_t it_id; |
186 | clockid_t it_clock; |
187 | int it_sigev_notify; |
188 | enum pid_type it_pid_type; |
189 | struct signal_struct *it_signal; |
190 | const struct k_clock *kclock; |
191 | |
192 | /* 2nd cacheline and above contain fields which are modified regularly */ |
193 | spinlock_t it_lock; |
194 | int it_status; |
195 | bool it_sig_periodic; |
196 | s64 it_overrun; |
197 | s64 it_overrun_last; |
198 | unsigned int it_signal_seq; |
199 | unsigned int it_sigqueue_seq; |
200 | ktime_t it_interval; |
201 | struct hlist_node ignored_list; |
202 | union { |
203 | struct pid *it_pid; |
204 | struct task_struct *it_process; |
205 | }; |
206 | struct sigqueue sigq; |
207 | rcuref_t rcuref; |
208 | union { |
209 | struct { |
210 | struct hrtimer timer; |
211 | } real; |
212 | struct cpu_timer cpu; |
213 | struct { |
214 | struct alarm alarmtimer; |
215 | } alarm; |
216 | } it; |
217 | struct rcu_head rcu; |
218 | } ____cacheline_aligned_in_smp; |
219 | |
220 | void run_posix_cpu_timers(void); |
221 | void posix_cpu_timers_exit(struct task_struct *task); |
222 | void posix_cpu_timers_exit_group(struct task_struct *task); |
223 | void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, |
224 | u64 *newval, u64 *oldval); |
225 | |
226 | int update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); |
227 | |
228 | #ifdef CONFIG_POSIX_TIMERS |
229 | static inline void posixtimer_putref(struct k_itimer *tmr) |
230 | { |
231 | if (rcuref_put(ref: &tmr->rcuref)) |
232 | posixtimer_free_timer(timer: tmr); |
233 | } |
234 | |
235 | static inline void posixtimer_sigqueue_getref(struct sigqueue *q) |
236 | { |
237 | struct k_itimer *tmr = container_of(q, struct k_itimer, sigq); |
238 | |
239 | WARN_ON_ONCE(!rcuref_get(&tmr->rcuref)); |
240 | } |
241 | |
242 | static inline void posixtimer_sigqueue_putref(struct sigqueue *q) |
243 | { |
244 | struct k_itimer *tmr = container_of(q, struct k_itimer, sigq); |
245 | |
246 | posixtimer_putref(tmr); |
247 | } |
248 | |
249 | static inline bool posixtimer_valid(const struct k_itimer *timer) |
250 | { |
251 | unsigned long val = (unsigned long)timer->it_signal; |
252 | |
253 | return !(val & 0x1UL); |
254 | } |
255 | #else /* CONFIG_POSIX_TIMERS */ |
256 | static inline void posixtimer_sigqueue_getref(struct sigqueue *q) { } |
257 | static inline void posixtimer_sigqueue_putref(struct sigqueue *q) { } |
258 | #endif /* !CONFIG_POSIX_TIMERS */ |
259 | |
260 | #endif |
261 | |