summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2019-08-21 15:09:24 -0400
committerThomas Gleixner <tglx@linutronix.de>2019-08-28 05:50:42 -0400
commit244d49e30653658d4e7e9b2b8427777cbbc5affe (patch)
tree97754f775acd11c4bc98b43f69234dfb525cb175
parent8991afe2640d05a805eba01277856e8549cdc838 (diff)
posix-cpu-timers: Move state tracking to struct posix_cputimers
Put it where it belongs and clean up the ifdeffery in fork completely. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lkml.kernel.org/r/20190821192922.743229404@linutronix.de
-rw-r--r--include/linux/posix-timers.h8
-rw-r--r--include/linux/sched/cputime.h9
-rw-r--r--include/linux/sched/signal.h6
-rw-r--r--init/init_task.c2
-rw-r--r--kernel/fork.c6
-rw-r--r--kernel/time/posix-cpu-timers.c73
6 files changed, 54 insertions, 50 deletions
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3ea920e8fe7f..a9e3f69d2db4 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -77,15 +77,23 @@ struct posix_cputimer_base {
77/** 77/**
78 * posix_cputimers - Container for posix CPU timer related data 78 * posix_cputimers - Container for posix CPU timer related data
79 * @bases: Base container for posix CPU clocks 79 * @bases: Base container for posix CPU clocks
80 * @timers_active: Timers are queued.
81 * @expiry_active: Timer expiry is active. Used for
82 * process wide timers to avoid multiple
83 * task trying to handle expiry concurrently
80 * 84 *
81 * Used in task_struct and signal_struct 85 * Used in task_struct and signal_struct
82 */ 86 */
83struct posix_cputimers { 87struct posix_cputimers {
84 struct posix_cputimer_base bases[CPUCLOCK_MAX]; 88 struct posix_cputimer_base bases[CPUCLOCK_MAX];
89 unsigned int timers_active;
90 unsigned int expiry_active;
85}; 91};
86 92
87static inline void posix_cputimers_init(struct posix_cputimers *pct) 93static inline void posix_cputimers_init(struct posix_cputimers *pct)
88{ 94{
95 pct->timers_active = 0;
96 pct->expiry_active = 0;
89 pct->bases[0].nextevt = U64_MAX; 97 pct->bases[0].nextevt = U64_MAX;
90 pct->bases[1].nextevt = U64_MAX; 98 pct->bases[1].nextevt = U64_MAX;
91 pct->bases[2].nextevt = U64_MAX; 99 pct->bases[2].nextevt = U64_MAX;
diff --git a/include/linux/sched/cputime.h b/include/linux/sched/cputime.h
index eefa5dff16b4..6c9f19a33865 100644
--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -70,7 +70,7 @@ void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples);
70 */ 70 */
71 71
72/** 72/**
73 * get_running_cputimer - return &tsk->signal->cputimer if cputimer is running 73 * get_running_cputimer - return &tsk->signal->cputimer if cputimers are active
74 * 74 *
75 * @tsk: Pointer to target task. 75 * @tsk: Pointer to target task.
76 */ 76 */
@@ -80,8 +80,11 @@ struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk)
80{ 80{
81 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; 81 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
82 82
83 /* Check if cputimer isn't running. This is accessed without locking. */ 83 /*
84 if (!READ_ONCE(cputimer->running)) 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))
85 return NULL; 88 return NULL;
86 89
87 /* 90 /*
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 729bd892ee45..88050259c466 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -57,18 +57,12 @@ struct task_cputime_atomic {
57/** 57/**
58 * struct thread_group_cputimer - thread group interval timer counts 58 * struct thread_group_cputimer - thread group interval timer counts
59 * @cputime_atomic: atomic thread group interval timers. 59 * @cputime_atomic: atomic thread group interval timers.
60 * @running: true when there are timers running and
61 * @cputime_atomic receives updates.
62 * @checking_timer: true when a thread in the group is in the
63 * process of checking for thread group timers.
64 * 60 *
65 * This structure contains the version of task_cputime, above, that is 61 * This structure contains the version of task_cputime, above, that is
66 * used for thread group CPU timer calculations. 62 * used for thread group CPU timer calculations.
67 */ 63 */
68struct thread_group_cputimer { 64struct thread_group_cputimer {
69 struct task_cputime_atomic cputime_atomic; 65 struct task_cputime_atomic cputime_atomic;
70 bool running;
71 bool checking_timer;
72}; 66};
73 67
74struct multiprocess_signals { 68struct multiprocess_signals {
diff --git a/init/init_task.c b/init/init_task.c
index 7ab773b9b3cd..d49692a0ec51 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -30,8 +30,6 @@ static struct signal_struct init_signals = {
30 .posix_timers = LIST_HEAD_INIT(init_signals.posix_timers), 30 .posix_timers = LIST_HEAD_INIT(init_signals.posix_timers),
31 .cputimer = { 31 .cputimer = {
32 .cputime_atomic = INIT_CPUTIME_ATOMIC, 32 .cputime_atomic = INIT_CPUTIME_ATOMIC,
33 .running = false,
34 .checking_timer = false,
35 }, 33 },
36#endif 34#endif
37 INIT_CPU_TIMERS(init_signals) 35 INIT_CPU_TIMERS(init_signals)
diff --git a/kernel/fork.c b/kernel/fork.c
index 52bfe7c20ff6..f1228d9f0b11 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1517,7 +1517,6 @@ void __cleanup_sighand(struct sighand_struct *sighand)
1517 } 1517 }
1518} 1518}
1519 1519
1520#ifdef CONFIG_POSIX_TIMERS
1521/* 1520/*
1522 * Initialize POSIX timer handling for a thread group. 1521 * Initialize POSIX timer handling for a thread group.
1523 */ 1522 */
@@ -1528,12 +1527,7 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)
1528 1527
1529 cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur); 1528 cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
1530 posix_cputimers_group_init(pct, cpu_limit); 1529 posix_cputimers_group_init(pct, cpu_limit);
1531 if (cpu_limit != RLIM_INFINITY)
1532 sig->cputimer.running = true;
1533} 1530}
1534#else
1535static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
1536#endif
1537 1531
1538static int copy_signal(unsigned long clone_flags, struct task_struct *tsk) 1532static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
1539{ 1533{
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ef39a7a4a95c..52f4c99c1d60 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -23,8 +23,10 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer);
23void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit) 23void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
24{ 24{
25 posix_cputimers_init(pct); 25 posix_cputimers_init(pct);
26 if (cpu_limit != RLIM_INFINITY) 26 if (cpu_limit != RLIM_INFINITY) {
27 pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC; 27 pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC;
28 pct->timers_active = true;
29 }
28} 30}
29 31
30/* 32/*
@@ -248,8 +250,9 @@ static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic,
248void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples) 250void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
249{ 251{
250 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; 252 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
253 struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
251 254
252 WARN_ON_ONCE(!cputimer->running); 255 WARN_ON_ONCE(!pct->timers_active);
253 256
254 proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples); 257 proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
255} 258}
@@ -269,9 +272,10 @@ void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
269static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples) 272static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
270{ 273{
271 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; 274 struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
275 struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
272 276
273 /* Check if cputimer isn't running. This is accessed without locking. */ 277 /* Check if cputimer isn't running. This is accessed without locking. */
274 if (!READ_ONCE(cputimer->running)) { 278 if (!READ_ONCE(pct->timers_active)) {
275 struct task_cputime sum; 279 struct task_cputime sum;
276 280
277 /* 281 /*
@@ -283,13 +287,13 @@ static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
283 update_gt_cputime(&cputimer->cputime_atomic, &sum); 287 update_gt_cputime(&cputimer->cputime_atomic, &sum);
284 288
285 /* 289 /*
286 * We're setting cputimer->running without a lock. Ensure 290 * We're setting timers_active without a lock. Ensure this
287 * this only gets written to in one operation. We set 291 * only gets written to in one operation. We set it after
288 * running after update_gt_cputime() as a small optimization, 292 * update_gt_cputime() as a small optimization, but
289 * but barriers are not required because update_gt_cputime() 293 * barriers are not required because update_gt_cputime()
290 * can handle concurrent updates. 294 * can handle concurrent updates.
291 */ 295 */
292 WRITE_ONCE(cputimer->running, true); 296 WRITE_ONCE(pct->timers_active, true);
293 } 297 }
294 proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples); 298 proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
295} 299}
@@ -313,9 +317,10 @@ static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
313 bool start) 317 bool start)
314{ 318{
315 struct thread_group_cputimer *cputimer = &p->signal->cputimer; 319 struct thread_group_cputimer *cputimer = &p->signal->cputimer;
320 struct posix_cputimers *pct = &p->signal->posix_cputimers;
316 u64 samples[CPUCLOCK_MAX]; 321 u64 samples[CPUCLOCK_MAX];
317 322
318 if (!READ_ONCE(cputimer->running)) { 323 if (!READ_ONCE(pct->timers_active)) {
319 if (start) 324 if (start)
320 thread_group_start_cputime(p, samples); 325 thread_group_start_cputime(p, samples);
321 else 326 else
@@ -834,10 +839,10 @@ static void check_thread_timers(struct task_struct *tsk,
834 839
835static inline void stop_process_timers(struct signal_struct *sig) 840static inline void stop_process_timers(struct signal_struct *sig)
836{ 841{
837 struct thread_group_cputimer *cputimer = &sig->cputimer; 842 struct posix_cputimers *pct = &sig->posix_cputimers;
838 843
839 /* Turn off cputimer->running. This is done without locking. */ 844 /* Turn off the active flag. This is done without locking. */
840 WRITE_ONCE(cputimer->running, false); 845 WRITE_ONCE(pct->timers_active, false);
841 tick_dep_clear_signal(sig, TICK_DEP_BIT_POSIX_TIMER); 846 tick_dep_clear_signal(sig, TICK_DEP_BIT_POSIX_TIMER);
842} 847}
843 848
@@ -877,17 +882,17 @@ static void check_process_timers(struct task_struct *tsk,
877 unsigned long soft; 882 unsigned long soft;
878 883
879 /* 884 /*
880 * If cputimer is not running, then there are no active 885 * If there are no active process wide timers (POSIX 1.b, itimers,
881 * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU). 886 * RLIMIT_CPU) nothing to check.
882 */ 887 */
883 if (!READ_ONCE(sig->cputimer.running)) 888 if (!READ_ONCE(pct->timers_active))
884 return; 889 return;
885 890
886 /* 891 /*
887 * Signify that a thread is checking for process timers. 892 * Signify that a thread is checking for process timers.
888 * Write access to this field is protected by the sighand lock. 893 * Write access to this field is protected by the sighand lock.
889 */ 894 */
890 sig->cputimer.checking_timer = true; 895 pct->timers_active = true;
891 896
892 /* 897 /*
893 * Collect the current process totals. Group accounting is active 898 * Collect the current process totals. Group accounting is active
@@ -933,7 +938,7 @@ static void check_process_timers(struct task_struct *tsk,
933 if (expiry_cache_is_inactive(pct)) 938 if (expiry_cache_is_inactive(pct))
934 stop_process_timers(sig); 939 stop_process_timers(sig);
935 940
936 sig->cputimer.checking_timer = false; 941 pct->expiry_active = false;
937} 942}
938 943
939/* 944/*
@@ -1027,39 +1032,41 @@ task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
1027 */ 1032 */
1028static inline bool fastpath_timer_check(struct task_struct *tsk) 1033static inline bool fastpath_timer_check(struct task_struct *tsk)
1029{ 1034{
1035 struct posix_cputimers *pct = &tsk->posix_cputimers;
1030 struct signal_struct *sig; 1036 struct signal_struct *sig;
1031 1037
1032 if (!expiry_cache_is_inactive(&tsk->posix_cputimers)) { 1038 if (!expiry_cache_is_inactive(pct)) {
1033 u64 samples[CPUCLOCK_MAX]; 1039 u64 samples[CPUCLOCK_MAX];
1034 1040
1035 task_sample_cputime(tsk, samples); 1041 task_sample_cputime(tsk, samples);
1036 if (task_cputimers_expired(samples, &tsk->posix_cputimers)) 1042 if (task_cputimers_expired(samples, pct))
1037 return true; 1043 return true;
1038 } 1044 }
1039 1045
1040 sig = tsk->signal; 1046 sig = tsk->signal;
1047 pct = &sig->posix_cputimers;
1041 /* 1048 /*
1042 * Check if thread group timers expired when the cputimer is 1049 * Check if thread group timers expired when timers are active and
1043 * running and no other thread in the group is already checking 1050 * no other thread in the group is already handling expiry for
1044 * for thread group cputimers. These fields are read without the 1051 * thread group cputimers. These fields are read without the
1045 * sighand lock. However, this is fine because this is meant to 1052 * sighand lock. However, this is fine because this is meant to be
1046 * be a fastpath heuristic to determine whether we should try to 1053 * a fastpath heuristic to determine whether we should try to
1047 * acquire the sighand lock to check/handle timers. 1054 * acquire the sighand lock to handle timer expiry.
1048 * 1055 *
1049 * In the worst case scenario, if 'running' or 'checking_timer' gets 1056 * In the worst case scenario, if concurrently timers_active is set
1050 * set but the current thread doesn't see the change yet, we'll wait 1057 * or expiry_active is cleared, but the current thread doesn't see
1051 * until the next thread in the group gets a scheduler interrupt to 1058 * the change yet, the timer checks are delayed until the next
1052 * handle the timer. This isn't an issue in practice because these 1059 * thread in the group gets a scheduler interrupt to handle the
1053 * types of delays with signals actually getting sent are expected. 1060 * timer. This isn't an issue in practice because these types of
1061 * delays with signals actually getting sent are expected.
1054 */ 1062 */
1055 if (READ_ONCE(sig->cputimer.running) && 1063 if (READ_ONCE(pct->timers_active) && !READ_ONCE(pct->expiry_active)) {
1056 !READ_ONCE(sig->cputimer.checking_timer)) {
1057 u64 samples[CPUCLOCK_MAX]; 1064 u64 samples[CPUCLOCK_MAX];
1058 1065
1059 proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic, 1066 proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
1060 samples); 1067 samples);
1061 1068
1062 if (task_cputimers_expired(samples, &sig->posix_cputimers)) 1069 if (task_cputimers_expired(samples, pct))
1063 return true; 1070 return true;
1064 } 1071 }
1065 1072