1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds #ifndef _linux_POSIX_TIMERS_H
31da177e4SLinus Torvalds #define _linux_POSIX_TIMERS_H
41da177e4SLinus Torvalds
51da177e4SLinus Torvalds #include <linux/spinlock.h>
61da177e4SLinus Torvalds #include <linux/list.h>
7*f7abf14fSThomas Gleixner #include <linux/mutex.h>
89a7adcf5SJohn Stultz #include <linux/alarmtimer.h>
960bda037SThomas Gleixner #include <linux/timerqueue.h>
101da177e4SLinus Torvalds
11ce03f613SThomas Gleixner struct kernel_siginfo;
12ce03f613SThomas Gleixner struct task_struct;
1355ccb616SFrederic Weisbecker
1481e294cbSRichard Cochran /*
1581e294cbSRichard Cochran * Bit fields within a clockid:
1681e294cbSRichard Cochran *
1781e294cbSRichard Cochran * The most significant 29 bits hold either a pid or a file descriptor.
1881e294cbSRichard Cochran *
1981e294cbSRichard Cochran * Bit 2 indicates whether a cpu clock refers to a thread or a process.
2081e294cbSRichard Cochran *
2181e294cbSRichard Cochran * Bits 1 and 0 give the type: PROF=0, VIRT=1, SCHED=2, or FD=3.
2281e294cbSRichard Cochran *
2381e294cbSRichard Cochran * A clockid is invalid if bits 2, 1, and 0 are all set.
2481e294cbSRichard Cochran */
251da177e4SLinus Torvalds #define CPUCLOCK_PID(clock) ((pid_t) ~((clock) >> 3))
261da177e4SLinus Torvalds #define CPUCLOCK_PERTHREAD(clock) \
271da177e4SLinus Torvalds (((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
280606f422SRichard Cochran
291da177e4SLinus Torvalds #define CPUCLOCK_PERTHREAD_MASK 4
301da177e4SLinus Torvalds #define CPUCLOCK_WHICH(clock) ((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK)
311da177e4SLinus Torvalds #define CPUCLOCK_CLOCK_MASK 3
321da177e4SLinus Torvalds #define CPUCLOCK_PROF 0
331da177e4SLinus Torvalds #define CPUCLOCK_VIRT 1
341da177e4SLinus Torvalds #define CPUCLOCK_SCHED 2
351da177e4SLinus Torvalds #define CPUCLOCK_MAX 3
3681e294cbSRichard Cochran #define CLOCKFD CPUCLOCK_MAX
3781e294cbSRichard Cochran #define CLOCKFD_MASK (CPUCLOCK_PERTHREAD_MASK|CPUCLOCK_CLOCK_MASK)
381da177e4SLinus Torvalds
make_process_cpuclock(const unsigned int pid,const clockid_t clock)3929f1b2b0SNick Desaulniers static inline clockid_t make_process_cpuclock(const unsigned int pid,
4029f1b2b0SNick Desaulniers const clockid_t clock)
4129f1b2b0SNick Desaulniers {
4229f1b2b0SNick Desaulniers return ((~pid) << 3) | clock;
4329f1b2b0SNick Desaulniers }
make_thread_cpuclock(const unsigned int tid,const clockid_t clock)4429f1b2b0SNick Desaulniers static inline clockid_t make_thread_cpuclock(const unsigned int tid,
4529f1b2b0SNick Desaulniers const clockid_t clock)
4629f1b2b0SNick Desaulniers {
4729f1b2b0SNick Desaulniers return make_process_cpuclock(tid, clock | CPUCLOCK_PERTHREAD_MASK);
4829f1b2b0SNick Desaulniers }
491da177e4SLinus Torvalds
fd_to_clockid(const int fd)5029f1b2b0SNick Desaulniers static inline clockid_t fd_to_clockid(const int fd)
5129f1b2b0SNick Desaulniers {
5229f1b2b0SNick Desaulniers return make_process_cpuclock((unsigned int) fd, CLOCKFD);
5329f1b2b0SNick Desaulniers }
5429f1b2b0SNick Desaulniers
clockid_to_fd(const clockid_t clk)5529f1b2b0SNick Desaulniers static inline int clockid_to_fd(const clockid_t clk)
5629f1b2b0SNick Desaulniers {
5729f1b2b0SNick Desaulniers return ~(clk >> 3);
5829f1b2b0SNick Desaulniers }
590606f422SRichard Cochran
602b69942fSThomas Gleixner #ifdef CONFIG_POSIX_TIMERS
6187dc6448SThomas Gleixner
6287dc6448SThomas Gleixner /**
6360bda037SThomas Gleixner * cpu_timer - Posix CPU timer representation for k_itimer
6460bda037SThomas Gleixner * @node: timerqueue node to queue in the task/sig
6560bda037SThomas Gleixner * @head: timerqueue head on which this timer is queued
66*f7abf14fSThomas Gleixner * @pid: Pointer to target task PID
6760bda037SThomas Gleixner * @elist: List head for the expiry list
6860bda037SThomas Gleixner * @firing: Timer is currently firing
69*f7abf14fSThomas Gleixner * @handling: Pointer to the task which handles expiry
7060bda037SThomas Gleixner */
7160bda037SThomas Gleixner struct cpu_timer {
7260bda037SThomas Gleixner struct timerqueue_node node;
7360bda037SThomas Gleixner struct timerqueue_head *head;
7455e8c8ebSEric W. Biederman struct pid *pid;
7560bda037SThomas Gleixner struct list_head elist;
7660bda037SThomas Gleixner int firing;
77*f7abf14fSThomas Gleixner struct task_struct __rcu *handling;
7860bda037SThomas Gleixner };
7960bda037SThomas Gleixner
cpu_timer_enqueue(struct timerqueue_head * head,struct cpu_timer * ctmr)8060bda037SThomas Gleixner static inline bool cpu_timer_enqueue(struct timerqueue_head *head,
8160bda037SThomas Gleixner struct cpu_timer *ctmr)
8260bda037SThomas Gleixner {
8360bda037SThomas Gleixner ctmr->head = head;
8460bda037SThomas Gleixner return timerqueue_add(head, &ctmr->node);
8560bda037SThomas Gleixner }
8660bda037SThomas Gleixner
cpu_timer_queued(struct cpu_timer * ctmr)87ee375328SFrederic Weisbecker static inline bool cpu_timer_queued(struct cpu_timer *ctmr)
88ee375328SFrederic Weisbecker {
89ee375328SFrederic Weisbecker return !!ctmr->head;
90ee375328SFrederic Weisbecker }
91ee375328SFrederic Weisbecker
cpu_timer_dequeue(struct cpu_timer * ctmr)92175cc3abSFrederic Weisbecker static inline bool cpu_timer_dequeue(struct cpu_timer *ctmr)
9360bda037SThomas Gleixner {
94ee375328SFrederic Weisbecker if (cpu_timer_queued(ctmr)) {
9560bda037SThomas Gleixner timerqueue_del(ctmr->head, &ctmr->node);
9600d9e47fSThomas Gleixner ctmr->head = NULL;
97175cc3abSFrederic Weisbecker return true;
9800d9e47fSThomas Gleixner }
99175cc3abSFrederic Weisbecker return false;
10060bda037SThomas Gleixner }
10160bda037SThomas Gleixner
cpu_timer_getexpires(struct cpu_timer * ctmr)10260bda037SThomas Gleixner static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr)
10360bda037SThomas Gleixner {
10460bda037SThomas Gleixner return ctmr->node.expires;
10560bda037SThomas Gleixner }
10660bda037SThomas Gleixner
cpu_timer_setexpires(struct cpu_timer * ctmr,u64 exp)10760bda037SThomas Gleixner static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp)
10860bda037SThomas Gleixner {
10960bda037SThomas Gleixner ctmr->node.expires = exp;
11060bda037SThomas Gleixner }
11160bda037SThomas Gleixner
11260bda037SThomas Gleixner /**
11387dc6448SThomas Gleixner * posix_cputimer_base - Container per posix CPU clock
11487dc6448SThomas Gleixner * @nextevt: Earliest-expiration cache
11560bda037SThomas Gleixner * @tqhead: timerqueue head for cpu_timers
11687dc6448SThomas Gleixner */
11787dc6448SThomas Gleixner struct posix_cputimer_base {
11887dc6448SThomas Gleixner u64 nextevt;
11960bda037SThomas Gleixner struct timerqueue_head tqhead;
12087dc6448SThomas Gleixner };
12187dc6448SThomas Gleixner
1222b69942fSThomas Gleixner /**
1232b69942fSThomas Gleixner * posix_cputimers - Container for posix CPU timer related data
12487dc6448SThomas Gleixner * @bases: Base container for posix CPU clocks
125244d49e3SThomas Gleixner * @timers_active: Timers are queued.
126244d49e3SThomas Gleixner * @expiry_active: Timer expiry is active. Used for
127244d49e3SThomas Gleixner * process wide timers to avoid multiple
128244d49e3SThomas Gleixner * task trying to handle expiry concurrently
1292b69942fSThomas Gleixner *
1302b69942fSThomas Gleixner * Used in task_struct and signal_struct
1312b69942fSThomas Gleixner */
1322b69942fSThomas Gleixner struct posix_cputimers {
13387dc6448SThomas Gleixner struct posix_cputimer_base bases[CPUCLOCK_MAX];
134244d49e3SThomas Gleixner unsigned int timers_active;
135244d49e3SThomas Gleixner unsigned int expiry_active;
1362b69942fSThomas Gleixner };
1372b69942fSThomas Gleixner
1381fb497ddSThomas Gleixner /**
1391fb497ddSThomas Gleixner * posix_cputimers_work - Container for task work based posix CPU timer expiry
1401fb497ddSThomas Gleixner * @work: The task work to be scheduled
141*f7abf14fSThomas Gleixner * @mutex: Mutex held around expiry in context of this task work
1421fb497ddSThomas Gleixner * @scheduled: @work has been scheduled already, no further processing
1431fb497ddSThomas Gleixner */
1441fb497ddSThomas Gleixner struct posix_cputimers_work {
1451fb497ddSThomas Gleixner struct callback_head work;
146*f7abf14fSThomas Gleixner struct mutex mutex;
1471fb497ddSThomas Gleixner unsigned int scheduled;
1481fb497ddSThomas Gleixner };
1491fb497ddSThomas Gleixner
posix_cputimers_init(struct posix_cputimers * pct)1502b69942fSThomas Gleixner static inline void posix_cputimers_init(struct posix_cputimers *pct)
1512b69942fSThomas Gleixner {
15260bda037SThomas Gleixner memset(pct, 0, sizeof(*pct));
1532bbdbdaeSThomas Gleixner pct->bases[0].nextevt = U64_MAX;
1542bbdbdaeSThomas Gleixner pct->bases[1].nextevt = U64_MAX;
1552bbdbdaeSThomas Gleixner pct->bases[2].nextevt = U64_MAX;
1562b69942fSThomas Gleixner }
1572b69942fSThomas Gleixner
1583a245c0fSThomas Gleixner void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
1593a245c0fSThomas Gleixner
posix_cputimers_rt_watchdog(struct posix_cputimers * pct,u64 runtime)1603a245c0fSThomas Gleixner static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
1613a245c0fSThomas Gleixner u64 runtime)
1623a245c0fSThomas Gleixner {
16387dc6448SThomas Gleixner pct->bases[CPUCLOCK_SCHED].nextevt = runtime;
1643a245c0fSThomas Gleixner }
1653a245c0fSThomas Gleixner
1662b69942fSThomas Gleixner /* Init task static initializer */
16787dc6448SThomas Gleixner #define INIT_CPU_TIMERBASE(b) { \
1682bbdbdaeSThomas Gleixner .nextevt = U64_MAX, \
16987dc6448SThomas Gleixner }
17087dc6448SThomas Gleixner
17187dc6448SThomas Gleixner #define INIT_CPU_TIMERBASES(b) { \
17287dc6448SThomas Gleixner INIT_CPU_TIMERBASE(b[0]), \
17387dc6448SThomas Gleixner INIT_CPU_TIMERBASE(b[1]), \
17487dc6448SThomas Gleixner INIT_CPU_TIMERBASE(b[2]), \
1752b69942fSThomas Gleixner }
1762b69942fSThomas Gleixner
1772b69942fSThomas Gleixner #define INIT_CPU_TIMERS(s) \
1782b69942fSThomas Gleixner .posix_cputimers = { \
17987dc6448SThomas Gleixner .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \
1802b69942fSThomas Gleixner },
1812b69942fSThomas Gleixner #else
1822b69942fSThomas Gleixner struct posix_cputimers { };
1838f2edb4aSThomas Gleixner struct cpu_timer { };
1842b69942fSThomas Gleixner #define INIT_CPU_TIMERS(s)
posix_cputimers_init(struct posix_cputimers * pct)1853a245c0fSThomas Gleixner static inline void posix_cputimers_init(struct posix_cputimers *pct) { }
posix_cputimers_group_init(struct posix_cputimers * pct,u64 cpu_limit)1863a245c0fSThomas Gleixner static inline void posix_cputimers_group_init(struct posix_cputimers *pct,
1873a245c0fSThomas Gleixner u64 cpu_limit) { }
1882b69942fSThomas Gleixner #endif
1892b69942fSThomas Gleixner
1901fb497ddSThomas Gleixner #ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK
191ca7752caSMichael Pratt void clear_posix_cputimers_work(struct task_struct *p);
1921fb497ddSThomas Gleixner void posix_cputimers_init_work(void);
1931fb497ddSThomas Gleixner #else
clear_posix_cputimers_work(struct task_struct * p)194ca7752caSMichael Pratt static inline void clear_posix_cputimers_work(struct task_struct *p) { }
posix_cputimers_init_work(void)1951fb497ddSThomas Gleixner static inline void posix_cputimers_init_work(void) { }
1961fb497ddSThomas Gleixner #endif
1971fb497ddSThomas Gleixner
19803676b41SThomas Gleixner #define REQUEUE_PENDING 1
19903676b41SThomas Gleixner
20003676b41SThomas Gleixner /**
20103676b41SThomas Gleixner * struct k_itimer - POSIX.1b interval timer structure.
20203676b41SThomas Gleixner * @list: List head for binding the timer to signals->posix_timers
20303676b41SThomas Gleixner * @t_hash: Entry in the posix timer hash table
20403676b41SThomas Gleixner * @it_lock: Lock protecting the timer
205d97bb75dSThomas Gleixner * @kclock: Pointer to the k_clock struct handling this timer
20603676b41SThomas Gleixner * @it_clock: The posix timer clock id
20703676b41SThomas Gleixner * @it_id: The posix timer id for identifying the timer
20821e55c1fSThomas Gleixner * @it_active: Marker that timer is active
20903676b41SThomas Gleixner * @it_overrun: The overrun counter for pending signals
21003676b41SThomas Gleixner * @it_overrun_last: The overrun at the time of the last delivered signal
21103676b41SThomas Gleixner * @it_requeue_pending: Indicator that timer waits for being requeued on
21203676b41SThomas Gleixner * signal delivery
21303676b41SThomas Gleixner * @it_sigev_notify: The notify word of sigevent struct for signal delivery
21480105cd0SThomas Gleixner * @it_interval: The interval for periodic timers
21503676b41SThomas Gleixner * @it_signal: Pointer to the creators signal struct
21603676b41SThomas Gleixner * @it_pid: The pid of the process/task targeted by the signal
21703676b41SThomas Gleixner * @it_process: The task to wakeup on clock_nanosleep (CPU timers)
21803676b41SThomas Gleixner * @sigq: Pointer to preallocated sigqueue
21903676b41SThomas Gleixner * @it: Union representing the various posix timer type
2205d99b32aSSebastian Andrzej Siewior * internals.
2215d99b32aSSebastian Andrzej Siewior * @rcu: RCU head for freeing the timer.
22203676b41SThomas Gleixner */
2231da177e4SLinus Torvalds struct k_itimer {
22403676b41SThomas Gleixner struct list_head list;
2255ed67f05SPavel Emelyanov struct hlist_node t_hash;
2261da177e4SLinus Torvalds spinlock_t it_lock;
227d97bb75dSThomas Gleixner const struct k_clock *kclock;
22803676b41SThomas Gleixner clockid_t it_clock;
22903676b41SThomas Gleixner timer_t it_id;
23021e55c1fSThomas Gleixner int it_active;
23178c9c4dfSThomas Gleixner s64 it_overrun;
23278c9c4dfSThomas Gleixner s64 it_overrun_last;
23303676b41SThomas Gleixner int it_requeue_pending;
23403676b41SThomas Gleixner int it_sigev_notify;
23580105cd0SThomas Gleixner ktime_t it_interval;
23627af4245SOleg Nesterov struct signal_struct *it_signal;
23727af4245SOleg Nesterov union {
23803676b41SThomas Gleixner struct pid *it_pid;
23903676b41SThomas Gleixner struct task_struct *it_process;
24027af4245SOleg Nesterov };
24103676b41SThomas Gleixner struct sigqueue *sigq;
2421da177e4SLinus Torvalds union {
2431da177e4SLinus Torvalds struct {
244becf8b5dSThomas Gleixner struct hrtimer timer;
2451da177e4SLinus Torvalds } real;
24660bda037SThomas Gleixner struct cpu_timer cpu;
2471da177e4SLinus Torvalds struct {
2489a7adcf5SJohn Stultz struct alarm alarmtimer;
2499e264762SJohn Stultz } alarm;
2501da177e4SLinus Torvalds } it;
2515d99b32aSSebastian Andrzej Siewior struct rcu_head rcu;
2521da177e4SLinus Torvalds };
2531da177e4SLinus Torvalds
254dce3e8fdSThomas Gleixner void run_posix_cpu_timers(void);
2552a698971SThomas Gleixner void posix_cpu_timers_exit(struct task_struct *task);
2562a698971SThomas Gleixner void posix_cpu_timers_exit_group(struct task_struct *task);
2572a698971SThomas Gleixner void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
258858cf3a8SFrederic Weisbecker u64 *newval, u64 *oldval);
2591da177e4SLinus Torvalds
26018c91bb2SBarret Rhoden int update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
261f06febc9SFrank Mayhar
262ae7795bcSEric W. Biederman void posixtimer_rearm(struct kernel_siginfo *info);
2631da177e4SLinus Torvalds #endif
264