xref: /openbmc/linux/include/linux/posix-timers.h (revision f7abf14f)
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