History

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 ...

Linus Torvalds committed 7 years ago

Commit 7f2444d2 parents c5f12fd 77b4b5461 files · +1476 −895Browse files

Showing the changes to include/linux (11 of 61 files). Show all

Unified · Split

11 files
  1. include/linux/alarmtimer.h +2 −1
  2. include/linux/hrtimer.h +44 −4
  3. include/linux/init_task.h +0 −11
  4. include/linux/posix-timers.h +117 −14
  5. include/linux/sched.h +4 −25
  6. include/linux/sched/cputime.h +7 −5
  7. include/linux/sched/signal.h +3 −11
  8. include/linux/sched/types.h +23 −0
  9. include/linux/timer.h +1 −1
  10. include/linux/timerqueue.h +16 −7
  11. include/linux/wait.h +2 −2
include/linux/alarmtimer.h+2−1
@@ -5,7 +5,8 @@ · 4 unmodified lines
55 #include <linux/time.h>
66 #include <linux/hrtimer.h>
77 #include <linux/timerqueue.h>
8−#include <linux/rtc.h>
8+
9+struct rtc_device;
910
1011 enum alarmtimer_type {
1112 ALARM_REALTIME,
include/linux/hrtimer.h+44−4
@@ -32,12 +32,15 @@ struct hrtimer_cpu_base; · 31 unmodified lines
3232 * when starting the timer)
3333 * HRTIMER_MODE_SOFT - Timer callback function will be executed in
3434 * soft irq context
35+ * HRTIMER_MODE_HARD - Timer callback function will be executed in
36+ * hard irq context even on PREEMPT_RT.
3537 */
3638 enum hrtimer_mode {
3739 HRTIMER_MODE_ABS = 0x00,
3840 HRTIMER_MODE_REL = 0x01,
3941 HRTIMER_MODE_PINNED = 0x02,
4042 HRTIMER_MODE_SOFT = 0x04,
43+ HRTIMER_MODE_HARD = 0x08,
4144
4245 HRTIMER_MODE_ABS_PINNED = HRTIMER_MODE_ABS | HRTIMER_MODE_PINNED,
4346 HRTIMER_MODE_REL_PINNED = HRTIMER_MODE_REL | HRTIMER_MODE_PINNED,
@@ -48,6 +51,11 @@ enum hrtimer_mode { · 4 unmodified lines
4851 HRTIMER_MODE_ABS_PINNED_SOFT = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_SOFT,
4952 HRTIMER_MODE_REL_PINNED_SOFT = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_SOFT,
5053
54+ HRTIMER_MODE_ABS_HARD = HRTIMER_MODE_ABS | HRTIMER_MODE_HARD,
55+ HRTIMER_MODE_REL_HARD = HRTIMER_MODE_REL | HRTIMER_MODE_HARD,
56+
57+ HRTIMER_MODE_ABS_PINNED_HARD = HRTIMER_MODE_ABS_PINNED | HRTIMER_MODE_HARD,
58+ HRTIMER_MODE_REL_PINNED_HARD = HRTIMER_MODE_REL_PINNED | HRTIMER_MODE_HARD,
5159 };
5260
5361 /*
@@ -101,6 +109,8 @@ enum hrtimer_restart { · 47 unmodified lines
101109 * @state: state information (See bit values above)
102110 * @is_rel: Set if the timer was armed relative
103111 * @is_soft: Set if hrtimer will be expired in soft interrupt context.
112+ * @is_hard: Set if hrtimer will be expired in hard interrupt context
113+ * even on RT.
104114 *
105115 * The hrtimer structure must be initialized by hrtimer_init()
106116 */
@@ -112,6 +122,7 @@ struct hrtimer { · 5 unmodified lines
112122 u8 state;
113123 u8 is_rel;
114124 u8 is_soft;
125+ u8 is_hard;
115126 };
116127
117128 /**
@@ -183,6 +194,10 @@ enum hrtimer_base_type { · 65 unmodified lines
183194 * @nr_retries: Total number of hrtimer interrupt retries
184195 * @nr_hangs: Total number of hrtimer interrupt hangs
185196 * @max_hang_time: Maximum time spent in hrtimer_interrupt
197+ * @softirq_expiry_lock: Lock which is taken while softirq based hrtimer are
198+ * expired
199+ * @timer_waiters: A hrtimer_cancel() invocation waits for the timer
200+ * callback to finish.
186201 * @expires_next: absolute time of the next event, is required for remote
187202 * hrtimer enqueue; it is the total first expiry time (hard
188203 * and soft hrtimer are taken into account)
@@ -209,6 +224,10 @@ struct hrtimer_cpu_base { · 20 unmodified lines
209224 unsigned short nr_retries;
210225 unsigned short nr_hangs;
211226 unsigned int max_hang_time;
227+#endif
228+#ifdef CONFIG_PREEMPT_RT
229+ spinlock_t softirq_expiry_lock;
230+ atomic_t timer_waiters;
212231 #endif
213232 ktime_t expires_next;
214233 struct hrtimer *next_timer;
@@ -341,16 +360,29 @@ extern void hrtimers_resume(void); · 126 unmodified lines
341360
342361 DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
343362
363+#ifdef CONFIG_PREEMPT_RT
364+void hrtimer_cancel_wait_running(const struct hrtimer *timer);
365+#else
366+static inline void hrtimer_cancel_wait_running(struct hrtimer *timer)
367+{
368+ cpu_relax();
369+}
370+#endif
344371
345372 /* Exported timer functions: */
346373
347374 /* Initialize timers: */
348375 extern void hrtimer_init(struct hrtimer *timer, clockid_t which_clock,
349376 enum hrtimer_mode mode);
377+extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, clockid_t clock_id,
378+ enum hrtimer_mode mode);
350379
351380 #ifdef CONFIG_DEBUG_OBJECTS_TIMERS
352381 extern void hrtimer_init_on_stack(struct hrtimer *timer, clockid_t which_clock,
353382 enum hrtimer_mode mode);
383+extern void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl,
384+ clockid_t clock_id,
385+ enum hrtimer_mode mode);
354386
355387 extern void destroy_hrtimer_on_stack(struct hrtimer *timer);
356388 #else
@@ -360,6 +392,14 @@ static inline void hrtimer_init_on_stack(struct hrtimer *timer, · 3 unmodified lines
360392 {
361393 hrtimer_init(timer, which_clock, mode);
362394 }
395+
396+static inline void hrtimer_init_sleeper_on_stack(struct hrtimer_sleeper *sl,
397+ clockid_t clock_id,
398+ enum hrtimer_mode mode)
399+{
400+ hrtimer_init_sleeper(sl, clock_id, mode);
401+}
402+
363403 static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { }
364404 #endif
365405
@@ -395,6 +435,9 @@ static inline void hrtimer_start_expires(struct hrtimer *timer, · 29 unmodified lines
395435 hrtimer_start_range_ns(timer, soft, delta, mode);
396436 }
397437
438+void hrtimer_sleeper_start_expires(struct hrtimer_sleeper *sl,
439+ enum hrtimer_mode mode);
440+
398441 static inline void hrtimer_restart(struct hrtimer *timer)
399442 {
400443 hrtimer_start_expires(timer, HRTIMER_MODE_ABS);
@@ -463,11 +506,8 @@ extern long hrtimer_nanosleep(const struct timespec64 *rqtp, · 62 unmodified lines
463506 const enum hrtimer_mode mode,
464507 const clockid_t clockid);
465508
466−extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
467− struct task_struct *tsk);
468−
469509 extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta,
470− const enum hrtimer_mode mode);
510+ const enum hrtimer_mode mode);
471511 extern int schedule_hrtimeout_range_clock(ktime_t *expires,
472512 u64 delta,
473513 const enum hrtimer_mode mode,
include/linux/init_task.h+0−11
@@ -36,17 +36,6 @@ extern struct cred init_cred; · 35 unmodified lines
3636 #define INIT_PREV_CPUTIME(x)
3737 #endif
3838
39−#ifdef CONFIG_POSIX_TIMERS
40−#define INIT_CPU_TIMERS(s) \
41− .cpu_timers = { \
42− LIST_HEAD_INIT(s.cpu_timers[0]), \
43− LIST_HEAD_INIT(s.cpu_timers[1]), \
44− LIST_HEAD_INIT(s.cpu_timers[2]), \
45− },
46−#else
47−#define INIT_CPU_TIMERS(s)
48−#endif
49−
5039 #define INIT_TASK_COMM "swapper"
5140
5241 /* Attach to the init_task data structure for proper alignment */
include/linux/posix-timers.h+117−14
@@ -4,18 +4,11 @@ · 3 unmodified lines
44
55 #include <linux/spinlock.h>
66 #include <linux/list.h>
7−#include <linux/sched.h>
8−#include <linux/timex.h>
97 #include <linux/alarmtimer.h>
8+#include <linux/timerqueue.h>
109
11−struct siginfo;
12−
13−struct cpu_timer_list {
14− struct list_head entry;
15− u64 expires;
16− struct task_struct *task;
17− int firing;
18−};
10+struct kernel_siginfo;
11+struct task_struct;
1912
2013 /*
2114 * Bit fields within a clockid:
@@ -63,6 +56,115 @@ static inline int clockid_to_fd(const clockid_t clk) · 41 unmodified lines
6356 return ~(clk >> 3);
6457 }
6558
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+
66168 #define REQUEUE_PENDING 1
67169
68170 /**
@@ -85,7 +187,8 @@ static inline int clockid_to_fd(const clockid_t clk) · 16 unmodified lines
85187 * @it_process: The task to wakeup on clock_nanosleep (CPU timers)
86188 * @sigq: Pointer to preallocated sigqueue
87189 * @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.
89192 */
90193 struct k_itimer {
91194 struct list_head list;
@@ -110,15 +213,15 @@ struct k_itimer { · 18 unmodified lines
110213 struct {
111214 struct hrtimer timer;
112215 } real;
113− struct cpu_timer_list cpu;
216+ struct cpu_timer cpu;
114217 struct {
115218 struct alarm alarmtimer;
116219 } alarm;
117− struct rcu_head rcu;
118220 } it;
221+ struct rcu_head rcu;
119222 };
120223
121−void run_posix_cpu_timers(struct task_struct *task);
224+void run_posix_cpu_timers(void);
122225 void posix_cpu_timers_exit(struct task_struct *task);
123226 void posix_cpu_timers_exit_group(struct task_struct *task);
124227 void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
include/linux/sched.h+4−25
@@ -25,9 +25,11 @@ · 24 unmodified lines
2525 #include <linux/resource.h>
2626 #include <linux/latencytop.h>
2727 #include <linux/sched/prio.h>
28+#include <linux/sched/types.h>
2829 #include <linux/signal_types.h>
2930 #include <linux/mm_types_task.h>
3031 #include <linux/task_io_accounting.h>
32+#include <linux/posix-timers.h>
3133 #include <linux/rseq.h>
3234
3335 /* task_struct member predeclarations (sorted alphabetically): */
@@ -244,27 +246,6 @@ struct prev_cputime { · 210 unmodified lines
244246 #endif
245247 };
246248
247−/**
248− * struct task_cputime - collected CPU time counts
249− * @utime: time spent in user mode, in nanoseconds
250− * @stime: time spent in kernel mode, in nanoseconds
251− * @sum_exec_runtime: total time spent on the CPU, in nanoseconds
252− *
253− * This structure groups together three kinds of CPU time that are tracked for
254− * threads and thread groups. Most things considering CPU time want to group
255− * these counts together and treat all three of them in parallel.
256− */
257−struct task_cputime {
258− u64 utime;
259− u64 stime;
260− unsigned long long sum_exec_runtime;
261−};
262−
263−/* Alternate field names when used on cache expirations: */
264−#define virt_exp utime
265−#define prof_exp stime
266−#define sched_exp sum_exec_runtime
267−
268249 enum vtime_state {
269250 /* Task is sleeping or running in a CPU with VTIME inactive: */
270251 VTIME_INACTIVE = 0,
@@ -881,10 +862,8 @@ struct task_struct { · 610 unmodified lines
881862 unsigned long min_flt;
882863 unsigned long maj_flt;
883864
884−#ifdef CONFIG_POSIX_TIMERS
885− struct task_cputime cputime_expires;
886− struct list_head cpu_timers[3];
887−#endif
865+ /* Empty if CONFIG_POSIX_CPUTIMERS=n */
866+ struct posix_cputimers posix_cputimers;
888867
889868 /* Process credentials: */
890869
include/linux/sched/cputime.h+7−5
@@ -61,8 +61,7 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, · 60 unmodified lines
6161 * Thread group CPU time accounting.
6262 */
6363 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
64−void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
65−
64+void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples);
6665
6766 /*
6867 * The following are functions that support scheduler-internal time accounting.
@@ -71,7 +70,7 @@ void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times); · 2 unmodified lines
7170 */
7271
7372 /**
74− * get_running_cputimer - return &tsk->signal->cputimer if cputimer is running
73+ * get_running_cputimer - return &tsk->signal->cputimer if cputimers are active
7574 *
7675 * @tsk: Pointer to target task.
7776 */
@@ -81,8 +80,11 @@ struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk) · 3 unmodified lines
8180 {
8281 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
8382
84− /* Check if cputimer isn't running. This is accessed without locking. */
85− if (!READ_ONCE(cputimer->running))
83+ /*
84+ * Check whether posix CPU timers are active. If not the thread
85+ * group accounting is not active either. Lockless check.
86+ */
87+ if (!READ_ONCE(tsk->signal->posix_cputimers.timers_active))
8688 return NULL;
8789
8890 /*
include/linux/sched/signal.h+3−11
@@ -9,6 +9,7 @@ · 8 unmodified lines
99 #include <linux/sched/task.h>
1010 #include <linux/cred.h>
1111 #include <linux/refcount.h>
12+#include <linux/posix-timers.h>
1213
1314 /*
1415 * Types defining task->signal and task->sighand and APIs using them:
@@ -56,18 +57,12 @@ struct task_cputime_atomic { · 41 unmodified lines
5657 /**
5758 * struct thread_group_cputimer - thread group interval timer counts
5859 * @cputime_atomic: atomic thread group interval timers.
59− * @running: true when there are timers running and
60− * @cputime_atomic receives updates.
61− * @checking_timer: true when a thread in the group is in the
62− * process of checking for thread group timers.
6360 *
6461 * This structure contains the version of task_cputime, above, that is
6562 * used for thread group CPU timer calculations.
6663 */
6764 struct thread_group_cputimer {
6865 struct task_cputime_atomic cputime_atomic;
69− bool running;
70− bool checking_timer;
7166 };
7267
7368 struct multiprocess_signals {
@@ -148,12 +143,9 @@ struct signal_struct { · 74 unmodified lines
148143 */
149144 struct thread_group_cputimer cputimer;
150145
151− /* Earliest-expiration cache. */
152− struct task_cputime cputime_expires;
153−
154− struct list_head cpu_timers[3];
155−
156146 #endif
147+ /* Empty if CONFIG_POSIX_TIMERS=n */
148+ struct posix_cputimers posix_cputimers;
157149
158150 /* PID/PID hash table linkage. */
159151 struct pid *pids[PIDTYPE_MAX];
include/linux/sched/types.h+23−0
@@ -0,0 +1,23 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+#ifndef _LINUX_SCHED_TYPES_H
3+#define _LINUX_SCHED_TYPES_H
4+
5+#include <linux/types.h>
6+
7+/**
8+ * struct task_cputime - collected CPU time counts
9+ * @stime: time spent in kernel mode, in nanoseconds
10+ * @utime: time spent in user mode, in nanoseconds
11+ * @sum_exec_runtime: total time spent on the CPU, in nanoseconds
12+ *
13+ * This structure groups together three kinds of CPU time that are tracked for
14+ * threads and thread groups. Most things considering CPU time want to group
15+ * these counts together and treat all three of them in parallel.
16+ */
17+struct task_cputime {
18+ u64 stime;
19+ u64 utime;
20+ unsigned long long sum_exec_runtime;
21+};
22+
23+#endif
include/linux/timer.h+1−1
@@ -183,7 +183,7 @@ extern void add_timer(struct timer_list *timer); · 182 unmodified lines
183183
184184 extern int try_to_del_timer_sync(struct timer_list *timer);
185185
186−#ifdef CONFIG_SMP
186+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT)
187187 extern int del_timer_sync(struct timer_list *timer);
188188 #else
189189 # define del_timer_sync(t) del_timer(t)
include/linux/timerqueue.h+16−7
@@ -12,8 +12,7 @@ struct timerqueue_node { · 11 unmodified lines
1212 };
1313
1414 struct timerqueue_head {
15− struct rb_root head;
16− struct timerqueue_node *next;
15+ struct rb_root_cached rb_root;
1716 };
1817
1918
@@ -29,13 +28,14 @@ extern struct timerqueue_node *timerqueue_iterate_next( · 9 unmodified lines
2928 *
3029 * @head: head of timerqueue
3130 *
32− * Returns a pointer to the timer node that has the
33− * earliest expiration time.
31+ * Returns a pointer to the timer node that has the earliest expiration time.
3432 */
3533 static inline
3634 struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head)
3735 {
38− return head->next;
36+ struct rb_node *leftmost = rb_first_cached(&head->rb_root);
37+
38+ return rb_entry(leftmost, struct timerqueue_node, node);
3939 }
4040
4141 static inline void timerqueue_init(struct timerqueue_node *node)
@@ -43,9 +43,18 @@ static inline void timerqueue_init(struct timerqueue_node *node) · 1 unmodified line
4343 RB_CLEAR_NODE(&node->node);
4444 }
4545
46+static inline bool timerqueue_node_queued(struct timerqueue_node *node)
47+{
48+ return !RB_EMPTY_NODE(&node->node);
49+}
50+
51+static inline bool timerqueue_node_expires(struct timerqueue_node *node)
52+{
53+ return node->expires;
54+}
55+
4656 static inline void timerqueue_init_head(struct timerqueue_head *head)
4757 {
48− head->head = RB_ROOT;
49− head->next = NULL;
58+ head->rb_root = RB_ROOT_CACHED;
5059 }
5160 #endif /* _LINUX_TIMERQUEUE_H */
include/linux/wait.h+2−2
@@ -501,8 +501,8 @@ do { \ · 500 unmodified lines
501501 int __ret = 0; \
502502 struct hrtimer_sleeper __t; \
503503 \
504− hrtimer_init_on_stack(&__t.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); \
505− hrtimer_init_sleeper(&__t, current); \
504+ hrtimer_init_sleeper_on_stack(&__t, CLOCK_MONOTONIC, \
505+ HRTIMER_MODE_REL); \
506506 if ((timeout) != KTIME_MAX) \
507507 hrtimer_start_range_ns(&__t.timer, timeout, \
508508 current->timer_slack_ns, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t