| @@ -23,8 +23,10 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer); · 22 unmodified lines |
| 23 | void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit) | 23 | void 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, · 217 unmodified lines |
| 248 | void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples) | 250 | void 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) · 13 unmodified lines |
| 269 | static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples) | 272 | static 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) · 5 unmodified lines |
| 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, · 17 unmodified lines |
| 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, · 512 unmodified lines |
| 834 | | 839 | |
| 835 | static inline void stop_process_timers(struct signal_struct *sig) | 840 | static 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, · 33 unmodified lines |
| 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, · 39 unmodified lines |
| 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) · 87 unmodified lines |
| 1027 | */ | 1032 | */ |
| 1028 | static inline bool fastpath_timer_check(struct task_struct *tsk) | 1033 | static 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 | |