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