diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-17 15:35:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-17 15:35:15 -0400 |
commit | 7f2444d38f6bbfa12bc15e2533d8f9daa85ca02b (patch) | |
tree | 6506ec79036890edfd9797b001391a350b5ac10f /include/linux/posix-timers.h | |
parent | c5f12fdb8bd873aa3ffdb79512e6bdac92b257b0 (diff) | |
parent | 77b4b5420422fc037d00b8f3f0e89b2262e4ae29 (diff) |
Merge branch 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull core timer updates from Thomas Gleixner:
"Timers and timekeeping updates:
- A large overhaul of the posix CPU timer code which is a preparation
for moving the CPU timer expiry out into task work so it can be
properly accounted on the task/process.
An update to the bogus permission checks will come later during the
merge window as feedback was not complete before heading of for
travel.
- Switch the timerqueue code to use cached rbtrees and get rid of the
homebrewn caching of the leftmost node.
- Consolidate hrtimer_init() + hrtimer_init_sleeper() calls into a
single function
- Implement the separation of hrtimers to be forced to expire in hard
interrupt context even when PREEMPT_RT is enabled and mark the
affected timers accordingly.
- Implement a mechanism for hrtimers and the timer wheel to protect
RT against priority inversion and live lock issues when a (hr)timer
which should be canceled is currently executing the callback.
Instead of infinitely spinning, the task which tries to cancel the
timer blocks on a per cpu base expiry lock which is held and
released by the (hr)timer expiry code.
- Enable the Hyper-V TSC page based sched_clock for Hyper-V guests
resulting in faster access to timekeeping functions.
- Updates to various clocksource/clockevent drivers and their device
tree bindings.
- The usual small improvements all over the place"
* 'timers-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (101 commits)
posix-cpu-timers: Fix permission check regression
posix-cpu-timers: Always clear head pointer on dequeue
hrtimer: Add a missing bracket and hide `migration_base' on !SMP
posix-cpu-timers: Make expiry_active check actually work correctly
posix-timers: Unbreak CONFIG_POSIX_TIMERS=n build
tick: Mark sched_timer to expire in hard interrupt context
hrtimer: Add kernel doc annotation for HRTIMER_MODE_HARD
x86/hyperv: Hide pv_ops access for CONFIG_PARAVIRT=n
posix-cpu-timers: Utilize timerqueue for storage
posix-cpu-timers: Move state tracking to struct posix_cputimers
posix-cpu-timers: Deduplicate rlimit handling
posix-cpu-timers: Remove pointless comparisons
posix-cpu-timers: Get rid of 64bit divisions
posix-cpu-timers: Consolidate timer expiry further
posix-cpu-timers: Get rid of zero checks
rlimit: Rewrite non-sensical RLIMIT_CPU comment
posix-cpu-timers: Respect INFINITY for hard RTTIME limit
posix-cpu-timers: Switch thread group sampling to array
posix-cpu-timers: Restructure expiry array
posix-cpu-timers: Remove cputime_expires
...
Diffstat (limited to 'include/linux/posix-timers.h')
-rw-r--r-- | include/linux/posix-timers.h | 131 |
1 files changed, 117 insertions, 14 deletions
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index b20798fc5191..3d10c84a97a9 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h | |||
@@ -4,18 +4,11 @@ | |||
4 | 4 | ||
5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
6 | #include <linux/list.h> | 6 | #include <linux/list.h> |
7 | #include <linux/sched.h> | ||
8 | #include <linux/timex.h> | ||
9 | #include <linux/alarmtimer.h> | 7 | #include <linux/alarmtimer.h> |
8 | #include <linux/timerqueue.h> | ||
10 | 9 | ||
11 | struct siginfo; | 10 | struct kernel_siginfo; |
12 | 11 | struct task_struct; | |
13 | struct cpu_timer_list { | ||
14 | struct list_head entry; | ||
15 | u64 expires; | ||
16 | struct task_struct *task; | ||
17 | int firing; | ||
18 | }; | ||
19 | 12 | ||
20 | /* | 13 | /* |
21 | * Bit fields within a clockid: | 14 | * Bit fields within a clockid: |
@@ -63,6 +56,115 @@ static inline int clockid_to_fd(const clockid_t clk) | |||
63 | return ~(clk >> 3); | 56 | return ~(clk >> 3); |
64 | } | 57 | } |
65 | 58 | ||
59 | #ifdef CONFIG_POSIX_TIMERS | ||
60 | |||
61 | /** | ||
62 | * cpu_timer - Posix CPU timer representation for k_itimer | ||
63 | * @node: timerqueue node to queue in the task/sig | ||
64 | * @head: timerqueue head on which this timer is queued | ||
65 | * @task: Pointer to target task | ||
66 | * @elist: List head for the expiry list | ||
67 | * @firing: Timer is currently firing | ||
68 | */ | ||
69 | struct cpu_timer { | ||
70 | struct timerqueue_node node; | ||
71 | struct timerqueue_head *head; | ||
72 | struct task_struct *task; | ||
73 | struct list_head elist; | ||
74 | int firing; | ||
75 | }; | ||
76 | |||
77 | static inline bool cpu_timer_enqueue(struct timerqueue_head *head, | ||
78 | struct cpu_timer *ctmr) | ||
79 | { | ||
80 | ctmr->head = head; | ||
81 | return timerqueue_add(head, &ctmr->node); | ||
82 | } | ||
83 | |||
84 | static inline void cpu_timer_dequeue(struct cpu_timer *ctmr) | ||
85 | { | ||
86 | if (ctmr->head) { | ||
87 | timerqueue_del(ctmr->head, &ctmr->node); | ||
88 | ctmr->head = NULL; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr) | ||
93 | { | ||
94 | return ctmr->node.expires; | ||
95 | } | ||
96 | |||
97 | static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp) | ||
98 | { | ||
99 | ctmr->node.expires = exp; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * posix_cputimer_base - Container per posix CPU clock | ||
104 | * @nextevt: Earliest-expiration cache | ||
105 | * @tqhead: timerqueue head for cpu_timers | ||
106 | */ | ||
107 | struct posix_cputimer_base { | ||
108 | u64 nextevt; | ||
109 | struct timerqueue_head tqhead; | ||
110 | }; | ||
111 | |||
112 | /** | ||
113 | * posix_cputimers - Container for posix CPU timer related data | ||
114 | * @bases: Base container for posix CPU clocks | ||
115 | * @timers_active: Timers are queued. | ||
116 | * @expiry_active: Timer expiry is active. Used for | ||
117 | * process wide timers to avoid multiple | ||
118 | * task trying to handle expiry concurrently | ||
119 | * | ||
120 | * Used in task_struct and signal_struct | ||
121 | */ | ||
122 | struct posix_cputimers { | ||
123 | struct posix_cputimer_base bases[CPUCLOCK_MAX]; | ||
124 | unsigned int timers_active; | ||
125 | unsigned int expiry_active; | ||
126 | }; | ||
127 | |||
128 | static inline void posix_cputimers_init(struct posix_cputimers *pct) | ||
129 | { | ||
130 | memset(pct, 0, sizeof(*pct)); | ||
131 | pct->bases[0].nextevt = U64_MAX; | ||
132 | pct->bases[1].nextevt = U64_MAX; | ||
133 | pct->bases[2].nextevt = U64_MAX; | ||
134 | } | ||
135 | |||
136 | void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit); | ||
137 | |||
138 | static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct, | ||
139 | u64 runtime) | ||
140 | { | ||
141 | pct->bases[CPUCLOCK_SCHED].nextevt = runtime; | ||
142 | } | ||
143 | |||
144 | /* Init task static initializer */ | ||
145 | #define INIT_CPU_TIMERBASE(b) { \ | ||
146 | .nextevt = U64_MAX, \ | ||
147 | } | ||
148 | |||
149 | #define INIT_CPU_TIMERBASES(b) { \ | ||
150 | INIT_CPU_TIMERBASE(b[0]), \ | ||
151 | INIT_CPU_TIMERBASE(b[1]), \ | ||
152 | INIT_CPU_TIMERBASE(b[2]), \ | ||
153 | } | ||
154 | |||
155 | #define INIT_CPU_TIMERS(s) \ | ||
156 | .posix_cputimers = { \ | ||
157 | .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ | ||
158 | }, | ||
159 | #else | ||
160 | struct posix_cputimers { }; | ||
161 | struct cpu_timer { }; | ||
162 | #define INIT_CPU_TIMERS(s) | ||
163 | static inline void posix_cputimers_init(struct posix_cputimers *pct) { } | ||
164 | static inline void posix_cputimers_group_init(struct posix_cputimers *pct, | ||
165 | u64 cpu_limit) { } | ||
166 | #endif | ||
167 | |||
66 | #define REQUEUE_PENDING 1 | 168 | #define REQUEUE_PENDING 1 |
67 | 169 | ||
68 | /** | 170 | /** |
@@ -85,7 +187,8 @@ static inline int clockid_to_fd(const clockid_t clk) | |||
85 | * @it_process: The task to wakeup on clock_nanosleep (CPU timers) | 187 | * @it_process: The task to wakeup on clock_nanosleep (CPU timers) |
86 | * @sigq: Pointer to preallocated sigqueue | 188 | * @sigq: Pointer to preallocated sigqueue |
87 | * @it: Union representing the various posix timer type | 189 | * @it: Union representing the various posix timer type |
88 | * internals. Also used for rcu freeing the timer. | 190 | * internals. |
191 | * @rcu: RCU head for freeing the timer. | ||
89 | */ | 192 | */ |
90 | struct k_itimer { | 193 | struct k_itimer { |
91 | struct list_head list; | 194 | struct list_head list; |
@@ -110,15 +213,15 @@ struct k_itimer { | |||
110 | struct { | 213 | struct { |
111 | struct hrtimer timer; | 214 | struct hrtimer timer; |
112 | } real; | 215 | } real; |
113 | struct cpu_timer_list cpu; | 216 | struct cpu_timer cpu; |
114 | struct { | 217 | struct { |
115 | struct alarm alarmtimer; | 218 | struct alarm alarmtimer; |
116 | } alarm; | 219 | } alarm; |
117 | struct rcu_head rcu; | ||
118 | } it; | 220 | } it; |
221 | struct rcu_head rcu; | ||
119 | }; | 222 | }; |
120 | 223 | ||
121 | void run_posix_cpu_timers(struct task_struct *task); | 224 | void run_posix_cpu_timers(void); |
122 | void posix_cpu_timers_exit(struct task_struct *task); | 225 | void posix_cpu_timers_exit(struct task_struct *task); |
123 | void posix_cpu_timers_exit_group(struct task_struct *task); | 226 | void posix_cpu_timers_exit_group(struct task_struct *task); |
124 | void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, | 227 | void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, |