posix-cpu-timers: Cleanup and consolidation
Subsystems (4)
v2 cover posix-cpu-timers: Cleanup and consolidation
Folks!
This is the second version of that set. First one can be found here:
https://lkml.kernel.org/r/[email protected]
The following changes vs. V1:
- Folded the synchronization callback patch into the original one and replaced the original one in tip timers/core as requested by Christoph
- Merged the first couple of trivial patches into tip timers/core with Frederics reviewed-by picked up.
- Dropped the sighand locking change as pointed out by Frederic
- Dropped the last patch which switches to direct expiry mode as it got too ugly as the sighand locking change needed to be dropped. This will come with the next set on top of this which moves the expiry into task work context which was the initial reason for staring at this code.
- Reworked the storage array after the patch which removes the temporary union and the abused struct task_cputime as requested by Ingo.
- Fixed up a comment and the ugly hack in do_rlimit() which was needed to convert 0 expiry time to 1 which was required due to the 0 based checks which are now gone. (New)
- Fixed typos in comments and changelogs (Ingo)
The series applies on top of:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
and is available from git as well:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.timers/core
Thanks,
tglx
8<--------------
include/linux/init_task.h | 11 include/linux/posix-timers.h | 121 ++++- include/linux/sched.h | 29 - include/linux/sched/cputime.h | 12 include/linux/sched/signal.h | 14 include/linux/sched/types.h | 23 include/linux/timerqueue.h | 10 init/init_task.c | 2 kernel/fork.c | 34 - kernel/sched/rt.c | 6 kernel/sys.c | 16 kernel/time/itimer.c | 11 kernel/time/posix-cpu-timers.c | 952 +++++++++++++++++++---------------------- 13 files changed, 616 insertions(+), 625 deletions(-)
PATCH v2 1/38 posix-cpu-timers: Provide task validation functions
The code contains three slightly different copies of validating whether a given clock resolves to a valid task and whether the current caller has permissions to access it.
Create central functions. Replace check_clock() as a first step and rename it to something sensible.
--- kernel/time/posix-cpu-timers.c | 65 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 21 deletions(-)
kernel/time/posix-cpu-timers.c +44 -21
@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_strucspin_unlock_irq (&task->sighand->siglock); } -static int check_clock (const clockid_t which_clock) +/* +* Functions for validating access to tasks. +*/ +static struct task_struct *lookup_task (const pid_t pid,bool thread) { -int error =0 ;struct task_struct *p; -const pid_t pid =CPUCLOCK_PID (which_clock); -if (CPUCLOCK_WHICH (which_clock) >=CPUCLOCK_MAX ) -return -EINVAL ; +if (!pid) +return thread ? current : current->group_leader; -if (pid ==0 ) -return 0 ; + p =find_task_by_vpid (pid); +if (!p || p == current) +return p; +if (thread) +return same_thread_group (p, current) ? p :NULL ; +if (p == current) +return p; +return has_group_leader_pid (p) ? p :NULL ; +} + +static struct task_struct *__get_task_for_clock (const clockid_t clock, +bool getref) +{ +const bool thread = !!CPUCLOCK_PERTHREAD (clock); +const pid_t pid =CPUCLOCK_PID (clock); +struct task_struct *p; + +if (CPUCLOCK_WHICH (clock) >=CPUCLOCK_MAX ) +return NULL ;rcu_read_lock (); - p =find_task_by_vpid (pid); -if (!p || !(CPUCLOCK_PERTHREAD (which_clock) ? -same_thread_group (p, current) :has_group_leader_pid (p))) { - error = -EINVAL ; - } + p =lookup_task (pid, thread); +if (p && getref) +get_task_struct (p);rcu_read_unlock (); +return p; +} -return error; +static inline struct task_struct *get_task_for_clock (const clockid_t clock) +{ +return __get_task_for_clock (clock, true); +} + +static inline int validate_clock_permissions (const clockid_t clock) +{ +return __get_task_for_clock (clock, false) ?0 : -EINVAL ; }/*
@@ -125,7 +150,8 @@ static inline u64 virt_ticks(struct taskstatic int posix_cpu_clock_getres (const clockid_t which_clock,struct timespec64 *tp) { -int error =check_clock (which_clock); +int error =validate_clock_permissions (which_clock); +if (!error) { tp->tv_sec =0 ; tp->tv_nsec = ((NSEC_PER_SEC +HZ -1 ) /HZ );
@@ -142,20 +168,17 @@ posix_cpu_clock_getres(const clockid_t w }static int -posix_cpu_clock_set (const clockid_t which_clock,const struct timespec64 *tp) +posix_cpu_clock_set (const clockid_t clock,const struct timespec64 *tp) { +int error =validate_clock_permissions (clock); +/* * You can never reset a CPU clock, but we check for other errors * in the call before failing with EPERM. */ -int error =check_clock (which_clock); -if (error ==0 ) { - error = -EPERM ; - } -return error; +return error ? : -EPERM ; } -/* * Sample a per-thread clock for the given task. */
Frederic Weisbecker
maintainerRe: [patch V2 01/38] posix-cpu-timers: Provide task validation functions
Quoted 28 lines · Thomas Gleixner
The code contains three slightly different copies of validating whether a given clock resolves to a valid task and whether the current caller has permissions to access it.
Create central functions. Replace
check_clock()as a first step and rename it to something sensible.Signed-off-by Thomas Gleixner <[email protected]>--- kernel/time/posix-cpu-timers.c | 65 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 21 deletions(-)kernel/time/posix-cpu-timers.c +4
-3@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_strucspin_unlock_irq (&task->sighand->siglock); } -static int check_clock (const clockid_t which_clock) +/* +* Functions for validating access to tasks. +*/ +static struct task_struct *lookup_task (const pid_t pid,bool thread) { -int error =0 ;struct task_struct *p; -const pid_t pid =CPUCLOCK_PID (which_clock);
kernel/time/posix-cpu-timers.c void update_rlimit_cpu(struct task_struc · line 50
Quoted 10 lines
kernel/time/posix-cpu-timers.c +5
-4-if (CPUCLOCK_WHICH (which_clock) >=CPUCLOCK_MAX ) -return -EINVAL ; +if (!pid) +return thread ? current : current->group_leader; -if (pid ==0 ) -return 0 ; + p =find_task_by_vpid (pid); +if (!p || p == current) +return p;
What if (p == current && !thread && !has_group_leader_pid(p)) ?
kernel/time/posix-cpu-timers.c void update_rlimit_cpu(struct task_struc · line 54
Quoted 4 lines
kernel/time/posix-cpu-timers.c +4
-0+if (thread) +return same_thread_group (p, current) ? p :NULL ; +if (p == current) +return p;
You already checked that above.
Quoted 2 lines
kernel/time/posix-cpu-timers.c +2
-0+return has_group_leader_pid (p) ? p :NULL ; +}
Frederic Weisbecker
maintainerRe: [patch V2 01/38] posix-cpu-timers: Provide task validation functions
Quoted 34 lines · Frederic Weisbecker
Quoted 33 lines · Thomas Gleixner
The code contains three slightly different copies of validating whether a given clock resolves to a valid task and whether the current caller has permissions to access it.
Create central functions. Replace
check_clock()as a first step and rename it to something sensible.Signed-off-by Thomas Gleixner <[email protected]>--- kernel/time/posix-cpu-timers.c | 65 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 21 deletions(-)kernel/time/posix-cpu-timers.c +6
-5@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_strucspin_unlock_irq (&task->sighand->siglock); } -static int check_clock (const clockid_t which_clock) +/* +* Functions for validating access to tasks. +*/ +static struct task_struct *lookup_task (const pid_t pid,bool thread) { -int error =0 ;struct task_struct *p; -const pid_t pid =CPUCLOCK_PID (which_clock); -if (CPUCLOCK_WHICH (which_clock) >=CPUCLOCK_MAX ) -return -EINVAL ; +if (!pid) +return thread ? current : current->group_leader;
Quoted 7 lines
kernel/time/posix-cpu-timers.c void update_rlimit_cpu(struct task_struc · line 50
Quoted 5 lines
kernel/time/posix-cpu-timers.c +3
-2-if (pid ==0 ) -return 0 ; + p =find_task_by_vpid (pid); +if (!p || p == current) +return p;What if (p == current && !thread && !has_group_leader_pid(p)) ?
Ah looking at the next patch, posix_cpu_clock_get_task() and posix_cpu_clock_getres() had different ad-hoc checks for this specific case.
clock_getres() used to return -EINVAL while clock_get() doesn't care. They certainly should agree in their behaviour. I'm not sure which one is correct. It probably doesn't matter much.
Re: [patch V2 01/38] posix-cpu-timers: Provide task validation functions
Quoted 43 lines · Frederic Weisbecker
Quoted 34 lines · Frederic Weisbecker
Quoted 33 lines · Thomas Gleixner
The code contains three slightly different copies of validating whether a given clock resolves to a valid task and whether the current caller has permissions to access it.
Create central functions. Replace
check_clock()as a first step and rename it to something sensible.Signed-off-by Thomas Gleixner <[email protected]>--- kernel/time/posix-cpu-timers.c | 65 +++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 21 deletions(-)kernel/time/posix-cpu-timers.c +6
-5@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_strucspin_unlock_irq (&task->sighand->siglock); } -static int check_clock (const clockid_t which_clock) +/* +* Functions for validating access to tasks. +*/ +static struct task_struct *lookup_task (const pid_t pid,bool thread) { -int error =0 ;struct task_struct *p; -const pid_t pid =CPUCLOCK_PID (which_clock); -if (CPUCLOCK_WHICH (which_clock) >=CPUCLOCK_MAX ) -return -EINVAL ; +if (!pid) +return thread ? current : current->group_leader;Quoted 7 lines
kernel/time/posix-cpu-timers.c void update_rlimit_cpu(struct task_struc · line 50
Quoted 5 lines
kernel/time/posix-cpu-timers.c +3
-2-if (pid ==0 ) -return 0 ; + p =find_task_by_vpid (pid); +if (!p || p == current) +return p;What if (p == current && !thread && !has_group_leader_pid(p)) ?
Quoted 6 lines
Ah looking at the next patch,
posix_cpu_clock_get_task()andposix_cpu_clock_getres()had different ad-hoc checks for this specific case.
clock_getres()used to return-EINVALwhileclock_get()doesn't care. They certainly should agree in their behaviour. I'm not sure which one is correct. It probably doesn't matter much.
Let me stare on the different variants again
Thanks,
tglx
[tip: timers/core] posix-cpu-timers: Provide task validation functions
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 6ae40e3fdcd33a6ff3c490b9302d6a1861093f65 Gitweb: https://git.kernel.org/tip/6ae40e3fdcd33a6ff3c490b9302d6a1861093f65 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:48 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:24 +02:00
posix-cpu-timers: Provide task validation functions
The code contains three slightly different copies of validating whether a given clock resolves to a valid task and whether the current caller has permissions to access it.
Create central functions. Replace check_clock() as a first step and rename it to something sensible.
--- kernel/time/posix-cpu-timers.c | 65 ++++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 21 deletions(-)
kernel/time/posix-cpu-timers.c +44 -21
@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)spin_unlock_irq (&task->sighand->siglock); } -static int check_clock (const clockid_t which_clock) +/* +* Functions for validating access to tasks. +*/ +static struct task_struct *lookup_task (const pid_t pid,bool thread) { -int error =0 ;struct task_struct *p; -const pid_t pid =CPUCLOCK_PID (which_clock); -if (CPUCLOCK_WHICH (which_clock) >=CPUCLOCK_MAX ) -return -EINVAL ; +if (!pid) +return thread ? current : current->group_leader; + + p =find_task_by_vpid (pid); +if (!p || p == current) +return p; +if (thread) +return same_thread_group (p, current) ? p :NULL ; +if (p == current) +return p; +return has_group_leader_pid (p) ? p :NULL ; +} + +static struct task_struct *__get_task_for_clock (const clockid_t clock, +bool getref) +{ +const bool thread = !!CPUCLOCK_PERTHREAD (clock); +const pid_t pid =CPUCLOCK_PID (clock); +struct task_struct *p; -if (pid ==0 ) -return 0 ; +if (CPUCLOCK_WHICH (clock) >=CPUCLOCK_MAX ) +return NULL ;rcu_read_lock (); - p =find_task_by_vpid (pid); -if (!p || !(CPUCLOCK_PERTHREAD (which_clock) ? -same_thread_group (p, current) :has_group_leader_pid (p))) { - error = -EINVAL ; - } + p =lookup_task (pid, thread); +if (p && getref) +get_task_struct (p);rcu_read_unlock (); +return p; +} -return error; +static inline struct task_struct *get_task_for_clock (const clockid_t clock) +{ +return __get_task_for_clock (clock, true); +} + +static inline int validate_clock_permissions (const clockid_t clock) +{ +return __get_task_for_clock (clock, false) ?0 : -EINVAL ; }/*
@@ -125,7 +150,8 @@ static inline u64 virt_ticks(struct task_struct *p)static int posix_cpu_clock_getres (const clockid_t which_clock,struct timespec64 *tp) { -int error =check_clock (which_clock); +int error =validate_clock_permissions (which_clock); +if (!error) { tp->tv_sec =0 ; tp->tv_nsec = ((NSEC_PER_SEC +HZ -1 ) /HZ );
@@ -142,20 +168,17 @@ posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp) }static int -posix_cpu_clock_set (const clockid_t which_clock,const struct timespec64 *tp) +posix_cpu_clock_set (const clockid_t clock,const struct timespec64 *tp) { +int error =validate_clock_permissions (clock); +/* * You can never reset a CPU clock, but we check for other errors * in the call before failing with EPERM. */ -int error =check_clock (which_clock); -if (error ==0 ) { - error = -EPERM ; - } -return error; +return error ? : -EPERM ; } -/* * Sample a per-thread clock for the given task. */
PATCH v2 2/38 posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
In reply to Thomas GleixnerReplace the next slightly different copy of permission checks. That also removes the necessarity to check the return value of the sample functions because the clock id is already validated.
--- kernel/time/posix-cpu-timers.c | 61 ++++++++++------------------------------- 1 file changed, 16 insertions(+), 45 deletions(-)
kernel/time/posix-cpu-timers.c +16 -45
@@ -289,53 +289,24 @@ static int cpu_clock_sample_group(constreturn 0 ; } -static int posix_cpu_clock_get_task (struct task_struct *tsk, -const clockid_t which_clock, -struct timespec64 *tp) +static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp) { -int err = -EINVAL ; -u64 rtn; +const clockid_t clkid =CPUCLOCK_WHICH (clock); +struct task_struct *tsk; +u64 t; + + tsk =get_task_for_clock (clock); +if (!tsk) +return -EINVAL ; + +if (CPUCLOCK_PERTHREAD (clock)) +cpu_clock_sample (clkid, tsk, &t); +else +cpu_clock_sample_group (clkid, tsk, &t); +put_task_struct (tsk); -if (CPUCLOCK_PERTHREAD (which_clock)) { -if (same_thread_group (tsk, current)) - err =cpu_clock_sample (which_clock, tsk, &rtn); - }else { -if (tsk == current ||thread_group_leader (tsk)) - err =cpu_clock_sample_group (which_clock, tsk, &rtn); - } - -if (!err) - *tp =ns_to_timespec64 (rtn); - -return err; -} - - -static int posix_cpu_clock_get (const clockid_t which_clock,struct timespec64 *tp) -{ -const pid_t pid =CPUCLOCK_PID (which_clock); -int err = -EINVAL ; - -if (pid ==0 ) { -/* -* Special case constant value for our own clocks. -* We don't have to do any lookup to find ourselves. -*/ - err =posix_cpu_clock_get_task (current, which_clock, tp); - }else { -/* -* Find the given PID, and validate that the caller -* should be able to see it. -*/ -struct task_struct *p; -rcu_read_lock (); - p =find_task_by_vpid (pid); -if (p) - err =posix_cpu_clock_get_task (p, which_clock, tp); -rcu_read_unlock (); - } - -return err; + *tp =ns_to_timespec64 (t); +return 0 ; }/*
Re: [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
Quoted 13 lines · Thomas Gleixner
Replace the next slightly different copy of permission checks. That also removes the necessarity to check the return value of the sample functions because the clock id is already validated.
Signed-off-by Thomas Gleixner <[email protected]>--- kernel/time/posix-cpu-timers.c | 61 ++++++++++------------------------------- 1 file changed, 16 insertions(+), 45 deletions(-)kernel/time/posix-cpu-timers.c +0
-0@@ -289,53 +289,24 @@ static int cpu_clock_sample_group(constreturn 0 ;
kernel/time/posix-cpu-timers.c static int cpu_clock_sample_group(const · line 294
Quoted 10 lines
kernel/time/posix-cpu-timers.c +2
-5} -static int posix_cpu_clock_get_task (struct task_struct *tsk, -const clockid_t which_clock, -struct timespec64 *tp) +static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp) { -int err = -EINVAL ; -u64 rtn; +const clockid_t clkid =CPUCLOCK_WHICH (clock);
So I guess you later remove the CPUCLOCK_WHICH() from cpu_clock_sample*() and turn them to void.
[tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: bfcf3e92c6c07cd1084624bad5622f3dad96328c Gitweb: https://git.kernel.org/tip/bfcf3e92c6c07cd1084624bad5622f3dad96328c Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:49 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:25 +02:00
posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
Replace the next slightly different copy of permission checks. That also removes the necessarity to check the return value of the sample functions because the clock id is already validated.
--- kernel/time/posix-cpu-timers.c | 57 ++++++++------------------------- 1 file changed, 14 insertions(+), 43 deletions(-)
kernel/time/posix-cpu-timers.c +14 -43
@@ -289,53 +289,24 @@ static int cpu_clock_sample_group(const clockid_t which_clock,return 0 ; } -static int posix_cpu_clock_get_task (struct task_struct *tsk, -const clockid_t which_clock, -struct timespec64 *tp) +static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp) { -int err = -EINVAL ; -u64 rtn; - -if (CPUCLOCK_PERTHREAD (which_clock)) { -if (same_thread_group (tsk, current)) - err =cpu_clock_sample (which_clock, tsk, &rtn); - }else { -if (tsk == current ||thread_group_leader (tsk)) - err =cpu_clock_sample_group (which_clock, tsk, &rtn); - } - -if (!err) - *tp =ns_to_timespec64 (rtn); +const clockid_t clkid =CPUCLOCK_WHICH (clock); +struct task_struct *tsk; +u64 t; -return err; -} - - -static int posix_cpu_clock_get (const clockid_t which_clock,struct timespec64 *tp) -{ -const pid_t pid =CPUCLOCK_PID (which_clock); -int err = -EINVAL ; + tsk =get_task_for_clock (clock); +if (!tsk) +return -EINVAL ; -if (pid ==0 ) { -/* -* Special case constant value for our own clocks. -* We don't have to do any lookup to find ourselves. -*/ - err =posix_cpu_clock_get_task (current, which_clock, tp); - }else { -/* -* Find the given PID, and validate that the caller -* should be able to see it. -*/ -struct task_struct *p; -rcu_read_lock (); - p =find_task_by_vpid (pid); -if (p) - err =posix_cpu_clock_get_task (p, which_clock, tp); -rcu_read_unlock (); - } +if (CPUCLOCK_PERTHREAD (clock)) +cpu_clock_sample (clkid, tsk, &t); +else +cpu_clock_sample_group (clkid, tsk, &t); +put_task_struct (tsk); -return err; + *tp =ns_to_timespec64 (t); +return 0 ; }/*
kbuild test robot
build botRe: [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
Thank you for the patch! Yet something to improve:
Hi tip-bot2,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190828]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/tip-bot2-for-Thomas-Gleixner/posix-cpu-timers-Use-common-permission-check-in-posix_cpu_clock_get/20190829-181227
config: parisc-c3000_defconfig (attached as .config)
compiler: hppa-linux-gcc (GCC) 7.4.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=7.4.0 make.cross ARCH=parisc
If you fix the issue, kindly add following tag
All error/warnings (new ones prefixed by >>):
kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':
>> kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]
tsk = get_task_for_clock(clock);
^~~~~~~~~~~~~~~~~~
get_task_struct
>> kernel/time/posix-cpu-timers.c:275:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
tsk = get_task_for_clock(clock);
^cc1: some warnings being treated as errors
vim +275 kernel/time/posix-cpu-timers.c
268
269 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
270 {
271 const clockid_t clkid = CPUCLOCK_WHICH(clock);
272 struct task_struct *tsk;
273 u64 t;
274
> 275 tsk = get_task_for_clock(clock);
276 if (!tsk)
277 return -EINVAL;
278
279 if (CPUCLOCK_PERTHREAD(clock))
280 cpu_clock_sample(clkid, tsk, &t);
281 else
282 cpu_clock_sample_group(clkid, tsk, &t);
283 put_task_struct(tsk);
284
285 *tp = ns_to_timespec64(t);
286 return 0;
287 }
288
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
Quoted 5 lines · kbuild test robot
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190828]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
I have no idea what you are testing there.
Quoted 9 lines
kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':Quoted 1 line
Quoted 1 line
kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]tsk = get_task_for_clock(clock); ^~~~~~~~~~~~~~~~~~ get_task_structQuoted 1 line
Quoted 1 line
kernel/time/posix-cpu-timers.c:275:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]tsk = get_task_for_clock(clock); ^cc1: some warnings being treated as errors
That commit comes _after_ the commit which introduced the function and get_task_for_clock() is defined above posix_cpu_clock_get(), so I assume you missed to apply the commit on which this depends on.
Thanks,
tglx
Re: [kbuild-all] [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
Quoted 8 lines · Thomas Gleixner
Quoted 5 lines · kbuild test robot
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190828]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]I have no idea what you are testing there.
oops, looks we have missed some info in report. We actually test patches from mailing list we monitor.
Quoted 6 lines
Quoted 6 lines
kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':Quoted 1 line
Quoted 1 line
kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]tsk = get_task_for_clock(clock); ^~~~~~~~~~~~~~~~~~ get_task_struct
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line
kernel/time/posix-cpu-timers.c:275:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]tsk = get_task_for_clock(clock); ^cc1: some warnings being treated as errors
That commit comes _after_ the commit which introduced the function and
get_task_for_clock()is defined aboveposix_cpu_clock_get(), so I assume you missed to apply the commit on which this depends on.
thanks for info, currently the bot can't figure out the dependency if two patches are not in one series, or we didn't find the right base repo to apply, which we will improve continuously.
Quoted 8 lines
Thanks,
tglx
_______________________________________________
kbuild-all mailing list
[email protected]
https://lists.01.org/mailman/listinfo/kbuild-all
kbuild test robot
build botRe: [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
In reply to tip-bot2 for Thomas GleixnerThank you for the patch! Perhaps something to improve:
Hi tip-bot2,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on linus/master]
[cannot apply to v5.3-rc6 next-20190827]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/tip-bot2-for-Thomas-Gleixner/posix-cpu-timers-Use-common-permission-check-in-posix_cpu_clock_get/20190829-181227
config: nds32-defconfig (attached as .config)
compiler: nds32le-linux-gcc (GCC) 8.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
GCC_VERSION=8.1.0 make.cross ARCH=nds32
If you fix the issue, kindly add following tag
All warnings (new ones prefixed by >>):
kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':
kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]
tsk = get_task_for_clock(clock);
^~~~~~~~~~~~~~~~~~
get_task_struct
>> kernel/time/posix-cpu-timers.c:275:6: warning: assignment to 'struct task_struct *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
tsk = get_task_for_clock(clock);
^cc1: some warnings being treated as errors
vim +275 kernel/time/posix-cpu-timers.c
268
269 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
270 {
271 const clockid_t clkid = CPUCLOCK_WHICH(clock);
272 struct task_struct *tsk;
273 u64 t;
274
> 275 tsk = get_task_for_clock(clock);
276 if (!tsk)
277 return -EINVAL;
278
279 if (CPUCLOCK_PERTHREAD(clock))
280 cpu_clock_sample(clkid, tsk, &t);
281 else
282 cpu_clock_sample_group(clkid, tsk, &t);
283 put_task_struct(tsk);
284
285 *tp = ns_to_timespec64(t);
286 return 0;
287 }
288
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
PATCH v2 3/38 posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
In reply to Thomas GleixnerYet another copy of the same thing gone...
--- kernel/time/posix-cpu-timers.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-)
kernel/time/posix-cpu-timers.c +3 -32
@@ -316,44 +316,15 @@ static int posix_cpu_clock_get(const clo*/ static int posix_cpu_timer_create (struct k_itimer *new_timer) { -int ret =0 ; -const pid_t pid =CPUCLOCK_PID (new_timer->it_clock); -struct task_struct *p; +struct task_struct *p =get_task_for_clock (new_timer->it_clock); -if (CPUCLOCK_WHICH (new_timer->it_clock) >=CPUCLOCK_MAX ) +if (!p)return -EINVAL ; new_timer->kclock = &clock_posix_cpu; -INIT_LIST_HEAD (&new_timer->it.cpu.entry); - -rcu_read_lock (); -if (CPUCLOCK_PERTHREAD (new_timer->it_clock)) { -if (pid ==0 ) { - p = current; - }else { - p =find_task_by_vpid (pid); -if (p && !same_thread_group (p, current)) - p =NULL ; - } - }else { -if (pid ==0 ) { - p = current->group_leader; - }else { - p =find_task_by_vpid (pid); -if (p && !has_group_leader_pid (p)) - p =NULL ; - } - } new_timer->it.cpu.task = p; -if (p) { -get_task_struct (p); - }else { - ret = -EINVAL ; - } -rcu_read_unlock (); - -return ret; +return 0 ; }/*
Re: [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
Quoted 4 lines · Thomas Gleixner
Yet another copy of the same thing gone...
Signed-off-by Thomas Gleixner <[email protected]>---
[tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: e5a8b65b4cb2fe024b83bdec0424269949cc0a27 Gitweb: https://git.kernel.org/tip/e5a8b65b4cb2fe024b83bdec0424269949cc0a27 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:50 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:25 +02:00
posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
Yet another copy of the same thing gone...
--- kernel/time/posix-cpu-timers.c | 35 ++------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-)
kernel/time/posix-cpu-timers.c +3 -32
@@ -316,44 +316,15 @@ static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)*/ static int posix_cpu_timer_create (struct k_itimer *new_timer) { -int ret =0 ; -const pid_t pid =CPUCLOCK_PID (new_timer->it_clock); -struct task_struct *p; +struct task_struct *p =get_task_for_clock (new_timer->it_clock); -if (CPUCLOCK_WHICH (new_timer->it_clock) >=CPUCLOCK_MAX ) +if (!p)return -EINVAL ; new_timer->kclock = &clock_posix_cpu; -INIT_LIST_HEAD (&new_timer->it.cpu.entry); - -rcu_read_lock (); -if (CPUCLOCK_PERTHREAD (new_timer->it_clock)) { -if (pid ==0 ) { - p = current; - }else { - p =find_task_by_vpid (pid); -if (p && !same_thread_group (p, current)) - p =NULL ; - } - }else { -if (pid ==0 ) { - p = current->group_leader; - }else { - p =find_task_by_vpid (pid); -if (p && !has_group_leader_pid (p)) - p =NULL ; - } - } new_timer->it.cpu.task = p; -if (p) { -get_task_struct (p); - }else { - ret = -EINVAL ; - } -rcu_read_unlock (); - -return ret; +return 0 ; }/*
PATCH v2 4/38 posix-cpu-timers: Provide quick sample function for itimer
In reply to Thomas Gleixnerget_itimer() needs a sample of the current thread group cputime. It invokes thread_group_cputimer() - which is a misnomer. That function also starts eventually the group cputime accouting which is bogus because the accounting is already active when a timer is armed.
--- include/linux/sched/cputime.h | 2 +- kernel/time/posix-cpu-timers.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-)
include/linux/sched/cputime.h +1 -1
@@ -62,7 +62,7 @@ extern void cputime_adjust(struct task_c*/ void thread_group_cputime (struct task_struct *tsk,struct task_cputime *times);void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times); - +void thread_group_sample_cputime (struct task_struct *tsk,struct task_cputime *times);/* * The following are functions that support scheduler-internal time accounting.
kernel/time/posix-cpu-timers.c +21 -0
@@ -232,6 +232,27 @@ static inline void sample_cputime_atomic times->sum_exec_runtime =atomic64_read (&atomic_times->sum_exec_runtime); } +/** +* thread_group_sample_cputime - Sample cputime for a given task +* @tsk: Task for which cputime needs to be started +* @iimes: Storage for time samples +* +* Called from sys_getitimer() to calculate the expiry time of an active +* timer. That means group cputime accounting is already active. Called +* with task sighand lock held. +* +* Updates @times with an uptodate sample of the thread group cputimes. +*/ +void thread_group_sample_cputime (struct task_struct *tsk, +struct task_cputime *times) +{ +struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; + +WARN_ON_ONCE (!cputimer->running); + +sample_cputime_atomic (times, &cputimer->cputime_atomic); +} +void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times) {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
Re: [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer
Quoted 6 lines · Thomas Gleixner
get_itimer()needs a sample of the current thread group cputime. It invokesthread_group_cputimer()- which is a misnomer. That function also starts eventually the group cputime accouting which is bogus because the accounting is already active when a timer is armed.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Provide quick sample function for itimer
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 19298fbf453c90a6cf72288155f80c6f55e9139d Gitweb: https://git.kernel.org/tip/19298fbf453c90a6cf72288155f80c6f55e9139d Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:51 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:26 +02:00
posix-cpu-timers: Provide quick sample function for itimer
get_itimer() needs a sample of the current thread group cputime. It invokes thread_group_cputimer() - which is a misnomer. That function also starts eventually the group cputime accouting which is bogus because the accounting is already active when a timer is armed.
--- include/linux/sched/cputime.h | 2 +- kernel/time/posix-cpu-timers.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-)
include/linux/sched/cputime.h +1 -1
@@ -62,7 +62,7 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,*/ void thread_group_cputime (struct task_struct *tsk,struct task_cputime *times);void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times); - +void thread_group_sample_cputime (struct task_struct *tsk,struct task_cputime *times);/* * The following are functions that support scheduler-internal time accounting.
kernel/time/posix-cpu-timers.c +21 -0
@@ -232,6 +232,27 @@ static inline void sample_cputime_atomic(struct task_cputime *times, times->sum_exec_runtime =atomic64_read (&atomic_times->sum_exec_runtime); } +/** +* thread_group_sample_cputime - Sample cputime for a given task +* @tsk: Task for which cputime needs to be started +* @iimes: Storage for time samples +* +* Called from sys_getitimer() to calculate the expiry time of an active +* timer. That means group cputime accounting is already active. Called +* with task sighand lock held. +* +* Updates @times with an uptodate sample of the thread group cputimes. +*/ +void thread_group_sample_cputime (struct task_struct *tsk, +struct task_cputime *times) +{ +struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; + +WARN_ON_ONCE (!cputimer->running); + +sample_cputime_atomic (times, &cputimer->cputime_atomic); +} +void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times) {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
PATCH v2 5/38 itimers: Use quick sample function
In reply to Thomas Gleixnerget_itimer() locks sighand lock and checks whether the timer is already expired. If it is not expired then the thread group cputime accounting is already enabled. Use the sampling function not the one which is meant for starting a timer.
--- kernel/time/itimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -58,7 +58,7 @@ static void get_cpu_itimer(struct task_sstruct task_cputime cputime;u64 t; -thread_group_cputimer (tsk, &cputime); +thread_group_sample_cputime (tsk, &cputime);if (clock_id ==CPUCLOCK_PROF ) t = cputime.utime + cputime.stime;else
Re: [patch V2 05/38] itimers: Use quick sample function
Quoted 6 lines · Thomas Gleixner
get_itimer()locks sighand lock and checks whether the timer is already expired. If it is not expired then the thread group cputime accounting is already enabled. Use the sampling function not the one which is meant for starting a timer.Signed-off-by Thomas Gleixner <[email protected]>
I've always hated the abuse of thread_group_cputimer().
Thanks!
[tip: timers/core] itimers: Use quick sample function
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: a34360d42434bbf28c0f375444c52c154ae3e6cf Gitweb: https://git.kernel.org/tip/a34360d42434bbf28c0f375444c52c154ae3e6cf Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:52 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:26 +02:00
itimers: Use quick sample function
get_itimer() locks sighand lock and checks whether the timer is already expired. If it is not expired then the thread group cputime accounting is already enabled. Use the sampling function not the one which is meant for starting a timer.
--- kernel/time/itimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -58,7 +58,7 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,struct task_cputime cputime;u64 t; -thread_group_cputimer (tsk, &cputime); +thread_group_sample_cputime (tsk, &cputime);if (clock_id ==CPUCLOCK_PROF ) t = cputime.utime + cputime.stime;else
kbuild test robot
build botRe: [tip: timers/core] itimers: Use quick sample function
Thank you for the patch! Yet something to improve:
Hi tip-bot2,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190829]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/tip-bot2-for-Thomas-Gleixner/itimers-Use-quick-sample-function/20190830-063115
config: i386-defconfig (attached as .config)
compiler: gcc-7 (Debian 7.4.0-11) 7.4.0 reproduce:
# save the attached .config to linux build tree
make ARCH=i386 If you fix the issue, kindly add following tag
All errors (new ones prefixed by >>):
kernel/time/itimer.c: In function 'get_cpu_itimer':
>> kernel/time/itimer.c:61:3: error: implicit declaration of function 'thread_group_sample_cputime'; did you mean 'thread_group_cputime'? [-Werror=implicit-function-declaration]
thread_group_sample_cputime(tsk, &cputime);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
thread_group_cputimecc1: some warnings being treated as errors
vim +61 kernel/time/itimer.c
46
47 static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
48 struct itimerval *const value)
49 {
50 u64 val, interval;
51 struct cpu_itimer *it = &tsk->signal->it[clock_id];
52
53 spin_lock_irq(&tsk->sighand->siglock);
54
55 val = it->expires;
56 interval = it->incr;
57 if (val) {
58 struct task_cputime cputime;
59 u64 t;
60
> 61 thread_group_sample_cputime(tsk, &cputime);
62 if (clock_id == CPUCLOCK_PROF)
63 t = cputime.utime + cputime.stime;
64 else
65 /* CPUCLOCK_VIRT */
66 t = cputime.utime;
67
68 if (val < t)
69 /* about to fire */
70 val = TICK_NSEC;
71 else
72 val -= t;
73 }
74
75 spin_unlock_irq(&tsk->sighand->siglock);
76
77 value->it_value = ns_to_timeval(val);
78 value->it_interval = ns_to_timeval(interval);
79 }
80 ---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
Re: [tip: timers/core] itimers: Use quick sample function
Quoted 4 lines · kbuild test robot
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190829]
Of course not. Because the patch is already in v5.3-rc6 next-20190829
Quoted 2 lines
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
I did so several times now and so did Borislav.
Can you please stop applying random patches from tip-bot2 notifications which are part of a larger series and if applied alone obviously fail because the prerequisite patches fail?
tip-bot2 mails are notifications that a patch has been merged into a branch of the tip tree. They contain the information in which branch these patches are applied so please start testing that branch in the proper order or ignore tip-bot2 completely.
I really value your service, but recently the usefulness to noise ratio has degraded massively.
Thanks,
tglx
PATCH v2 6/38 posix-cpu-timers: Sample directly in timer check
In reply to Thomas GleixnerThe thread group accounting is active, otherwise the expiry function would not be running. Sample the thread group time directly.
--- kernel/time/posix-cpu-timers.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
kernel/time/posix-cpu-timers.c +4 -3
@@ -914,16 +914,17 @@ static void check_process_timers(structif (!READ_ONCE (tsk->signal->cputimer.running))return ; -/* +/* * Signify that a thread is checking for process timers. * Write access to this field is protected by the sighand lock. */ sig->cputimer.checking_timer = true;/* -* Collect the current process totals. +* Collect the current process totals. Group accounting is active +* so the sample can be taken directly. */ -thread_group_cputimer (tsk, &cputime); +sample_cputime_atomic (&cputime, &sig->cputimer.cputime_atomic); utime = cputime.utime; ptime = utime + cputime.stime; sum_sched_runtime = cputime.sum_exec_runtime;
Re: [patch V2 06/38] posix-cpu-timers: Sample directly in timer check
Quoted 4 lines · Thomas Gleixner
The thread group accounting is active, otherwise the expiry function would not be running. Sample the thread group time directly.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Sample directly in timer check
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: a324956fae05d863386c682830e917f6685f1d4f Gitweb: https://git.kernel.org/tip/a324956fae05d863386c682830e917f6685f1d4f Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:53 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:27 +02:00
posix-cpu-timers: Sample directly in timer check
The thread group accounting is active, otherwise the expiry function would not be running. Sample the thread group time directly.
--- kernel/time/posix-cpu-timers.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
kernel/time/posix-cpu-timers.c +4 -3
@@ -914,16 +914,17 @@ static void check_process_timers(struct task_struct *tsk,if (!READ_ONCE (tsk->signal->cputimer.running))return ; -/* +/* * Signify that a thread is checking for process timers. * Write access to this field is protected by the sighand lock. */ sig->cputimer.checking_timer = true;/* -* Collect the current process totals. +* Collect the current process totals. Group accounting is active +* so the sample can be taken directly. */ -thread_group_cputimer (tsk, &cputime); +sample_cputime_atomic (&cputime, &sig->cputimer.cputime_atomic); utime = cputime.utime; ptime = utime + cputime.stime; sum_sched_runtime = cputime.sum_exec_runtime;
PATCH v2 7/38 posix-cpu-timers: Rename thread_group_cputimer() and make it static
In reply to Thomas Gleixnerthread_group_cputimer() is a complete misnomer. The function does two things:
- For arming process wide timers it makes sure that the atomic time storage is up to date. If no cpu timer is armed yet, then the atomic time storage is not updated by the scheduler for performance reasons.
In that case a full summing up of all threads needs to be done and the update needs to be enabled.
- Samples the current time into the caller supplied storage.
Rename it to thread_group_start_cputime(), make it static and fixup the callsite.
--- include/linux/sched/cputime.h | 1 - kernel/time/posix-cpu-timers.c | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-)
include/linux/sched/cputime.h +0 -1
@@ -61,7 +61,6 @@ extern void cputime_adjust(struct task_c* Thread group CPU time accounting. */ void thread_group_cputime (struct task_struct *tsk,struct task_cputime *times); -void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times);void thread_group_sample_cputime (struct task_struct *tsk,struct task_cputime *times);/*
kernel/time/posix-cpu-timers.c +15 -2
@@ -253,7 +253,20 @@ void thread_group_sample_cputime(structsample_cputime_atomic (times, &cputimer->cputime_atomic); } -void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times) +/** +* thread_group_start_cputime - Start cputime and return a sample +* @tsk: Task for which cputime needs to be started +* @iimes: Storage for time samples +* +* The thread group cputime accouting is avoided when there are no posix +* CPU timers armed. Before starting a timer it's required to check whether +* the time accounting is active. If not, a full update of the atomic +* accounting store needs to be done and the accounting enabled. +* +* Updates @times with an uptodate sample of the thread group cputimes. +*/ +static void +thread_group_start_cputime (struct task_struct *tsk,struct task_cputime *times) {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;struct task_cputime sum;
@@ -536,7 +549,7 @@ static int cpu_timer_sample_group(const {struct task_cputime cputime; -thread_group_cputimer (p, &cputime); +thread_group_start_cputime (p, &cputime);switch (CPUCLOCK_WHICH (which_clock)) {default :return -EINVAL ;
Re: [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static
Quoted 9 lines · Thomas Gleixner
thread_group_cputimer()is a complete misnomer. The function does two things:- For arming process wide timers it makes sure that the atomic time storage is up to date. If no cpu timer is armed yet, then the atomic time storage is not updated by the scheduler for performance reasons.
In that case a full summing up of all threads needs to be done and the update needs to be enabled.
Quoted 6 lines
- Samples the current time into the caller supplied storage.
Rename it to
thread_group_start_cputime(), make it static and fixup the callsite.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Rename thread_group_cputimer() and make it static
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: c506bef424ca282f2ad357e86fee940c69018974 Gitweb: https://git.kernel.org/tip/c506bef424ca282f2ad357e86fee940c69018974 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:54 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:27 +02:00
posix-cpu-timers: Rename thread_group_cputimer() and make it static
thread_group_cputimer() is a complete misnomer. The function does two things:
- For arming process wide timers it makes sure that the atomic time storage is up to date. If no cpu timer is armed yet, then the atomic time storage is not updated by the scheduler for performance reasons.
In that case a full summing up of all threads needs to be done and the update needs to be enabled.
- Samples the current time into the caller supplied storage.
Rename it to thread_group_start_cputime(), make it static and fixup the callsite.
--- include/linux/sched/cputime.h | 1 - kernel/time/posix-cpu-timers.c | 17 +++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-)
include/linux/sched/cputime.h +0 -1
@@ -61,7 +61,6 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,* Thread group CPU time accounting. */ void thread_group_cputime (struct task_struct *tsk,struct task_cputime *times); -void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times);void thread_group_sample_cputime (struct task_struct *tsk,struct task_cputime *times);/*
kernel/time/posix-cpu-timers.c +15 -2
@@ -253,7 +253,20 @@ void thread_group_sample_cputime(struct task_struct *tsk,sample_cputime_atomic (times, &cputimer->cputime_atomic); } -void thread_group_cputimer (struct task_struct *tsk,struct task_cputime *times) +/** +* thread_group_start_cputime - Start cputime and return a sample +* @tsk: Task for which cputime needs to be started +* @iimes: Storage for time samples +* +* The thread group cputime accouting is avoided when there are no posix +* CPU timers armed. Before starting a timer it's required to check whether +* the time accounting is active. If not, a full update of the atomic +* accounting store needs to be done and the accounting enabled. +* +* Updates @times with an uptodate sample of the thread group cputimes. +*/ +static void +thread_group_start_cputime (struct task_struct *tsk,struct task_cputime *times) {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;struct task_cputime sum;
@@ -536,7 +549,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock, {struct task_cputime cputime; -thread_group_cputimer (p, &cputime); +thread_group_start_cputime (p, &cputime);switch (CPUCLOCK_WHICH (which_clock)) {default :return -EINVAL ;
PATCH v2 8/38 posix-cpu-timers: Consolidate thread group sample code
In reply to Thomas Gleixnercpu_clock_sample_group() and cpu_timer_sample_group() are almost the same. Before the rename one called thread_group_cputimer() and the other thread_group_cputime(). Really intuitive function names.
Consolidate the functions and also avoid the thread traversal when the thread group's accounting is already active.
---
V2: Fixed typos
--- kernel/time/posix-cpu-timers.c | 59 +++++++++++++---------------------------- 1 file changed, 20 insertions(+), 39 deletions(-)
kernel/time/posix-cpu-timers.c +20 -39
@@ -294,29 +294,37 @@ thread_group_start_cputime(struct task_s }/* -* Sample a process (thread group) clock for the given group_leader task. -* Must be called with task sighand lock held for safe while_each_thread() -* traversal. +* Sample a process (thread group) clock for the given task clkid. If the +* group's cputime accounting is already enabled, read the atomic +* store. Otherwise a full update is required. Task's sighand lock must be +* held to protect the task traversal on a full update. */ static int cpu_clock_sample_group (const clockid_t which_clock,struct task_struct *p, -u64 *sample) +u64 *sample,bool start) { +struct thread_group_cputimer *cputimer = &p->signal->cputimer;struct task_cputime cputime; +if (!READ_ONCE (cputimer->running)) { +if (start) +thread_group_start_cputime (p, &cputime); +else +thread_group_cputime (p, &cputime); + }else { +sample_cputime_atomic (&cputime, &cputimer->cputime_atomic); + } +switch (CPUCLOCK_WHICH (which_clock)) {default :return -EINVAL ;case CPUCLOCK_PROF : -thread_group_cputime (p, &cputime); *sample = cputime.utime + cputime.stime;break ;case CPUCLOCK_VIRT : -thread_group_cputime (p, &cputime); *sample = cputime.utime;break ;case CPUCLOCK_SCHED : -thread_group_cputime (p, &cputime); *sample = cputime.sum_exec_runtime;break ; }
@@ -336,7 +344,7 @@ static int posix_cpu_clock_get(const cloif (CPUCLOCK_PERTHREAD (clock))cpu_clock_sample (clkid, tsk, &t);else -cpu_clock_sample_group (clkid, tsk, &t); +cpu_clock_sample_group (clkid, tsk, &t, false);put_task_struct (tsk); *tp =ns_to_timespec64 (t);
@@ -540,33 +548,6 @@ static void cpu_timer_fire(struct k_itim }/* -* Sample a process (thread group) timer for the given group_leader task. -* Must be called with task sighand lock held for safe while_each_thread() -* traversal. -*/ -static int cpu_timer_sample_group (const clockid_t which_clock, -struct task_struct *p,u64 *sample) -{ -struct task_cputime cputime; - -thread_group_start_cputime (p, &cputime); -switch (CPUCLOCK_WHICH (which_clock)) { -default : -return -EINVAL ; -case CPUCLOCK_PROF : - *sample = cputime.utime + cputime.stime; -break ; -case CPUCLOCK_VIRT : - *sample = cputime.utime; -break ; -case CPUCLOCK_SCHED : - *sample = cputime.sum_exec_runtime; -break ; - } -return 0 ; -} - -/* * Guts of sys_timer_settime for CPU timers. * This is called with the timer locked and interrupts disabled. * If we return TIMER_RETRY, it's necessary to release the timer's lock
@@ -627,7 +608,7 @@ static int posix_cpu_timer_set(struct k_if (CPUCLOCK_PERTHREAD (timer->it_clock)) {cpu_clock_sample (timer->it_clock, p, &val); }else { -cpu_timer_sample_group (timer->it_clock, p, &val); +cpu_clock_sample_group (timer->it_clock, p, &val, true); }if (old) {
@@ -755,7 +736,7 @@ static void posix_cpu_timer_get(struct k timer->it.cpu.expires =0 ;return ; }else { -cpu_timer_sample_group (timer->it_clock, p, &now); +cpu_clock_sample_group (timer->it_clock, p, &now, false);unlock_task_sighand (p, &flags); } }
@@ -1042,7 +1023,7 @@ static void posix_cpu_timer_rearm(struct/* If the process is dying, no need to rearm */ goto unlock; } -cpu_timer_sample_group (timer->it_clock, p, &now); +cpu_clock_sample_group (timer->it_clock, p, &now, true);bump_cpu_timer (timer, now);/* Leave the sighand locked for the call below. */ }
@@ -1211,7 +1192,7 @@ void set_process_cpu_timer(struct task_sif (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED ))return ; - ret =cpu_timer_sample_group (clock_idx, tsk, &now); + ret =cpu_clock_sample_group (clock_idx, tsk, &now, true);if (oldval && ret != -EINVAL ) {/*
Re: [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code
Quoted 9 lines · Thomas Gleixner
cpu_clock_sample_group()andcpu_timer_sample_group()are almost the same. Before the rename one calledthread_group_cputimer()and the otherthread_group_cputime(). Really intuitive function names.Consolidate the functions and also avoid the thread traversal when the thread group's accounting is already active.
Signed-off-by Thomas Gleixner <[email protected]>---
[snip]
kernel/time/posix-cpu-timers.c static void posix_cpu_timer_get(struct k · line 739
Quoted 6 lines
kernel/time/posix-cpu-timers.c +1
-1@@ -755,7 +736,7 @@ static void posix_cpu_timer_get(struct k timer->it.cpu.expires =0 ;return ; }else { -cpu_timer_sample_group (timer->it_clock, p, &now); +cpu_clock_sample_group (timer->it_clock, p, &now, false);
We might want to warn here if !cputimer->running.
[tip: timers/core] posix-cpu-timers: Consolidate thread group sample code
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 24ab7f5a7b2c917e89fc6a87252f18faff91d6ce Gitweb: https://git.kernel.org/tip/24ab7f5a7b2c917e89fc6a87252f18faff91d6ce Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:55 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:28 +02:00
posix-cpu-timers: Consolidate thread group sample code
cpu_clock_sample_group() and cpu_timer_sample_group() are almost the same. Before the rename one called thread_group_cputimer() and the other thread_group_cputime(). Really intuitive function names.
Consolidate the functions and also avoid the thread traversal when the thread group's accounting is already active.
--- kernel/time/posix-cpu-timers.c | 59 +++++++++++---------------------- 1 file changed, 20 insertions(+), 39 deletions(-)
kernel/time/posix-cpu-timers.c +20 -39
@@ -294,29 +294,37 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times) }/* -* Sample a process (thread group) clock for the given group_leader task. -* Must be called with task sighand lock held for safe while_each_thread() -* traversal. +* Sample a process (thread group) clock for the given task clkid. If the +* group's cputime accounting is already enabled, read the atomic +* store. Otherwise a full update is required. Task's sighand lock must be +* held to protect the task traversal on a full update. */ static int cpu_clock_sample_group (const clockid_t which_clock,struct task_struct *p, -u64 *sample) +u64 *sample,bool start) { +struct thread_group_cputimer *cputimer = &p->signal->cputimer;struct task_cputime cputime; +if (!READ_ONCE (cputimer->running)) { +if (start) +thread_group_start_cputime (p, &cputime); +else +thread_group_cputime (p, &cputime); + }else { +sample_cputime_atomic (&cputime, &cputimer->cputime_atomic); + } +switch (CPUCLOCK_WHICH (which_clock)) {default :return -EINVAL ;case CPUCLOCK_PROF : -thread_group_cputime (p, &cputime); *sample = cputime.utime + cputime.stime;break ;case CPUCLOCK_VIRT : -thread_group_cputime (p, &cputime); *sample = cputime.utime;break ;case CPUCLOCK_SCHED : -thread_group_cputime (p, &cputime); *sample = cputime.sum_exec_runtime;break ; }
@@ -336,7 +344,7 @@ static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)if (CPUCLOCK_PERTHREAD (clock))cpu_clock_sample (clkid, tsk, &t);else -cpu_clock_sample_group (clkid, tsk, &t); +cpu_clock_sample_group (clkid, tsk, &t, false);put_task_struct (tsk); *tp =ns_to_timespec64 (t);
@@ -540,33 +548,6 @@ static void cpu_timer_fire(struct k_itimer *timer) }/* -* Sample a process (thread group) timer for the given group_leader task. -* Must be called with task sighand lock held for safe while_each_thread() -* traversal. -*/ -static int cpu_timer_sample_group (const clockid_t which_clock, -struct task_struct *p,u64 *sample) -{ -struct task_cputime cputime; - -thread_group_start_cputime (p, &cputime); -switch (CPUCLOCK_WHICH (which_clock)) { -default : -return -EINVAL ; -case CPUCLOCK_PROF : - *sample = cputime.utime + cputime.stime; -break ; -case CPUCLOCK_VIRT : - *sample = cputime.utime; -break ; -case CPUCLOCK_SCHED : - *sample = cputime.sum_exec_runtime; -break ; - } -return 0 ; -} - -/* * Guts of sys_timer_settime for CPU timers. * This is called with the timer locked and interrupts disabled. * If we return TIMER_RETRY, it's necessary to release the timer's lock
@@ -627,7 +608,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,if (CPUCLOCK_PERTHREAD (timer->it_clock)) {cpu_clock_sample (timer->it_clock, p, &val); }else { -cpu_timer_sample_group (timer->it_clock, p, &val); +cpu_clock_sample_group (timer->it_clock, p, &val, true); }if (old) {
@@ -755,7 +736,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp timer->it.cpu.expires =0 ;return ; }else { -cpu_timer_sample_group (timer->it_clock, p, &now); +cpu_clock_sample_group (timer->it_clock, p, &now, false);unlock_task_sighand (p, &flags); } }
@@ -1042,7 +1023,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)/* If the process is dying, no need to rearm */ goto unlock; } -cpu_timer_sample_group (timer->it_clock, p, &now); +cpu_clock_sample_group (timer->it_clock, p, &now, true);bump_cpu_timer (timer, now);/* Leave the sighand locked for the call below. */ }
@@ -1211,7 +1192,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,if (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED ))return ; - ret =cpu_timer_sample_group (clock_idx, tsk, &now); + ret =cpu_clock_sample_group (clock_idx, tsk, &now, true);if (oldval && ret != -EINVAL ) {/*
PATCH v2 9/38 posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
In reply to Thomas GleixnerExtract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
--- kernel/time/posix-cpu-timers.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/time/posix-cpu-timers.c +6 -5
@@ -556,10 +556,11 @@ static void cpu_timer_fire(struct k_itimstatic int posix_cpu_timer_set (struct k_itimer *timer,int timer_flags,struct itimerspec64 *new,struct itimerspec64 *old) { -unsigned long flags; -struct sighand_struct *sighand; -struct task_struct *p = timer->it.cpu.task; +clockid_t clkid =CPUCLOCK_WHICH (timer->it_clock);u64 old_expires, new_expires, old_incr, val; +struct task_struct *p = timer->it.cpu.task; +struct sighand_struct *sighand; +unsigned long flags;int ret;if (WARN_ON_ONCE (!p))
@@ -606,9 +607,9 @@ static int posix_cpu_timer_set(struct k_* check if it's already passed. In short, we need a sample. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (timer->it_clock, p, &val); +cpu_clock_sample (clkid, p, &val); }else { -cpu_clock_sample_group (timer->it_clock, p, &val, true); +cpu_clock_sample_group (clkid, p, &val, true); }if (old) {
Re: [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
Quoted 5 lines · Thomas Gleixner
Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: c7a37c6f4c651a531101c5721814333bae2804ec Gitweb: https://git.kernel.org/tip/c7a37c6f4c651a531101c5721814333bae2804ec Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:56 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:28 +02:00
posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
--- kernel/time/posix-cpu-timers.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/time/posix-cpu-timers.c +6 -5
@@ -556,10 +556,11 @@ static void cpu_timer_fire(struct k_itimer *timer)static int posix_cpu_timer_set (struct k_itimer *timer,int timer_flags,struct itimerspec64 *new,struct itimerspec64 *old) { -unsigned long flags; -struct sighand_struct *sighand; -struct task_struct *p = timer->it.cpu.task; +clockid_t clkid =CPUCLOCK_WHICH (timer->it_clock);u64 old_expires, new_expires, old_incr, val; +struct task_struct *p = timer->it.cpu.task; +struct sighand_struct *sighand; +unsigned long flags;int ret;if (WARN_ON_ONCE (!p))
@@ -606,9 +607,9 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,* check if it's already passed. In short, we need a sample. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (timer->it_clock, p, &val); +cpu_clock_sample (clkid, p, &val); }else { -cpu_clock_sample_group (timer->it_clock, p, &val, true); +cpu_clock_sample_group (clkid, p, &val, true); }if (old) {
PATCH v2 10/38 posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
In reply to Thomas GleixnerExtract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
--- kernel/time/posix-cpu-timers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/time/posix-cpu-timers.c +3 -2
@@ -699,6 +699,7 @@ static int posix_cpu_timer_set(struct k_static void posix_cpu_timer_get (struct k_itimer *timer,struct itimerspec64 *itp) { +clockid_t clkid =CPUCLOCK_WHICH (timer->it_clock);struct task_struct *p = timer->it.cpu.task;u64 now;
@@ -717,7 +718,7 @@ static void posix_cpu_timer_get(struct k* Sample the clock to take the difference with the expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (timer->it_clock, p, &now); +cpu_clock_sample (clkid, p, &now); }else {struct sighand_struct *sighand;unsigned long flags;
@@ -737,7 +738,7 @@ static void posix_cpu_timer_get(struct k timer->it.cpu.expires =0 ;return ; }else { -cpu_clock_sample_group (timer->it_clock, p, &now, false); +cpu_clock_sample_group (clkid, p, &now, false);unlock_task_sighand (p, &flags); } }
Re: [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
Quoted 5 lines · Thomas Gleixner
Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 99093c5b81f58815fbfc1fe301c87206c6f5f730 Gitweb: https://git.kernel.org/tip/99093c5b81f58815fbfc1fe301c87206c6f5f730 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:57 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:29 +02:00
posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
--- kernel/time/posix-cpu-timers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/time/posix-cpu-timers.c +3 -2
@@ -699,6 +699,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,static void posix_cpu_timer_get (struct k_itimer *timer,struct itimerspec64 *itp) { +clockid_t clkid =CPUCLOCK_WHICH (timer->it_clock);struct task_struct *p = timer->it.cpu.task;u64 now;
@@ -717,7 +718,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp* Sample the clock to take the difference with the expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (timer->it_clock, p, &now); +cpu_clock_sample (clkid, p, &now); }else {struct sighand_struct *sighand;unsigned long flags;
@@ -737,7 +738,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp timer->it.cpu.expires =0 ;return ; }else { -cpu_clock_sample_group (timer->it_clock, p, &now, false); +cpu_clock_sample_group (clkid, p, &now, false);unlock_task_sighand (p, &flags); } }
PATCH v2 11/38 posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
In reply to Thomas GleixnerExtract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
--- kernel/time/posix-cpu-timers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/time/posix-cpu-timers.c +3 -2
@@ -987,6 +987,7 @@ static void check_process_timers(struct*/ static void posix_cpu_timer_rearm (struct k_itimer *timer) { +clockid_t clkid =CPUCLOCK_WHICH (timer->it_clock);struct task_struct *p = timer->it.cpu.task;struct sighand_struct *sighand;unsigned long flags;
@@ -999,7 +1000,7 @@ static void posix_cpu_timer_rearm(struct* Fetch the current sample and update the timer's expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (timer->it_clock, p, &now); +cpu_clock_sample (clkid, p, &now);bump_cpu_timer (timer, now);if (unlikely (p->exit_state))return ;
@@ -1025,7 +1026,7 @@ static void posix_cpu_timer_rearm(struct/* If the process is dying, no need to rearm */ goto unlock; } -cpu_clock_sample_group (timer->it_clock, p, &now, true); +cpu_clock_sample_group (clkid, p, &now, true);bump_cpu_timer (timer, now);/* Leave the sighand locked for the call below. */ }
Re: [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
Quoted 5 lines · Thomas Gleixner
Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: da020ce406b2a9b714b82de9123a4c5a4848647b Gitweb: https://git.kernel.org/tip/da020ce406b2a9b714b82de9123a4c5a4848647b Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:58 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:29 +02:00
posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it as argument to the sample functions. That allows to simplify them once all callers are fixed.
--- kernel/time/posix-cpu-timers.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
kernel/time/posix-cpu-timers.c +3 -2
@@ -987,6 +987,7 @@ static void check_process_timers(struct task_struct *tsk,*/ static void posix_cpu_timer_rearm (struct k_itimer *timer) { +clockid_t clkid =CPUCLOCK_WHICH (timer->it_clock);struct task_struct *p = timer->it.cpu.task;struct sighand_struct *sighand;unsigned long flags;
@@ -999,7 +1000,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)* Fetch the current sample and update the timer's expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (timer->it_clock, p, &now); +cpu_clock_sample (clkid, p, &now);bump_cpu_timer (timer, now);if (unlikely (p->exit_state))return ;
@@ -1025,7 +1026,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)/* If the process is dying, no need to rearm */ goto unlock; } -cpu_clock_sample_group (timer->it_clock, p, &now, true); +cpu_clock_sample_group (clkid, p, &now, true);bump_cpu_timer (timer, now);/* Leave the sighand locked for the call below. */ }
PATCH v2 12/38 posix-cpu-timers: Remove pointless return value check
In reply to Thomas Gleixnerset_process_cpu_timer() checks already whether the clock id is valid. No point in checking the return value of the sample function. That allows to simplify the sample function later.
--- kernel/time/posix-cpu-timers.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/time/posix-cpu-timers.c +2 -3
@@ -1190,14 +1190,13 @@ void set_process_cpu_timer(struct task_s u64 *newval, u64 *oldval) {u64 now; -int ret;if (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED ))return ; - ret =cpu_clock_sample_group (clock_idx, tsk, &now, true); +cpu_clock_sample_group (clock_idx, tsk, &now, true); -if (oldval && ret != -EINVAL ) { +if (oldval) {/* * We are setting itimer. The *oldval is absolute and we update * it to be relative, *newval argument is relative and we update
Re: [patch V2 12/38] posix-cpu-timers: Remove pointless return value check
Quoted 5 lines · Thomas Gleixner
set_process_cpu_timer()checks already whether the clock id is valid. No point in checking the return value of the sample function. That allows to simplify the sample function later.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Remove pointless return value check
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 5405d0051f7ca820d1781d87baf4d730ff58f208 Gitweb: https://git.kernel.org/tip/5405d0051f7ca820d1781d87baf4d730ff58f208 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:08:59 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:30 +02:00
posix-cpu-timers: Remove pointless return value check
set_process_cpu_timer() checks already whether the clock id is valid. No point in checking the return value of the sample function. That allows to simplify the sample function later.
--- kernel/time/posix-cpu-timers.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/time/posix-cpu-timers.c +2 -3
@@ -1190,14 +1190,13 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, u64 *newval, u64 *oldval) {u64 now; -int ret;if (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED ))return ; - ret =cpu_clock_sample_group (clock_idx, tsk, &now, true); +cpu_clock_sample_group (clock_idx, tsk, &now, true); -if (oldval && ret != -EINVAL ) { +if (oldval) {/* * We are setting itimer. The *oldval is absolute and we update * it to be relative, *newval argument is relative and we update
PATCH v2 13/38 posix-cpu-timers: Simplify sample functions
In reply to Thomas GleixnerAll callers hand in a valdiated clock id. Remove the return value which was unchecked in most places anyway.
--- kernel/time/posix-cpu-timers.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-)
kernel/time/posix-cpu-timers.c +13 -15
@@ -180,14 +180,12 @@ posix_cpu_clock_set(const clockid_t cloc }/* -* Sample a per-thread clock for the given task. +* Sample a per-thread clock for the given task. clkid is validated. */ -static int cpu_clock_sample (const clockid_t which_clock, -struct task_struct *p,u64 *sample) +static void cpu_clock_sample (const clockid_t clkid,struct task_struct *p, +u64 *sample) { -switch (CPUCLOCK_WHICH (which_clock)) { -default : -return -EINVAL ; +switch (clkid) {case CPUCLOCK_PROF : *sample =prof_ticks (p);break ;
@@ -197,8 +195,9 @@ static int cpu_clock_sample(const clockicase CPUCLOCK_SCHED : *sample =task_sched_runtime (p);break ; +default : +WARN_ON_ONCE (1 ); } -return 0 ; }/*
@@ -297,11 +296,11 @@ thread_group_start_cputime(struct task_s* Sample a process (thread group) clock for the given task clkid. If the * group's cputime accounting is already enabled, read the atomic * store. Otherwise a full update is required. Task's sighand lock must be -* held to protect the task traversal on a full update. +* held to protect the task traversal on a full update. clkid is already +* validated. */ -static int cpu_clock_sample_group (const clockid_t which_clock, -struct task_struct *p, -u64 *sample,bool start) +static void cpu_clock_sample_group (const clockid_t clkid,struct task_struct *p, +u64 *sample,bool start) {struct thread_group_cputimer *cputimer = &p->signal->cputimer;struct task_cputime cputime;
@@ -315,9 +314,7 @@ static int cpu_clock_sample_group(constsample_cputime_atomic (&cputime, &cputimer->cputime_atomic); } -switch (CPUCLOCK_WHICH (which_clock)) { -default : -return -EINVAL ; +switch (clkid) {case CPUCLOCK_PROF : *sample = cputime.utime + cputime.stime;break ;
@@ -327,8 +324,9 @@ static int cpu_clock_sample_group(constcase CPUCLOCK_SCHED : *sample = cputime.sum_exec_runtime;break ; +default : +WARN_ON_ONCE (1 ); } -return 0 ; }static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp)
Re: [patch V2 13/38] posix-cpu-timers: Simplify sample functions
Quoted 4 lines · Thomas Gleixner
All callers hand in a valdiated clock id. Remove the return value which was unchecked in most places anyway.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Simplify sample functions
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 2092c1d4fed9f279d10600b4c1b5167dd8486a2a Gitweb: https://git.kernel.org/tip/2092c1d4fed9f279d10600b4c1b5167dd8486a2a Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:00 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:31 +02:00
posix-cpu-timers: Simplify sample functions
All callers hand in a valdiated clock id. Remove the return value which was unchecked in most places anyway.
--- kernel/time/posix-cpu-timers.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-)
kernel/time/posix-cpu-timers.c +13 -15
@@ -180,14 +180,12 @@ posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp) }/* -* Sample a per-thread clock for the given task. +* Sample a per-thread clock for the given task. clkid is validated. */ -static int cpu_clock_sample (const clockid_t which_clock, -struct task_struct *p,u64 *sample) +static void cpu_clock_sample (const clockid_t clkid,struct task_struct *p, +u64 *sample) { -switch (CPUCLOCK_WHICH (which_clock)) { -default : -return -EINVAL ; +switch (clkid) {case CPUCLOCK_PROF : *sample =prof_ticks (p);break ;
@@ -197,8 +195,9 @@ static int cpu_clock_sample(const clockid_t which_clock,case CPUCLOCK_SCHED : *sample =task_sched_runtime (p);break ; +default : +WARN_ON_ONCE (1 ); } -return 0 ; }/*
@@ -297,11 +296,11 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)* Sample a process (thread group) clock for the given task clkid. If the * group's cputime accounting is already enabled, read the atomic * store. Otherwise a full update is required. Task's sighand lock must be -* held to protect the task traversal on a full update. +* held to protect the task traversal on a full update. clkid is already +* validated. */ -static int cpu_clock_sample_group (const clockid_t which_clock, -struct task_struct *p, -u64 *sample,bool start) +static void cpu_clock_sample_group (const clockid_t clkid,struct task_struct *p, +u64 *sample,bool start) {struct thread_group_cputimer *cputimer = &p->signal->cputimer;struct task_cputime cputime;
@@ -315,9 +314,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock,sample_cputime_atomic (&cputime, &cputimer->cputime_atomic); } -switch (CPUCLOCK_WHICH (which_clock)) { -default : -return -EINVAL ; +switch (clkid) {case CPUCLOCK_PROF : *sample = cputime.utime + cputime.stime;break ;
@@ -327,8 +324,9 @@ static int cpu_clock_sample_group(const clockid_t which_clock,case CPUCLOCK_SCHED : *sample = cputime.sum_exec_runtime;break ; +default : +WARN_ON_ONCE (1 ); } -return 0 ; }static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp)
PATCH v2 14/38 posix-cpu-timers: Get rid of pointer indirection
In reply to Thomas GleixnerNow that the sample functions have no return value anymore, the result can simply be returned instead of using pointer indirection.
--- kernel/time/posix-cpu-timers.c | 50 ++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 28 deletions(-)
kernel/time/posix-cpu-timers.c +22 -28
@@ -182,22 +182,19 @@ posix_cpu_clock_set(const clockid_t cloc/* * Sample a per-thread clock for the given task. clkid is validated. */ -static void cpu_clock_sample (const clockid_t clkid,struct task_struct *p, -u64 *sample) +static u64 cpu_clock_sample (const clockid_t clkid,struct task_struct *p) {switch (clkid) {case CPUCLOCK_PROF : - *sample =prof_ticks (p); -break ; +return prof_ticks (p);case CPUCLOCK_VIRT : - *sample =virt_ticks (p); -break ; +return virt_ticks (p);case CPUCLOCK_SCHED : - *sample =task_sched_runtime (p); -break ; +return task_sched_runtime (p);default :WARN_ON_ONCE (1 ); } +return 0 ; }/*
@@ -299,8 +296,8 @@ thread_group_start_cputime(struct task_s* held to protect the task traversal on a full update. clkid is already * validated. */ -static void cpu_clock_sample_group (const clockid_t clkid,struct task_struct *p, -u64 *sample,bool start) +static u64 cpu_clock_sample_group (const clockid_t clkid,struct task_struct *p, +bool start) {struct thread_group_cputimer *cputimer = &p->signal->cputimer;struct task_cputime cputime;
@@ -316,17 +313,15 @@ static void cpu_clock_sample_group(constswitch (clkid) {case CPUCLOCK_PROF : - *sample = cputime.utime + cputime.stime; -break ; +return cputime.utime + cputime.stime;case CPUCLOCK_VIRT : - *sample = cputime.utime; -break ; +return cputime.utime;case CPUCLOCK_SCHED : - *sample = cputime.sum_exec_runtime; -break ; +return cputime.sum_exec_runtime;default :WARN_ON_ONCE (1 ); } +return 0 ; }static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp)
@@ -340,9 +335,9 @@ static int posix_cpu_clock_get(const cloreturn -EINVAL ;if (CPUCLOCK_PERTHREAD (clock)) -cpu_clock_sample (clkid, tsk, &t); + t =cpu_clock_sample (clkid, tsk);else -cpu_clock_sample_group (clkid, tsk, &t, false); + t =cpu_clock_sample_group (clkid, tsk, false);put_task_struct (tsk); *tp =ns_to_timespec64 (t);
@@ -604,11 +599,10 @@ static int posix_cpu_timer_set(struct k_* times (in arm_timer). With an absolute time, we must * check if it's already passed. In short, we need a sample. */ -if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (clkid, p, &val); - }else { -cpu_clock_sample_group (clkid, p, &val, true); - } +if (CPUCLOCK_PERTHREAD (timer->it_clock)) + val =cpu_clock_sample (clkid, p); +else + val =cpu_clock_sample_group (clkid, p, true);if (old) {if (old_expires ==0 ) {
@@ -716,7 +710,7 @@ static void posix_cpu_timer_get(struct k* Sample the clock to take the difference with the expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (clkid, p, &now); + now =cpu_clock_sample (clkid, p); }else {struct sighand_struct *sighand;unsigned long flags;
@@ -736,7 +730,7 @@ static void posix_cpu_timer_get(struct k timer->it.cpu.expires =0 ;return ; }else { -cpu_clock_sample_group (clkid, p, &now, false); + now =cpu_clock_sample_group (clkid, p, false);unlock_task_sighand (p, &flags); } }
@@ -998,7 +992,7 @@ static void posix_cpu_timer_rearm(struct* Fetch the current sample and update the timer's expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (clkid, p, &now); + now =cpu_clock_sample (clkid, p);bump_cpu_timer (timer, now);if (unlikely (p->exit_state))return ;
@@ -1024,7 +1018,7 @@ static void posix_cpu_timer_rearm(struct/* If the process is dying, no need to rearm */ goto unlock; } -cpu_clock_sample_group (clkid, p, &now, true); + now =cpu_clock_sample_group (clkid, p, true);bump_cpu_timer (timer, now);/* Leave the sighand locked for the call below. */ }
@@ -1192,7 +1186,7 @@ void set_process_cpu_timer(struct task_sif (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED ))return ; -cpu_clock_sample_group (clock_idx, tsk, &now, true); + now =cpu_clock_sample_group (clock_idx, tsk, true);if (oldval) {/*
Re: [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection
Quoted 4 lines · Thomas Gleixner
Now that the sample functions have no return value anymore, the result can simply be returned instead of using pointer indirection.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Get rid of pointer indirection
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 8c2d74f03705c2c993a57673bae8fd535eabede6 Gitweb: https://git.kernel.org/tip/8c2d74f03705c2c993a57673bae8fd535eabede6 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:01 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:32 +02:00
posix-cpu-timers: Get rid of pointer indirection
Now that the sample functions have no return value anymore, the result can simply be returned instead of using pointer indirection.
--- kernel/time/posix-cpu-timers.c | 50 ++++++++++++++------------------- 1 file changed, 22 insertions(+), 28 deletions(-)
kernel/time/posix-cpu-timers.c +22 -28
@@ -182,22 +182,19 @@ posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)/* * Sample a per-thread clock for the given task. clkid is validated. */ -static void cpu_clock_sample (const clockid_t clkid,struct task_struct *p, -u64 *sample) +static u64 cpu_clock_sample (const clockid_t clkid,struct task_struct *p) {switch (clkid) {case CPUCLOCK_PROF : - *sample =prof_ticks (p); -break ; +return prof_ticks (p);case CPUCLOCK_VIRT : - *sample =virt_ticks (p); -break ; +return virt_ticks (p);case CPUCLOCK_SCHED : - *sample =task_sched_runtime (p); -break ; +return task_sched_runtime (p);default :WARN_ON_ONCE (1 ); } +return 0 ; }/*
@@ -299,8 +296,8 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)* held to protect the task traversal on a full update. clkid is already * validated. */ -static void cpu_clock_sample_group (const clockid_t clkid,struct task_struct *p, -u64 *sample,bool start) +static u64 cpu_clock_sample_group (const clockid_t clkid,struct task_struct *p, +bool start) {struct thread_group_cputimer *cputimer = &p->signal->cputimer;struct task_cputime cputime;
@@ -316,17 +313,15 @@ static void cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,switch (clkid) {case CPUCLOCK_PROF : - *sample = cputime.utime + cputime.stime; -break ; +return cputime.utime + cputime.stime;case CPUCLOCK_VIRT : - *sample = cputime.utime; -break ; +return cputime.utime;case CPUCLOCK_SCHED : - *sample = cputime.sum_exec_runtime; -break ; +return cputime.sum_exec_runtime;default :WARN_ON_ONCE (1 ); } +return 0 ; }static int posix_cpu_clock_get (const clockid_t clock,struct timespec64 *tp)
@@ -340,9 +335,9 @@ static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)return -EINVAL ;if (CPUCLOCK_PERTHREAD (clock)) -cpu_clock_sample (clkid, tsk, &t); + t =cpu_clock_sample (clkid, tsk);else -cpu_clock_sample_group (clkid, tsk, &t, false); + t =cpu_clock_sample_group (clkid, tsk, false);put_task_struct (tsk); *tp =ns_to_timespec64 (t);
@@ -604,11 +599,10 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,* times (in arm_timer). With an absolute time, we must * check if it's already passed. In short, we need a sample. */ -if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (clkid, p, &val); - }else { -cpu_clock_sample_group (clkid, p, &val, true); - } +if (CPUCLOCK_PERTHREAD (timer->it_clock)) + val =cpu_clock_sample (clkid, p); +else + val =cpu_clock_sample_group (clkid, p, true);if (old) {if (old_expires ==0 ) {
@@ -716,7 +710,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp* Sample the clock to take the difference with the expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (clkid, p, &now); + now =cpu_clock_sample (clkid, p); }else {struct sighand_struct *sighand;unsigned long flags;
@@ -736,7 +730,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp timer->it.cpu.expires =0 ;return ; }else { -cpu_clock_sample_group (clkid, p, &now, false); + now =cpu_clock_sample_group (clkid, p, false);unlock_task_sighand (p, &flags); } }
@@ -998,7 +992,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)* Fetch the current sample and update the timer's expiry time. */ if (CPUCLOCK_PERTHREAD (timer->it_clock)) { -cpu_clock_sample (clkid, p, &now); + now =cpu_clock_sample (clkid, p);bump_cpu_timer (timer, now);if (unlikely (p->exit_state))return ;
@@ -1024,7 +1018,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)/* If the process is dying, no need to rearm */ goto unlock; } -cpu_clock_sample_group (clkid, p, &now, true); + now =cpu_clock_sample_group (clkid, p, true);bump_cpu_timer (timer, now);/* Leave the sighand locked for the call below. */ }
@@ -1192,7 +1186,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,if (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED ))return ; -cpu_clock_sample_group (clock_idx, tsk, &now, true); + now =cpu_clock_sample_group (clock_idx, tsk, true);if (oldval) {/*
PATCH v2 15/38 posix-cpu-timers: Sample task times once in expiry check
In reply to Thomas GleixnerSampling the task times twice does not make sense. Do it once.
--- kernel/time/posix-cpu-timers.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
kernel/time/posix-cpu-timers.c +6 -4
@@ -785,9 +785,9 @@ static inline void check_dl_overrun(strustatic void check_thread_timers (struct task_struct *tsk,struct list_head *firing) { -struct list_head *timers = tsk->cpu_timers;struct task_cputime *tsk_expires = &tsk->cputime_expires; -u64 expires; +struct list_head *timers = tsk->cpu_timers; +u64 expires, stime, utime;unsigned long soft;if (dl_task (tsk))
@@ -800,10 +800,12 @@ static void check_thread_timers(struct tif (task_cputime_zero (&tsk->cputime_expires))return ; - expires =check_timers_list (timers, firing,prof_ticks (tsk)); +task_cputime (tsk, &utime, &stime); + + expires =check_timers_list (timers, firing, utime + stime); tsk_expires->prof_exp = expires; - expires =check_timers_list (++timers, firing,virt_ticks (tsk)); + expires =check_timers_list (++timers, firing, utime); tsk_expires->virt_exp = expires; tsk_expires->sched_exp = check_timers_list(++timers, firing,
Re: [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check
Quoted 3 lines · Thomas Gleixner
Sampling the task times twice does not make sense. Do it once.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Sample task times once in expiry check
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 0476ff2c151ee35bda2f938e8828b6f6113ebf55 Gitweb: https://git.kernel.org/tip/0476ff2c151ee35bda2f938e8828b6f6113ebf55 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:02 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:32 +02:00
posix-cpu-timers: Sample task times once in expiry check
Sampling the task times twice does not make sense. Do it once.
--- kernel/time/posix-cpu-timers.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
kernel/time/posix-cpu-timers.c +6 -4
@@ -785,9 +785,9 @@ static inline void check_dl_overrun(struct task_struct *tsk)static void check_thread_timers (struct task_struct *tsk,struct list_head *firing) { -struct list_head *timers = tsk->cpu_timers;struct task_cputime *tsk_expires = &tsk->cputime_expires; -u64 expires; +struct list_head *timers = tsk->cpu_timers; +u64 expires, stime, utime;unsigned long soft;if (dl_task (tsk))
@@ -800,10 +800,12 @@ static void check_thread_timers(struct task_struct *tsk,if (task_cputime_zero (&tsk->cputime_expires))return ; - expires =check_timers_list (timers, firing,prof_ticks (tsk)); +task_cputime (tsk, &utime, &stime); + + expires =check_timers_list (timers, firing, utime + stime); tsk_expires->prof_exp = expires; - expires =check_timers_list (++timers, firing,virt_ticks (tsk)); + expires =check_timers_list (++timers, firing, utime); tsk_expires->virt_exp = expires; tsk_expires->sched_exp = check_timers_list(++timers, firing,
PATCH v2 16/38 posix-cpu-timers: Move prof/virt_ticks into caller
In reply to Thomas GleixnerThe functions have only one caller left. No point in having them.
Move the almost duplicated code into the caller and simplify it.
--- kernel/time/posix-cpu-timers.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-)
kernel/time/posix-cpu-timers.c +9 -21
@@ -130,23 +130,6 @@ static inline int task_cputime_zero(consreturn 0 ; } -static inline u64 prof_ticks (struct task_struct *p) -{ -u64 utime, stime; - -task_cputime (p, &utime, &stime); - -return utime + stime; -} -static inline u64 virt_ticks (struct task_struct *p) -{ -u64 utime, stime; - -task_cputime (p, &utime, &stime); - -return utime; -} -static int posix_cpu_clock_getres (const clockid_t which_clock,struct timespec64 *tp) {
@@ -184,13 +167,18 @@ posix_cpu_clock_set(const clockid_t cloc*/ static u64 cpu_clock_sample (const clockid_t clkid,struct task_struct *p) { +u64 utime, stime; + +if (clkid ==CPUCLOCK_SCHED ) +return task_sched_runtime (p); + +task_cputime (p, &utime, &stime); +switch (clkid) {case CPUCLOCK_PROF : -return prof_ticks (p); +return utime + stime;case CPUCLOCK_VIRT : -return virt_ticks (p); -case CPUCLOCK_SCHED : -return task_sched_runtime (p); +return utime;default :WARN_ON_ONCE (1 ); }
Re: [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller
Quoted 5 lines · Thomas Gleixner
The functions have only one caller left. No point in having them.
Move the almost duplicated code into the caller and simplify it.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Move prof/virt_ticks into caller
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: ab693c5a5e3107f035d5162e6ada9aaf7dd76a1d Gitweb: https://git.kernel.org/tip/ab693c5a5e3107f035d5162e6ada9aaf7dd76a1d Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:03 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:33 +02:00
posix-cpu-timers: Move prof/virt_ticks into caller
The functions have only one caller left. No point in having them.
Move the almost duplicated code into the caller and simplify it.
--- kernel/time/posix-cpu-timers.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-)
kernel/time/posix-cpu-timers.c +9 -21
@@ -130,23 +130,6 @@ static inline int task_cputime_zero(const struct task_cputime *cputime)return 0 ; } -static inline u64 prof_ticks (struct task_struct *p) -{ -u64 utime, stime; - -task_cputime (p, &utime, &stime); - -return utime + stime; -} -static inline u64 virt_ticks (struct task_struct *p) -{ -u64 utime, stime; - -task_cputime (p, &utime, &stime); - -return utime; -} -static int posix_cpu_clock_getres (const clockid_t which_clock,struct timespec64 *tp) {
@@ -184,13 +167,18 @@ posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)*/ static u64 cpu_clock_sample (const clockid_t clkid,struct task_struct *p) { +u64 utime, stime; + +if (clkid ==CPUCLOCK_SCHED ) +return task_sched_runtime (p); + +task_cputime (p, &utime, &stime); +switch (clkid) {case CPUCLOCK_PROF : -return prof_ticks (p); +return utime + stime;case CPUCLOCK_VIRT : -return virt_ticks (p); -case CPUCLOCK_SCHED : -return task_sched_runtime (p); +return utime;default :WARN_ON_ONCE (1 ); }
PATCH v2 17/38 posix-cpu-timers: Create a container struct
In reply to Thomas GleixnerPer task/process data of posix CPU timers is all over the place which makes the code hard to follow and requires ifdeffery.
Create a container to hold all this information in one place, so data is consolidated and the ifdeffery can be confined to the posix timer header file and removed from places like fork.
As a first step, move the cpu_timers list head array into the new struct and clean up the initializers and simplify fork. The remaining #ifdef in fork will be removed later.
---
V2: Have an empty struct for POSIX_TIMERS=n so ifdefs can be avoided
--- include/linux/init_task.h | 11 ----------- include/linux/posix-timers.h | 34 ++++++++++++++++++++++++++++++++++ include/linux/sched.h | 4 +++- include/linux/sched/signal.h | 5 +++-- kernel/fork.c | 11 ++++------- kernel/time/posix-cpu-timers.c | 20 ++++++++++---------- 6 files changed, 54 insertions(+), 31 deletions(-)
include/linux/init_task.h +0 -11
@@ -36,17 +36,6 @@ extern struct cred init_cred;#define INIT_PREV_CPUTIME (x)#endif -#ifdef CONFIG_POSIX_TIMERS -#define INIT_CPU_TIMERS (s) \ - .cpu_timers = { \ - LIST_HEAD_INIT(s.cpu_timers[0]), \ - LIST_HEAD_INIT(s.cpu_timers[1]), \ - LIST_HEAD_INIT(s.cpu_timers[2]), \ - }, -#else -#define INIT_CPU_TIMERS (s) -#endif -#define INIT_TASK_COMM "swapper"/* Attach to the init_task data structure for proper alignment */
include/linux/posix-timers.h +34 -0
@@ -62,6 +62,40 @@ static inline int clockid_to_fd(const clreturn ~(clk >>3 ); } +/** +* posix_cputimers - Container for posix CPU timer related data +* @cpu_timers: List heads to queue posix CPU timers +* +* Used in task_struct and signal_struct +*/ +struct posix_cputimers { +struct list_head cpu_timers[CPUCLOCK_MAX ]; +}; + +static inline void posix_cputimers_init (struct posix_cputimers *pct) +{ +INIT_LIST_HEAD (&pct->cpu_timers[0 ]); +INIT_LIST_HEAD (&pct->cpu_timers[1 ]); +INIT_LIST_HEAD (&pct->cpu_timers[2 ]); +} + +#ifdef CONFIG_POSIX_TIMERS +/* Init task static initializer */ +#define INIT_CPU_TIMERLISTS (c) { \ + LIST_HEAD_INIT(c.cpu_timers[0]), \ + LIST_HEAD_INIT(c.cpu_timers[1]), \ + LIST_HEAD_INIT(c.cpu_timers[2]), \ +} + +#define INIT_CPU_TIMERS (s) \ + .posix_cputimers = { \ + .cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers), \ + }, +#else +struct posix_cputimers { }; +#define INIT_CPU_TIMERS (s) +#endif +#define REQUEUE_PENDING 1/**
include/linux/sched.h +3 -1
@@ -28,6 +28,7 @@#include <linux/signal_types.h> #include <linux/mm_types_task.h> #include <linux/task_io_accounting.h> +#include <linux/posix-timers.h> #include <linux/rseq.h> /* task_struct member predeclarations (sorted alphabetically): */
@@ -878,8 +879,9 @@ struct task_struct {#ifdef CONFIG_POSIX_TIMERS struct task_cputime cputime_expires; -struct list_head cpu_timers[3 ];#endif +/* Empty if CONFIG_POSIX_CPUTIMERS=n */ +struct posix_cputimers posix_cputimers;/* Process credentials: */
include/linux/sched/signal.h +3 -2
@@ -9,6 +9,7 @@#include <linux/sched/task.h> #include <linux/cred.h> #include <linux/refcount.h> +#include <linux/posix-timers.h> /* * Types defining task->signal and task->sighand and APIs using them:
@@ -151,9 +152,9 @@ struct signal_struct {/* Earliest-expiration cache. */ struct task_cputime cputime_expires; -struct list_head cpu_timers[3 ]; -#endif +/* Empty if CONFIG_POSIX_TIMERS=n */ +struct posix_cputimers posix_cputimers;/* PID/PID hash table linkage. */ struct pid *pids[PIDTYPE_MAX ];
kernel/fork.c +4 -7
@@ -1523,6 +1523,7 @@ void __cleanup_sighand(struct sighand_st*/ static void posix_cpu_timers_init_group (struct signal_struct *sig) { +struct posix_cputimers *pct = &sig->posix_cputimers;unsigned long cpu_limit; cpu_limit =READ_ONCE (sig->rlim[RLIMIT_CPU ].rlim_cur);
@@ -1531,10 +1532,7 @@ static void posix_cpu_timers_init_group( sig->cputimer.running = true; } -/* The timer lists. */ -INIT_LIST_HEAD (&sig->cpu_timers[0 ]); -INIT_LIST_HEAD (&sig->cpu_timers[1 ]); -INIT_LIST_HEAD (&sig->cpu_timers[2 ]); +posix_cputimers_init (pct); }#else static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { }
@@ -1649,9 +1647,8 @@ static void posix_cpu_timers_init(struct tsk->cputime_expires.prof_exp =0 ; tsk->cputime_expires.virt_exp =0 ; tsk->cputime_expires.sched_exp =0 ; -INIT_LIST_HEAD (&tsk->cpu_timers[0 ]); -INIT_LIST_HEAD (&tsk->cpu_timers[1 ]); - INIT_LIST_HEAD(&tsk->cpu_timers[2]); + + posix_cputimers_init(&tsk->posix_cputimers); }#else static inline void posix_cpu_timers_init (struct task_struct *tsk) { }
kernel/time/posix-cpu-timers.c +10 -10
@@ -407,11 +407,11 @@ static void cleanup_timers_list(struct l* * This must be called with the siglock held. */ -static void cleanup_timers (struct list_head *head) +static void cleanup_timers (struct posix_cputimers *pct) { -cleanup_timers_list (head); -cleanup_timers_list (++head); -cleanup_timers_list (++head); +cleanup_timers_list (&pct->cpu_timers[CPUCLOCK_PROF ]); +cleanup_timers_list (&pct->cpu_timers[CPUCLOCK_VIRT ]); +cleanup_timers_list (&pct->cpu_timers[CPUCLOCK_SCHED ]); }/*
@@ -421,11 +421,11 @@ static void cleanup_timers(struct list_h*/ void posix_cpu_timers_exit (struct task_struct *tsk) { -cleanup_timers (tsk->cpu_timers); +cleanup_timers (&tsk->posix_cputimers); }void posix_cpu_timers_exit_group (struct task_struct *tsk) { -cleanup_timers (tsk->signal->cpu_timers); +cleanup_timers (&tsk->signal->posix_cputimers); }static inline int expires_gt (u64 expires,u64 new_exp)
@@ -446,10 +446,10 @@ static void arm_timer(struct k_itimer *tstruct cpu_timer_list *next;if (CPUCLOCK_PERTHREAD (timer->it_clock)) { - head = p->cpu_timers; + head = p->posix_cputimers.cpu_timers; cputime_expires = &p->cputime_expires; }else { - head = p->signal->cpu_timers; + head = p->signal->posix_cputimers.cpu_timers; cputime_expires = &p->signal->cputime_expires; } head +=CPUCLOCK_WHICH (timer->it_clock);
@@ -773,8 +773,8 @@ static inline void check_dl_overrun(strustatic void check_thread_timers (struct task_struct *tsk,struct list_head *firing) { +struct list_head *timers = tsk->posix_cputimers.cpu_timers;struct task_cputime *tsk_expires = &tsk->cputime_expires; -struct list_head *timers = tsk->cpu_timers;u64 expires, stime, utime;unsigned long soft;
@@ -879,9 +879,9 @@ static void check_process_timers(struct struct list_head *firing) {struct signal_struct *const sig = tsk->signal; +struct list_head *timers = sig->posix_cputimers.cpu_timers;u64 utime, ptime, virt_expires, prof_expires;u64 sum_sched_runtime, sched_expires; -struct list_head *timers = sig->cpu_timers;struct task_cputime cputime;unsigned long soft;
Re: [patch V2 17/38] posix-cpu-timers: Create a container struct
include/linux/posix-timers.h static inline int clockid_to_fd(const cl · line 63
Quoted 5 lines · Thomas Gleixner
include/linux/posix-timers.h +0
-0@@ -62,6 +62,40 @@ static inline int clockid_to_fd(const clreturn ~(clk >>3 ); }
Shouldn't you start the #ifdef CONFIG_POSIX_TIMERS here? Because you're redefining struct posix_cputimers otherwise.
Quoted 24 lines
include/linux/posix-timers.h +24
-0+/** +* posix_cputimers - Container for posix CPU timer related data +* @cpu_timers: List heads to queue posix CPU timers +* +* Used in task_struct and signal_struct +*/ +struct posix_cputimers { +struct list_head cpu_timers[CPUCLOCK_MAX ]; +}; + +static inline void posix_cputimers_init (struct posix_cputimers *pct) +{ +INIT_LIST_HEAD (&pct->cpu_timers[0 ]); +INIT_LIST_HEAD (&pct->cpu_timers[1 ]); +INIT_LIST_HEAD (&pct->cpu_timers[2 ]); +} + +#ifdef CONFIG_POSIX_TIMERS +/* Init task static initializer */ +#define INIT_CPU_TIMERLISTS (c) { \ + LIST_HEAD_INIT(c.cpu_timers[0]), \ + LIST_HEAD_INIT(c.cpu_timers[1]), \ + LIST_HEAD_INIT(c.cpu_timers[2]), \ +}
include/linux/posix-timers.h static inline int clockid_to_fd(const cl · line 98
Quoted 10 lines
include/linux/posix-timers.h +10
-0+ +#define INIT_CPU_TIMERS (s) \ + .posix_cputimers = { \ + .cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers), \ + }, +#else +struct posix_cputimers { }; +#define INIT_CPU_TIMERS (s) +#endif +
Other than that:
Re: [patch V2 17/38] posix-cpu-timers: Create a container struct
Quoted 9 lines · Frederic Weisbecker
include/linux/posix-timers.h static inline int clockid_to_fd(const cl · line 63
Quoted 5 lines · Thomas Gleixner
include/linux/posix-timers.h +0
-0@@ -62,6 +62,40 @@ static inline int clockid_to_fd(const clreturn ~(clk >>3 ); }Shouldn't you start the #ifdef
CONFIG_POSIX_TIMERShere? Because you're redefining structposix_cputimersotherwise.
Yeah...
[tip: timers/core] posix-cpu-timers: Create a container struct
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 2b69942f9021bf75bd1b001f53bd2578361fadf3 Gitweb: https://git.kernel.org/tip/2b69942f9021bf75bd1b001f53bd2578361fadf3 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:04 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:33 +02:00
posix-cpu-timers: Create a container struct
Per task/process data of posix CPU timers is all over the place which makes the code hard to follow and requires ifdeffery.
Create a container to hold all this information in one place, so data is consolidated and the ifdeffery can be confined to the posix timer header file and removed from places like fork.
As a first step, move the cpu_timers list head array into the new struct and clean up the initializers and simplify fork. The remaining #ifdef in fork will be removed later.
--- include/linux/init_task.h | 11 +----------- include/linux/posix-timers.h | 34 +++++++++++++++++++++++++++++++++- include/linux/sched.h | 4 +++- include/linux/sched/signal.h | 5 +++-- kernel/fork.c | 11 ++++------- kernel/time/posix-cpu-timers.c | 20 +++++++++---------- 6 files changed, 54 insertions(+), 31 deletions(-)
include/linux/init_task.h +0 -11
@@ -36,17 +36,6 @@ extern struct cred init_cred;#define INIT_PREV_CPUTIME (x)#endif -#ifdef CONFIG_POSIX_TIMERS -#define INIT_CPU_TIMERS (s) \ - .cpu_timers = { \ - LIST_HEAD_INIT(s.cpu_timers[0]), \ - LIST_HEAD_INIT(s.cpu_timers[1]), \ - LIST_HEAD_INIT(s.cpu_timers[2]), \ - }, -#else -#define INIT_CPU_TIMERS (s) -#endif -#define INIT_TASK_COMM "swapper"/* Attach to the init_task data structure for proper alignment */
include/linux/posix-timers.h +34 -0
@@ -62,6 +62,40 @@ static inline int clockid_to_fd(const clockid_t clk)return ~(clk >>3 ); } +#ifdef CONFIG_POSIX_TIMERS +/** +* posix_cputimers - Container for posix CPU timer related data +* @cpu_timers: List heads to queue posix CPU timers +* +* Used in task_struct and signal_struct +*/ +struct posix_cputimers { +struct list_head cpu_timers[CPUCLOCK_MAX ]; +}; + +static inline void posix_cputimers_init (struct posix_cputimers *pct) +{ +INIT_LIST_HEAD (&pct->cpu_timers[0 ]); +INIT_LIST_HEAD (&pct->cpu_timers[1 ]); +INIT_LIST_HEAD (&pct->cpu_timers[2 ]); +} + +/* Init task static initializer */ +#define INIT_CPU_TIMERLISTS (c) { \ + LIST_HEAD_INIT(c.cpu_timers[0]), \ + LIST_HEAD_INIT(c.cpu_timers[1]), \ + LIST_HEAD_INIT(c.cpu_timers[2]), \ +} + +#define INIT_CPU_TIMERS (s) \ + .posix_cputimers = { \ + .cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers), \ + }, +#else +struct posix_cputimers { }; +#define INIT_CPU_TIMERS (s) +#endif +#define REQUEUE_PENDING 1/**
include/linux/sched.h +3 -1
@@ -28,6 +28,7 @@#include <linux/signal_types.h> #include <linux/mm_types_task.h> #include <linux/task_io_accounting.h> +#include <linux/posix-timers.h> #include <linux/rseq.h> /* task_struct member predeclarations (sorted alphabetically): */
@@ -878,8 +879,9 @@ struct task_struct {#ifdef CONFIG_POSIX_TIMERS struct task_cputime cputime_expires; -struct list_head cpu_timers[3 ];#endif +/* Empty if CONFIG_POSIX_CPUTIMERS=n */ +struct posix_cputimers posix_cputimers;/* Process credentials: */
include/linux/sched/signal.h +3 -2
@@ -9,6 +9,7 @@#include <linux/sched/task.h> #include <linux/cred.h> #include <linux/refcount.h> +#include <linux/posix-timers.h> /* * Types defining task->signal and task->sighand and APIs using them:
@@ -151,9 +152,9 @@ struct signal_struct {/* Earliest-expiration cache. */ struct task_cputime cputime_expires; -struct list_head cpu_timers[3 ]; -#endif +/* Empty if CONFIG_POSIX_TIMERS=n */ +struct posix_cputimers posix_cputimers;/* PID/PID hash table linkage. */ struct pid *pids[PIDTYPE_MAX ];
kernel/fork.c +4 -7
@@ -1523,6 +1523,7 @@ void __cleanup_sighand(struct sighand_struct *sighand)*/ static void posix_cpu_timers_init_group (struct signal_struct *sig) { +struct posix_cputimers *pct = &sig->posix_cputimers;unsigned long cpu_limit; cpu_limit =READ_ONCE (sig->rlim[RLIMIT_CPU ].rlim_cur);
@@ -1531,10 +1532,7 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) sig->cputimer.running = true; } -/* The timer lists. */ -INIT_LIST_HEAD (&sig->cpu_timers[0 ]); -INIT_LIST_HEAD (&sig->cpu_timers[1 ]); -INIT_LIST_HEAD (&sig->cpu_timers[2 ]); +posix_cputimers_init (pct); }#else static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { }
@@ -1649,9 +1647,8 @@ static void posix_cpu_timers_init(struct task_struct *tsk) tsk->cputime_expires.prof_exp =0 ; tsk->cputime_expires.virt_exp =0 ; tsk->cputime_expires.sched_exp =0 ; -INIT_LIST_HEAD (&tsk->cpu_timers[0 ]); -INIT_LIST_HEAD (&tsk->cpu_timers[1 ]); - INIT_LIST_HEAD(&tsk->cpu_timers[2]); + + posix_cputimers_init(&tsk->posix_cputimers); }#else static inline void posix_cpu_timers_init (struct task_struct *tsk) { }
kernel/time/posix-cpu-timers.c +10 -10
@@ -407,11 +407,11 @@ static void cleanup_timers_list(struct list_head *head)* * This must be called with the siglock held. */ -static void cleanup_timers (struct list_head *head) +static void cleanup_timers (struct posix_cputimers *pct) { -cleanup_timers_list (head); -cleanup_timers_list (++head); -cleanup_timers_list (++head); +cleanup_timers_list (&pct->cpu_timers[CPUCLOCK_PROF ]); +cleanup_timers_list (&pct->cpu_timers[CPUCLOCK_VIRT ]); +cleanup_timers_list (&pct->cpu_timers[CPUCLOCK_SCHED ]); }/*
@@ -421,11 +421,11 @@ static void cleanup_timers(struct list_head *head)*/ void posix_cpu_timers_exit (struct task_struct *tsk) { -cleanup_timers (tsk->cpu_timers); +cleanup_timers (&tsk->posix_cputimers); }void posix_cpu_timers_exit_group (struct task_struct *tsk) { -cleanup_timers (tsk->signal->cpu_timers); +cleanup_timers (&tsk->signal->posix_cputimers); }static inline int expires_gt (u64 expires,u64 new_exp)
@@ -446,10 +446,10 @@ static void arm_timer(struct k_itimer *timer)struct cpu_timer_list *next;if (CPUCLOCK_PERTHREAD (timer->it_clock)) { - head = p->cpu_timers; + head = p->posix_cputimers.cpu_timers; cputime_expires = &p->cputime_expires; }else { - head = p->signal->cpu_timers; + head = p->signal->posix_cputimers.cpu_timers; cputime_expires = &p->signal->cputime_expires; } head +=CPUCLOCK_WHICH (timer->it_clock);
@@ -773,8 +773,8 @@ static inline void check_dl_overrun(struct task_struct *tsk)static void check_thread_timers (struct task_struct *tsk,struct list_head *firing) { +struct list_head *timers = tsk->posix_cputimers.cpu_timers;struct task_cputime *tsk_expires = &tsk->cputime_expires; -struct list_head *timers = tsk->cpu_timers;u64 expires, stime, utime;unsigned long soft;
@@ -879,9 +879,9 @@ static void check_process_timers(struct task_struct *tsk, struct list_head *firing) {struct signal_struct *const sig = tsk->signal; +struct list_head *timers = sig->posix_cputimers.cpu_timers;u64 utime, ptime, virt_expires, prof_expires;u64 sum_sched_runtime, sched_expires; -struct list_head *timers = sig->cpu_timers;struct task_cputime cputime;unsigned long soft;
PATCH v2 19/38 posix-cpu-timers: Move expiry cache into struct posix_cputimers
In reply to Thomas GleixnerThe expiry cache belongs into the posix_cputimers container where the other cpu timers information is.
---
V2: Adapt to previous change of empty struct and move the group init out of
line to avoid include hell.
--- include/linux/posix-timers.h | 24 ++++++++++++++++++++- include/linux/sched.h | 8 ------- include/linux/sched/signal.h | 3 -- kernel/fork.c | 25 ++-------------------- kernel/sched/rt.c | 6 +++-- kernel/time/posix-cpu-timers.c | 45 ++++++++++++++++++++++++----------------- 6 files changed, 57 insertions(+), 54 deletions(-)
include/linux/posix-timers.h +23 -1
@@ -62,24 +62,43 @@ static inline int clockid_to_fd(const clreturn ~(clk >>3 ); } +/* +* Alternate field names for struct task_cputime when used on cache +* expirations. Will go away soon. +*/ +#define virt_exp utime +#define prof_exp stime +#define sched_exp sum_exec_runtime + +#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data +* @cputime_expires: Earliest-expiration cache * @cpu_timers: List heads to queue posix CPU timers * * Used in task_struct and signal_struct */ struct posix_cputimers { +struct task_cputime cputime_expires;struct list_head cpu_timers[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { +memset (&pct->cputime_expires,0 ,sizeof (pct->cputime_expires));INIT_LIST_HEAD (&pct->cpu_timers[0 ]);INIT_LIST_HEAD (&pct->cpu_timers[1 ]);INIT_LIST_HEAD (&pct->cpu_timers[2 ]); } -#ifdef CONFIG_POSIX_TIMERS +void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit); + +static inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct, +u64 runtime) +{ + pct->cputime_expires.sched_exp = runtime; +} +/* Init task static initializer */ #define INIT_CPU_TIMERLISTS (c) { \ LIST_HEAD_INIT(c.cpu_timers[0]), \
@@ -94,6 +113,9 @@ static inline void posix_cputimers_init(#else struct posix_cputimers { };#define INIT_CPU_TIMERS (s) +static inline void posix_cputimers_init (struct posix_cputimers *pct) { } +static inline void posix_cputimers_group_init (struct posix_cputimers *pct, +u64 cpu_limit) { }#endif #define REQUEUE_PENDING 1
include/linux/sched.h +0 -8
@@ -246,11 +246,6 @@ struct prev_cputime {#endif }; -/* Alternate field names when used on cache expirations: */ -#define virt_exp utime -#define prof_exp stime -#define sched_exp sum_exec_runtime -enum vtime_state {/* Task is sleeping or running in a CPU with VTIME inactive: */ VTIME_INACTIVE =0 ,
@@ -862,9 +857,6 @@ struct task_struct {unsigned long min_flt;unsigned long maj_flt; -#ifdef CONFIG_POSIX_TIMERS -struct task_cputime cputime_expires; -#endif /* Empty if CONFIG_POSIX_CPUTIMERS=n */ struct posix_cputimers posix_cputimers;
include/linux/sched/signal.h +0 -3
@@ -149,9 +149,6 @@ struct signal_struct {*/ struct thread_group_cputimer cputimer; -/* Earliest-expiration cache. */ -struct task_cputime cputime_expires; -#endif /* Empty if CONFIG_POSIX_TIMERS=n */ struct posix_cputimers posix_cputimers;
kernel/fork.c +3 -22
@@ -1527,12 +1527,9 @@ static void posix_cpu_timers_init_group(unsigned long cpu_limit; cpu_limit =READ_ONCE (sig->rlim[RLIMIT_CPU ].rlim_cur); -if (cpu_limit !=RLIM_INFINITY ) { - sig->cputime_expires.prof_exp = cpu_limit *NSEC_PER_SEC ; +posix_cputimers_group_init (pct, cpu_limit); +if (cpu_limit !=RLIM_INFINITY ) sig->cputimer.running = true; - } - - posix_cputimers_init(pct); }#else static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { }
@@ -1638,22 +1635,6 @@ static void rt_mutex_init_task(struct ta#endif } -#ifdef CONFIG_POSIX_TIMERS -/* -* Initialize POSIX timer handling for a single task. -*/ -static void posix_cpu_timers_init (struct task_struct *tsk) -{ - tsk->cputime_expires.prof_exp =0 ; - tsk->cputime_expires.virt_exp =0 ; - tsk->cputime_expires.sched_exp =0 ; - -posix_cputimers_init (&tsk->posix_cputimers); -} -#else -static inline void posix_cpu_timers_init (struct task_struct *tsk) { } -#endif -static inline void init_task_pid_links (struct task_struct *task) {enum pid_type type;
@@ -1932,7 +1913,7 @@ static __latent_entropy struct task_strutask_io_accounting_init (&p->ioac);acct_clear_integrals (p); -posix_cpu_timers_init (p); +posix_cputimers_init (&p->posix_cputimers); p->io_context =NULL ;audit_set_context (p,NULL );
kernel/sched/rt.c +4 -2
@@ -2305,8 +2305,10 @@ static void watchdog(struct rq *rq, stru } next =DIV_ROUND_UP (min (soft, hard),USEC_PER_SEC /HZ ); -if (p->rt.timeout > next) - p->cputime_expires.sched_exp = p->se.sum_exec_runtime; +if (p->rt.timeout > next) { +posix_cputimers_rt_watchdog (&p->posix_cputimers, + p->se.sum_exec_runtime); + } } }#else
kernel/time/posix-cpu-timers.c +27 -18
103 lines not on this page · raw message
Re: [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers
Quoted 4 lines · Thomas Gleixner
The expiry cache belongs into the
posix_cputimerscontainer where the other cpu timers information is.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Move expiry cache into struct posix_cputimers
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 3a245c0f110e2bfcf7f2cd2248a29005c78999e3 Gitweb: https://git.kernel.org/tip/3a245c0f110e2bfcf7f2cd2248a29005c78999e3 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:06 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:35 +02:00
posix-cpu-timers: Move expiry cache into struct posix_cputimers
The expiry cache belongs into the posix_cputimers container where the other cpu timers information is.
--- include/linux/posix-timers.h | 22 ++++++++++++++++- include/linux/sched.h | 8 +------ include/linux/sched/signal.h | 3 +-- kernel/fork.c | 25 ++---------------- kernel/sched/rt.c | 6 ++-- kernel/time/posix-cpu-timers.c | 45 +++++++++++++++++++-------------- 6 files changed, 56 insertions(+), 53 deletions(-)
include/linux/posix-timers.h +22 -0
@@ -62,24 +62,43 @@ static inline int clockid_to_fd(const clockid_t clk)return ~(clk >>3 ); } +/* +* Alternate field names for struct task_cputime when used on cache +* expirations. Will go away soon. +*/ +#define virt_exp utime +#define prof_exp stime +#define sched_exp sum_exec_runtime +#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data +* @cputime_expires: Earliest-expiration cache * @cpu_timers: List heads to queue posix CPU timers * * Used in task_struct and signal_struct */ struct posix_cputimers { +struct task_cputime cputime_expires;struct list_head cpu_timers[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { +memset (&pct->cputime_expires,0 ,sizeof (pct->cputime_expires));INIT_LIST_HEAD (&pct->cpu_timers[0 ]);INIT_LIST_HEAD (&pct->cpu_timers[1 ]);INIT_LIST_HEAD (&pct->cpu_timers[2 ]); } +void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit); + +static inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct, +u64 runtime) +{ + pct->cputime_expires.sched_exp = runtime; +} +/* Init task static initializer */ #define INIT_CPU_TIMERLISTS (c) { \ LIST_HEAD_INIT(c.cpu_timers[0]), \
@@ -94,6 +113,9 @@ static inline void posix_cputimers_init(struct posix_cputimers *pct)#else struct posix_cputimers { };#define INIT_CPU_TIMERS (s) +static inline void posix_cputimers_init (struct posix_cputimers *pct) { } +static inline void posix_cputimers_group_init (struct posix_cputimers *pct, +u64 cpu_limit) { }#endif #define REQUEUE_PENDING 1
include/linux/sched.h +0 -8
@@ -246,11 +246,6 @@ struct prev_cputime {#endif }; -/* Alternate field names when used on cache expirations: */ -#define virt_exp utime -#define prof_exp stime -#define sched_exp sum_exec_runtime -enum vtime_state {/* Task is sleeping or running in a CPU with VTIME inactive: */ VTIME_INACTIVE =0 ,
@@ -862,9 +857,6 @@ struct task_struct {unsigned long min_flt;unsigned long maj_flt; -#ifdef CONFIG_POSIX_TIMERS -struct task_cputime cputime_expires; -#endif /* Empty if CONFIG_POSIX_CPUTIMERS=n */ struct posix_cputimers posix_cputimers;
include/linux/sched/signal.h +0 -3
@@ -149,9 +149,6 @@ struct signal_struct {*/ struct thread_group_cputimer cputimer; -/* Earliest-expiration cache. */ -struct task_cputime cputime_expires; -#endif /* Empty if CONFIG_POSIX_TIMERS=n */ struct posix_cputimers posix_cputimers;
kernel/fork.c +3 -22
@@ -1527,12 +1527,9 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)unsigned long cpu_limit; cpu_limit =READ_ONCE (sig->rlim[RLIMIT_CPU ].rlim_cur); -if (cpu_limit !=RLIM_INFINITY ) { - sig->cputime_expires.prof_exp = cpu_limit *NSEC_PER_SEC ; +posix_cputimers_group_init (pct, cpu_limit); +if (cpu_limit !=RLIM_INFINITY ) sig->cputimer.running = true; - } - - posix_cputimers_init(pct); }#else static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { }
@@ -1638,22 +1635,6 @@ static void rt_mutex_init_task(struct task_struct *p)#endif } -#ifdef CONFIG_POSIX_TIMERS -/* -* Initialize POSIX timer handling for a single task. -*/ -static void posix_cpu_timers_init (struct task_struct *tsk) -{ - tsk->cputime_expires.prof_exp =0 ; - tsk->cputime_expires.virt_exp =0 ; - tsk->cputime_expires.sched_exp =0 ; - -posix_cputimers_init (&tsk->posix_cputimers); -} -#else -static inline void posix_cpu_timers_init (struct task_struct *tsk) { } -#endif -static inline void init_task_pid_links (struct task_struct *task) {enum pid_type type;
@@ -1932,7 +1913,7 @@ static __latent_entropy struct task_struct *copy_process(task_io_accounting_init (&p->ioac);acct_clear_integrals (p); -posix_cpu_timers_init (p); +posix_cputimers_init (&p->posix_cputimers); p->io_context =NULL ;audit_set_context (p,NULL );
kernel/sched/rt.c +4 -2
@@ -2305,8 +2305,10 @@ static void watchdog(struct rq *rq, struct task_struct *p) } next =DIV_ROUND_UP (min (soft, hard),USEC_PER_SEC /HZ ); -if (p->rt.timeout > next) - p->cputime_expires.sched_exp = p->se.sum_exec_runtime; +if (p->rt.timeout > next) { +posix_cputimers_rt_watchdog (&p->posix_cputimers, + p->se.sum_exec_runtime); + } } }#else
kernel/time/posix-cpu-timers.c +27 -18
103 lines not on this page · raw message
PATCH v2 20/38 posix-cpu-timers: Provide array based access to expiry cache
In reply to Thomas GleixnerUsing struct task_cputime for the expiry cache is a pretty odd choice and comes with magic defines to rename the fields for usage in the expiry cache.
struct task_cputime is basically a u64 array with 3 members, but it has distinct members.
The expiry cache content is different than the content of task_cputime because
expiry[PROF] = task_cputime.stime + task_cputime.utime expiry[VIRT] = task_cputime.utime expiry[SCHED] = task_cputime.sum_exec_runtime
So there is no direct mapping between task_cputime and the expiry cache and the #define based remapping is just a horrible hack.
Having the expiry cache array based allows further simplification of the expiry code.
To avoid an all in one cleanup which is hard to review add a temporary anonymous union into struct task_cputime which allows array based access to it. That requires to reorder the members. Add a build time sanity check to validate that the members are at the same place.
The union and the build time checks will be removed after conversion.
--- include/linux/posix-timers.h | 24 ++++++++++++++++++------ include/linux/sched/types.h | 4 ++-- kernel/time/posix-cpu-timers.c | 12 +++++++++++- 3 files changed, 31 insertions(+), 9 deletions(-)
include/linux/posix-timers.h +18 -6
@@ -65,27 +65,39 @@ static inline int clockid_to_fd(const cl/* * Alternate field names for struct task_cputime when used on cache * expirations. Will go away soon. +* +* stime corresponds to CLOCKCPU_PROF +* utime corresponds to CLOCKCPU_VIRT +* sum_exex_runtime corresponds to CLOCKCPU_SCHED +* +* The ordering is currently enforced so struct task_cputime and the +* expiries array in struct posix_cputimers are equivalent. */ -#define virt_exp utime#define prof_exp stime +#define virt_exp utime#define sched_exp sum_exec_runtime#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data -* @cputime_expires: Earliest-expiration cache +* @cputime_expires: Earliest-expiration cache task_cputime based +* @expiries: Earliest-expiration cache array based * @cpu_timers: List heads to queue posix CPU timers * * Used in task_struct and signal_struct */ struct posix_cputimers { -struct task_cputime cputime_expires; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +/* Temporary union until all users are cleaned up */ +union { +struct task_cputime cputime_expires; +u64 expiries[CPUCLOCK_MAX ]; + }; +struct list_head cpu_timers[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (&pct->cputime_expires,0 ,sizeof (pct->cputime_expires)); +memset (&pct->expiries,0 ,sizeof (pct->expiries));INIT_LIST_HEAD (&pct->cpu_timers[0 ]);INIT_LIST_HEAD (&pct->cpu_timers[1 ]);INIT_LIST_HEAD (&pct->cpu_timers[2 ]);
@@ -96,7 +108,7 @@ void posix_cputimers_group_init(struct pstatic inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct,u64 runtime) { - pct->cputime_expires.sched_exp = runtime; + pct->expiries[CPUCLOCK_SCHED ] = runtime; }/* Init task static initializer */
include/linux/sched/types.h +2 -2
@@ -6,8 +6,8 @@/** * struct task_cputime - collected CPU time counts -* @utime: time spent in user mode, in nanoseconds * @stime: time spent in kernel mode, in nanoseconds +* @utime: time spent in user mode, in nanoseconds * @sum_exec_runtime: total time spent on the CPU, in nanoseconds * * This structure groups together three kinds of CPU time that are tracked for
@@ -15,8 +15,8 @@* these counts together and treat all three of them in parallel. */ struct task_cputime { -u64 utime;u64 stime; +u64 utime;unsigned long long sum_exec_runtime; };
kernel/time/posix-cpu-timers.c +11 -1
@@ -18,13 +18,23 @@#include "posix-timers.h" +static inline void temporary_check (void ) +{ +BUILD_BUG_ON (offsetof(struct task_cputime , stime) != +CPUCLOCK_PROF *sizeof (u64)); +BUILD_BUG_ON (offsetof(struct task_cputime , utime) != +CPUCLOCK_VIRT *sizeof (u64)); +BUILD_BUG_ON (offsetof(struct task_cputime , sum_exec_runtime) != +CPUCLOCK_SCHED *sizeof (u64)); +} +static void posix_cpu_timer_rearm (struct k_itimer *timer);void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit) {posix_cputimers_init (pct);if (cpu_limit !=RLIM_INFINITY ) - pct->cputime_expires.prof_exp = cpu_limit *NSEC_PER_SEC ; + pct->expiries[CPUCLOCK_PROF ] = cpu_limit *NSEC_PER_SEC ; }/*
Re: [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache
Quoted 20 lines · Thomas Gleixner
Using struct
task_cputimefor the expiry cache is a pretty odd choice and comes with magic defines to rename the fields for usage in the expiry cache.struct
task_cputimeis basically a u64 array with 3 members, but it has distinct members.The expiry cache content is different than the content of
task_cputimebecauseexpiry[PROF] = task_cputime.stime + task_cputime.utime expiry[VIRT] = task_cputime.utime expiry[SCHED] = task_cputime.sum_exec_runtime
So there is no direct mapping between
task_cputimeand the expiry cache and the #define based remapping is just a horrible hack.Having the expiry cache array based allows further simplification of the expiry code.
Quoted 8 lines
To avoid an all in one cleanup which is hard to review add a temporary anonymous union into struct
task_cputimewhich allows array based access to it. That requires to reorder the members. Add a build time sanity check to validate that the members are at the same place.The union and the build time checks will be removed after conversion.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Provide array based access to expiry cache
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 11b8462f7e1d25f639c88949a2746a9c2667a766 Gitweb: https://git.kernel.org/tip/11b8462f7e1d25f639c88949a2746a9c2667a766 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:07 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:35 +02:00
posix-cpu-timers: Provide array based access to expiry cache
Using struct task_cputime for the expiry cache is a pretty odd choice and comes with magic defines to rename the fields for usage in the expiry cache.
struct task_cputime is basically a u64 array with 3 members, but it has distinct members.
The expiry cache content is different than the content of task_cputime because
expiry[PROF] = task_cputime.stime + task_cputime.utime expiry[VIRT] = task_cputime.utime expiry[SCHED] = task_cputime.sum_exec_runtime
So there is no direct mapping between task_cputime and the expiry cache and the #define based remapping is just a horrible hack.
Having the expiry cache array based allows further simplification of the expiry code.
To avoid an all in one cleanup which is hard to review add a temporary anonymous union into struct task_cputime which allows array based access to it. That requires to reorder the members. Add a build time sanity check to validate that the members are at the same place.
The union and the build time checks will be removed after conversion.
--- include/linux/posix-timers.h | 24 ++++++++++++++++++------ include/linux/sched/types.h | 4 ++-- kernel/time/posix-cpu-timers.c | 12 +++++++++++- 3 files changed, 31 insertions(+), 9 deletions(-)
include/linux/posix-timers.h +18 -6
@@ -65,27 +65,39 @@ static inline int clockid_to_fd(const clockid_t clk)/* * Alternate field names for struct task_cputime when used on cache * expirations. Will go away soon. +* +* stime corresponds to CLOCKCPU_PROF +* utime corresponds to CLOCKCPU_VIRT +* sum_exex_runtime corresponds to CLOCKCPU_SCHED +* +* The ordering is currently enforced so struct task_cputime and the +* expiries array in struct posix_cputimers are equivalent. */ -#define virt_exp utime#define prof_exp stime +#define virt_exp utime#define sched_exp sum_exec_runtime#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data -* @cputime_expires: Earliest-expiration cache +* @cputime_expires: Earliest-expiration cache task_cputime based +* @expiries: Earliest-expiration cache array based * @cpu_timers: List heads to queue posix CPU timers * * Used in task_struct and signal_struct */ struct posix_cputimers { -struct task_cputime cputime_expires; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +/* Temporary union until all users are cleaned up */ +union { +struct task_cputime cputime_expires; +u64 expiries[CPUCLOCK_MAX ]; + }; +struct list_head cpu_timers[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (&pct->cputime_expires,0 ,sizeof (pct->cputime_expires)); +memset (&pct->expiries,0 ,sizeof (pct->expiries));INIT_LIST_HEAD (&pct->cpu_timers[0 ]);INIT_LIST_HEAD (&pct->cpu_timers[1 ]);INIT_LIST_HEAD (&pct->cpu_timers[2 ]);
@@ -96,7 +108,7 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);static inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct,u64 runtime) { - pct->cputime_expires.sched_exp = runtime; + pct->expiries[CPUCLOCK_SCHED ] = runtime; }/* Init task static initializer */
include/linux/sched/types.h +2 -2
@@ -6,8 +6,8 @@/** * struct task_cputime - collected CPU time counts -* @utime: time spent in user mode, in nanoseconds * @stime: time spent in kernel mode, in nanoseconds +* @utime: time spent in user mode, in nanoseconds * @sum_exec_runtime: total time spent on the CPU, in nanoseconds * * This structure groups together three kinds of CPU time that are tracked for
@@ -15,8 +15,8 @@* these counts together and treat all three of them in parallel. */ struct task_cputime { -u64 utime;u64 stime; +u64 utime;unsigned long long sum_exec_runtime; };
kernel/time/posix-cpu-timers.c +11 -1
@@ -18,13 +18,23 @@#include "posix-timers.h" +static inline void temporary_check (void ) +{ +BUILD_BUG_ON (offsetof(struct task_cputime , stime) != +CPUCLOCK_PROF *sizeof (u64)); +BUILD_BUG_ON (offsetof(struct task_cputime , utime) != +CPUCLOCK_VIRT *sizeof (u64)); +BUILD_BUG_ON (offsetof(struct task_cputime , sum_exec_runtime) != +CPUCLOCK_SCHED *sizeof (u64)); +} +static void posix_cpu_timer_rearm (struct k_itimer *timer);void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit) {posix_cputimers_init (pct);if (cpu_limit !=RLIM_INFINITY ) - pct->cputime_expires.prof_exp = cpu_limit *NSEC_PER_SEC ; + pct->expiries[CPUCLOCK_PROF ] = cpu_limit *NSEC_PER_SEC ; }/*
PATCH v2 21/38 posix-cpu-timers: Simplify timer queueing
In reply to Thomas GleixnerNow that the expiry cache can be accessed as an array, the per clock checking can be reduced to just comparing the corresponding array elements.
--- kernel/time/posix-cpu-timers.c | 57 +++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 35 deletions(-)
kernel/time/posix-cpu-timers.c +22 -35
@@ -456,20 +456,20 @@ static inline int expires_gt(u64 expires*/ static void arm_timer (struct k_itimer *timer) { +struct cpu_timer_list *const nt = &timer->it.cpu; +int clkidx =CPUCLOCK_WHICH (timer->it_clock); +u64 *cpuexp, newexp = timer->it.cpu.expires;struct task_struct *p = timer->it.cpu.task;struct list_head *head, *listpos; -struct task_cputime *cputime_expires; -struct cpu_timer_list *const nt = &timer->it.cpu;struct cpu_timer_list *next;if (CPUCLOCK_PERTHREAD (timer->it_clock)) { - head = p->posix_cputimers.cpu_timers; - cputime_expires = &p->posix_cputimers.cputime_expires; + head = p->posix_cputimers.cpu_timers + clkidx; + cpuexp = p->posix_cputimers.expiries + clkidx; }else { - head = p->signal->posix_cputimers.cpu_timers; - cputime_expires = &p->signal->posix_cputimers.cputime_expires; + head = p->signal->posix_cputimers.cpu_timers + clkidx; + cpuexp = p->signal->posix_cputimers.expiries + clkidx; } - head +=CPUCLOCK_WHICH (timer->it_clock); listpos = head;list_for_each_entry (next, head, entry) {
@@ -479,35 +479,22 @@ static void arm_timer(struct k_itimer *t }list_add (&nt->entry, listpos); -if (listpos == head) { -u64 exp = nt->expires; +if (listpos != head) +return ; -/* -* We are the new earliest-expiring POSIX 1.b timer, hence -* need to update expiration cache. Take into account that -* for process timers we share expiration cache with itimers -* and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. -*/ - -switch (CPUCLOCK_WHICH (timer->it_clock)) { -case CPUCLOCK_PROF : -if (expires_gt (cputime_expires->prof_exp, exp)) - cputime_expires->prof_exp = exp; -break ; -case CPUCLOCK_VIRT : -if (expires_gt (cputime_expires->virt_exp, exp)) - cputime_expires->virt_exp = exp; -break ; -case CPUCLOCK_SCHED : -if (expires_gt (cputime_expires->sched_exp, exp)) - cputime_expires->sched_exp = exp; -break ; - } -if (CPUCLOCK_PERTHREAD (timer->it_clock)) -tick_dep_set_task (p,TICK_DEP_BIT_POSIX_TIMER ); -else -tick_dep_set_signal (p->signal,TICK_DEP_BIT_POSIX_TIMER ); - } +/* +* We are the new earliest-expiring POSIX 1.b timer, hence +* need to update expiration cache. Take into account that +* for process timers we share expiration cache with itimers +* and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. +*/ +if (expires_gt (*cpuexp, newexp)) + *cpuexp = newexp; + +if (CPUCLOCK_PERTHREAD (timer->it_clock)) +tick_dep_set_task (p,TICK_DEP_BIT_POSIX_TIMER ); +else +tick_dep_set_signal (p->signal,TICK_DEP_BIT_POSIX_TIMER ); }/*
Re: [patch V2 21/38] posix-cpu-timers: Simplify timer queueing
Quoted 4 lines · Thomas Gleixner
Now that the expiry cache can be accessed as an array, the per clock checking can be reduced to just comparing the corresponding array elements.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Simplify timer queueing
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 3b495b22d04df3220ccae829bf7c5cadb3059ccf Gitweb: https://git.kernel.org/tip/3b495b22d04df3220ccae829bf7c5cadb3059ccf Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:08 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:36 +02:00
posix-cpu-timers: Simplify timer queueing
Now that the expiry cache can be accessed as an array, the per clock checking can be reduced to just comparing the corresponding array elements.
--- kernel/time/posix-cpu-timers.c | 55 ++++++++++++--------------------- 1 file changed, 21 insertions(+), 34 deletions(-)
kernel/time/posix-cpu-timers.c +21 -34
@@ -456,20 +456,20 @@ static inline int expires_gt(u64 expires, u64 new_exp)*/ static void arm_timer (struct k_itimer *timer) { +struct cpu_timer_list *const nt = &timer->it.cpu; +int clkidx =CPUCLOCK_WHICH (timer->it_clock); +u64 *cpuexp, newexp = timer->it.cpu.expires;struct task_struct *p = timer->it.cpu.task;struct list_head *head, *listpos; -struct task_cputime *cputime_expires; -struct cpu_timer_list *const nt = &timer->it.cpu;struct cpu_timer_list *next;if (CPUCLOCK_PERTHREAD (timer->it_clock)) { - head = p->posix_cputimers.cpu_timers; - cputime_expires = &p->posix_cputimers.cputime_expires; + head = p->posix_cputimers.cpu_timers + clkidx; + cpuexp = p->posix_cputimers.expiries + clkidx; }else { - head = p->signal->posix_cputimers.cpu_timers; - cputime_expires = &p->signal->posix_cputimers.cputime_expires; + head = p->signal->posix_cputimers.cpu_timers + clkidx; + cpuexp = p->signal->posix_cputimers.expiries + clkidx; } - head +=CPUCLOCK_WHICH (timer->it_clock); listpos = head;list_for_each_entry (next, head, entry) {
@@ -479,35 +479,22 @@ static void arm_timer(struct k_itimer *timer) }list_add (&nt->entry, listpos); -if (listpos == head) { -u64 exp = nt->expires; +if (listpos != head) +return ; -/* -* We are the new earliest-expiring POSIX 1.b timer, hence -* need to update expiration cache. Take into account that -* for process timers we share expiration cache with itimers -* and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. -*/ +/* +* We are the new earliest-expiring POSIX 1.b timer, hence +* need to update expiration cache. Take into account that +* for process timers we share expiration cache with itimers +* and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. +*/ +if (expires_gt (*cpuexp, newexp)) + *cpuexp = newexp; -switch (CPUCLOCK_WHICH (timer->it_clock)) { -case CPUCLOCK_PROF : -if (expires_gt (cputime_expires->prof_exp, exp)) - cputime_expires->prof_exp = exp; -break ; -case CPUCLOCK_VIRT : -if (expires_gt (cputime_expires->virt_exp, exp)) - cputime_expires->virt_exp = exp; -break ; -case CPUCLOCK_SCHED : -if (expires_gt (cputime_expires->sched_exp, exp)) - cputime_expires->sched_exp = exp; -break ; - } -if (CPUCLOCK_PERTHREAD (timer->it_clock)) -tick_dep_set_task (p,TICK_DEP_BIT_POSIX_TIMER ); -else -tick_dep_set_signal (p->signal,TICK_DEP_BIT_POSIX_TIMER ); - } +if (CPUCLOCK_PERTHREAD (timer->it_clock)) +tick_dep_set_task (p,TICK_DEP_BIT_POSIX_TIMER ); +else +tick_dep_set_signal (p->signal,TICK_DEP_BIT_POSIX_TIMER ); }/*
PATCH v2 22/38 posix-cpu-timers: Simplify set_process_cpu_timer()
In reply to Thomas GleixnerThe expiry cache can now be accessed as an array. Replace the per clock checks with a simple comparison of the clock indexed array member.
--- kernel/time/posix-cpu-timers.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-)
kernel/time/posix-cpu-timers.c +8 -16
@@ -1174,15 +1174,15 @@ void run_posix_cpu_timers(void)* Set one of the process-wide special case CPU timers or RLIMIT_CPU. * The tsk->sighand->siglock must be held by the caller. */ -void set_process_cpu_timer (struct task_struct *tsk,unsigned int clock_idx, +void set_process_cpu_timer (struct task_struct *tsk,unsigned int clkid,u64 *newval,u64 *oldval) { -u64 now; +u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid; -if (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED )) +if (WARN_ON_ONCE (clkid >=CPUCLOCK_SCHED ))return ; - now =cpu_clock_sample_group (clock_idx, tsk, true); + now =cpu_clock_sample_group (clkid, tsk, true);if (oldval) {/*
@@ -1205,19 +1205,11 @@ void set_process_cpu_timer(struct task_s }/* -* Update expiration cache if we are the earliest timer, or eventually -* RLIMIT_CPU limit is earlier than prof_exp cpu timer expire. +* Update expiration cache if this is the earliest timer. CPUCLOCK_PROF +* expiry cache is also used by RLIMIT_CPU!. */ -switch (clock_idx) { -case CPUCLOCK_PROF : -if (expires_gt (tsk->signal->posix_cputimers.cputime_expires.prof_exp, *newval)) - tsk->signal->posix_cputimers.cputime_expires.prof_exp = *newval; -break ; -case CPUCLOCK_VIRT : -if (expires_gt (tsk->signal->posix_cputimers.cputime_expires.virt_exp, *newval)) - tsk->signal->posix_cputimers.cputime_expires.virt_exp = *newval; -break ; - } +if (expires_gt (*expiry, *newval)) + *expiry = *newval;tick_dep_set_signal (tsk->signal,TICK_DEP_BIT_POSIX_TIMER ); }
Re: [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer()
Quoted 4 lines · Thomas Gleixner
The expiry cache can now be accessed as an array. Replace the per clock checks with a simple comparison of the clock indexed array member.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Simplify set_process_cpu_timer()
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 1b0dd96d0f07c482bf1d04987cc1b35e376a7518 Gitweb: https://git.kernel.org/tip/1b0dd96d0f07c482bf1d04987cc1b35e376a7518 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:09 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:36 +02:00
posix-cpu-timers: Simplify set_process_cpu_timer()
The expiry cache can now be accessed as an array. Replace the per clock checks with a simple comparison of the clock indexed array member.
--- kernel/time/posix-cpu-timers.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-)
kernel/time/posix-cpu-timers.c +8 -16
@@ -1174,15 +1174,15 @@ void run_posix_cpu_timers(void)* Set one of the process-wide special case CPU timers or RLIMIT_CPU. * The tsk->sighand->siglock must be held by the caller. */ -void set_process_cpu_timer (struct task_struct *tsk,unsigned int clock_idx, +void set_process_cpu_timer (struct task_struct *tsk,unsigned int clkid,u64 *newval,u64 *oldval) { -u64 now; +u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid; -if (WARN_ON_ONCE (clock_idx >=CPUCLOCK_SCHED )) +if (WARN_ON_ONCE (clkid >=CPUCLOCK_SCHED ))return ; - now =cpu_clock_sample_group (clock_idx, tsk, true); + now =cpu_clock_sample_group (clkid, tsk, true);if (oldval) {/*
@@ -1205,19 +1205,11 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx, }/* -* Update expiration cache if we are the earliest timer, or eventually -* RLIMIT_CPU limit is earlier than prof_exp cpu timer expire. +* Update expiration cache if this is the earliest timer. CPUCLOCK_PROF +* expiry cache is also used by RLIMIT_CPU!. */ -switch (clock_idx) { -case CPUCLOCK_PROF : -if (expires_gt (tsk->signal->posix_cputimers.cputime_expires.prof_exp, *newval)) - tsk->signal->posix_cputimers.cputime_expires.prof_exp = *newval; -break ; -case CPUCLOCK_VIRT : -if (expires_gt (tsk->signal->posix_cputimers.cputime_expires.virt_exp, *newval)) - tsk->signal->posix_cputimers.cputime_expires.virt_exp = *newval; -break ; - } +if (expires_gt (*expiry, *newval)) + *expiry = *newval;tick_dep_set_signal (tsk->signal,TICK_DEP_BIT_POSIX_TIMER ); }
PATCH v2 23/38 posix-cpu-timers: Switch check_*_timers() to array cache
In reply to Thomas GleixnerUse the array based expiry cache in check_thread_timers() and convert the store in check_process_timers() for consistency.
--- kernel/time/posix-cpu-timers.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-)
kernel/time/posix-cpu-timers.c +11 -15
@@ -778,8 +778,7 @@ static void check_thread_timers(struct t struct list_head *firing) {struct list_head *timers = tsk->posix_cputimers.cpu_timers; -struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires; -u64 expires, stime, utime; +u64 stime, utime, *expires = tsk->posix_cputimers.expiries;unsigned long soft;if (dl_task (tsk))
@@ -789,19 +788,14 @@ static void check_thread_timers(struct t* If cputime_expires is zero, then there are no active * per thread CPU timers. */ -if (task_cputime_zero (tsk_expires)) +if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires))return ;task_cputime (tsk, &utime, &stime); - expires =check_timers_list (timers, firing, utime + stime); - tsk_expires->prof_exp = expires; - - expires =check_timers_list (++timers, firing, utime); - tsk_expires->virt_exp = expires; - - tsk_expires->sched_exp =check_timers_list (++timers, firing, - tsk->se.sum_exec_runtime); + *expires++ =check_timers_list (timers, firing, utime + stime); + *expires++ =check_timers_list (++timers, firing, utime); + *expires =check_timers_list (++timers, firing, tsk->se.sum_exec_runtime);/* * Check for the special case thread timers.
@@ -839,7 +833,8 @@ static void check_thread_timers(struct t__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); } } -if (task_cputime_zero (tsk_expires)) + +if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -958,9 +953,10 @@ static void check_process_timers(struct prof_expires = x; } - sig->posix_cputimers.cputime_expires.prof_exp = prof_expires; - sig->posix_cputimers.cputime_expires.virt_exp = virt_expires; - sig->posix_cputimers.cputime_expires.sched_exp = sched_expires; + sig->posix_cputimers.expiries[CPUCLOCK_PROF ] = prof_expires; + sig->posix_cputimers.expiries[CPUCLOCK_VIRT ] = virt_expires; + sig->posix_cputimers.expiries[CPUCLOCK_SCHED ] = sched_expires; +if (task_cputime_zero (&sig->posix_cputimers.cputime_expires))stop_process_timers (sig);
Re: [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache
Quoted 31 lines · Thomas Gleixner
Use the array based expiry cache in
check_thread_timers()and convert the store incheck_process_timers()for consistency.Signed-off-by Thomas Gleixner <[email protected]>--- kernel/time/posix-cpu-timers.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-)kernel/time/posix-cpu-timers.c +2
-4@@ -778,8 +778,7 @@ static void check_thread_timers(struct t struct list_head *firing) {struct list_head *timers = tsk->posix_cputimers.cpu_timers; -struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires; -u64 expires, stime, utime; +u64 stime, utime, *expires = tsk->posix_cputimers.expiries;unsigned long soft;if (dl_task (tsk))@@ -789,19 +788,14 @@ static void check_thread_timers(struct t* If cputime_expires is zero, then there are no active * per thread CPU timers. */ -if (task_cputime_zero (tsk_expires)) +if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires))return ;task_cputime (tsk, &utime, &stime); - expires =check_timers_list (timers, firing, utime + stime);
kernel/time/posix-cpu-timers.c static void check_thread_timers(struct t · line 798
Quoted 10 lines
kernel/time/posix-cpu-timers.c +3
-7- tsk_expires->prof_exp = expires; - - expires =check_timers_list (++timers, firing, utime); - tsk_expires->virt_exp = expires; - - tsk_expires->sched_exp =check_timers_list (++timers, firing, - tsk->se.sum_exec_runtime); + *expires++ =check_timers_list (timers, firing, utime + stime); + *expires++ =check_timers_list (++timers, firing, utime); + *expires =check_timers_list (++timers, firing, tsk->se.sum_exec_runtime);
What a nice reading for anyone learning the difference between pointers's pre and post incrementation :-)
[tip: timers/core] posix-cpu-timers: Switch check_*_timers() to array cache
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: c02b078e63a6f42029cb655d0aa3c991271637ac Gitweb: https://git.kernel.org/tip/c02b078e63a6f42029cb655d0aa3c991271637ac Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:10 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:36 +02:00
posix-cpu-timers: Switch check_*_timers() to array cache
Use the array based expiry cache in check_thread_timers() and convert the store in check_process_timers() for consistency.
--- kernel/time/posix-cpu-timers.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-)
kernel/time/posix-cpu-timers.c +11 -15
@@ -778,8 +778,7 @@ static void check_thread_timers(struct task_struct *tsk, struct list_head *firing) {struct list_head *timers = tsk->posix_cputimers.cpu_timers; -struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires; -u64 expires, stime, utime; +u64 stime, utime, *expires = tsk->posix_cputimers.expiries;unsigned long soft;if (dl_task (tsk))
@@ -789,19 +788,14 @@ static void check_thread_timers(struct task_struct *tsk,* If cputime_expires is zero, then there are no active * per thread CPU timers. */ -if (task_cputime_zero (tsk_expires)) +if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires))return ;task_cputime (tsk, &utime, &stime); - expires =check_timers_list (timers, firing, utime + stime); - tsk_expires->prof_exp = expires; - - expires =check_timers_list (++timers, firing, utime); - tsk_expires->virt_exp = expires; - - tsk_expires->sched_exp =check_timers_list (++timers, firing, - tsk->se.sum_exec_runtime); + *expires++ =check_timers_list (timers, firing, utime + stime); + *expires++ =check_timers_list (++timers, firing, utime); + *expires =check_timers_list (++timers, firing, tsk->se.sum_exec_runtime);/* * Check for the special case thread timers.
@@ -839,7 +833,8 @@ static void check_thread_timers(struct task_struct *tsk,__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); } } -if (task_cputime_zero (tsk_expires)) + +if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -958,9 +953,10 @@ static void check_process_timers(struct task_struct *tsk, prof_expires = x; } - sig->posix_cputimers.cputime_expires.prof_exp = prof_expires; - sig->posix_cputimers.cputime_expires.virt_exp = virt_expires; - sig->posix_cputimers.cputime_expires.sched_exp = sched_expires; + sig->posix_cputimers.expiries[CPUCLOCK_PROF ] = prof_expires; + sig->posix_cputimers.expiries[CPUCLOCK_VIRT ] = virt_expires; + sig->posix_cputimers.expiries[CPUCLOCK_SCHED ] = sched_expires; +if (task_cputime_zero (&sig->posix_cputimers.cputime_expires))stop_process_timers (sig);
PATCH v2 24/38 posix-cpu-timers: Remove the odd field rename defines
In reply to Thomas GleixnerThe last users of the odd define based renaming of struct task_cputime members are gone. Good riddance.
--- include/linux/posix-timers.h | 15 --------------- 1 file changed, 15 deletions(-)
include/linux/posix-timers.h +0 -15
@@ -62,21 +62,6 @@ static inline int clockid_to_fd(const clreturn ~(clk >>3 ); } -/* -* Alternate field names for struct task_cputime when used on cache -* expirations. Will go away soon. -* -* stime corresponds to CLOCKCPU_PROF -* utime corresponds to CLOCKCPU_VIRT -* sum_exex_runtime corresponds to CLOCKCPU_SCHED -* -* The ordering is currently enforced so struct task_cputime and the -* expiries array in struct posix_cputimers are equivalent. -*/ -#define prof_exp stime -#define virt_exp utime -#define sched_exp sum_exec_runtime -#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data
Re: [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines
Quoted 4 lines · Thomas Gleixner
The last users of the odd define based renaming of struct
task_cputimemembers are gone. Good riddance.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Remove the odd field rename defines
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: bbc9bae1e49bee9862c7f24101a728e73cd9f589 Gitweb: https://git.kernel.org/tip/bbc9bae1e49bee9862c7f24101a728e73cd9f589 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:11 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:37 +02:00
posix-cpu-timers: Remove the odd field rename defines
The last users of the odd define based renaming of struct task_cputime members are gone. Good riddance.
--- include/linux/posix-timers.h | 15 --------------- 1 file changed, 15 deletions(-)
include/linux/posix-timers.h +0 -15
@@ -62,21 +62,6 @@ static inline int clockid_to_fd(const clockid_t clk)return ~(clk >>3 ); } -/* -* Alternate field names for struct task_cputime when used on cache -* expirations. Will go away soon. -* -* stime corresponds to CLOCKCPU_PROF -* utime corresponds to CLOCKCPU_VIRT -* sum_exex_runtime corresponds to CLOCKCPU_SCHED -* -* The ordering is currently enforced so struct task_cputime and the -* expiries array in struct posix_cputimers are equivalent. -*/ -#define prof_exp stime -#define virt_exp utime -#define sched_exp sum_exec_runtime -#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data
PATCH v2 25/38 posix-cpu-timers: Provide array based sample functions
In reply to Thomas GleixnerInstead of using task_cputime and doing the addition of utime and stime at all call sites, it's way simpler to have a sample array which allows indexed based checks against the expiry cache array.
--- kernel/time/posix-cpu-timers.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
kernel/time/posix-cpu-timers.c +26 -0
@@ -202,6 +202,32 @@ static u64 cpu_clock_sample(const clockireturn 0 ; } +static inline void store_samples (u64 *samples,u64 stime,u64 utime,u64 rtime) +{ + samples[CPUCLOCK_PROF ] = stime + utime; + samples[CPUCLOCK_VIRT ] = utime; + samples[CPUCLOCK_SCHED ] = rtime; +} + +static void task_sample_cputime (struct task_struct *p,u64 *samples) +{ +u64 stime, utime; + +task_cputime (p, &utime, &stime); +store_samples (samples, stime, utime, p->se.sum_exec_runtime); +} + +static void proc_sample_cputime_atomic (struct task_cputime_atomic *at, +u64 *samples) +{ +u64 stime, utime, rtime; + + utime =atomic64_read (&at->utime); + stime =atomic64_read (&at->stime); + rtime =atomic64_read (&at->sum_exec_runtime); +store_samples (samples, stime, utime, rtime); +} +/* * Set cputime to sum_cputime if sum_cputime > cputime. Use cmpxchg * to avoid race conditions with concurrent updates to cputime.
Re: [patch V2 25/38] posix-cpu-timers: Provide array based sample functions
Quoted 5 lines · Thomas Gleixner
Instead of using
task_cputimeand doing the addition of utime and stime at all call sites, it's way simpler to have a sample array which allows indexed based checks against the expiry cache array.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Provide array based sample functions
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: b0d524f77956eec887b30732af1f5f98cbf62b9f Gitweb: https://git.kernel.org/tip/b0d524f77956eec887b30732af1f5f98cbf62b9f Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:12 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:38 +02:00
posix-cpu-timers: Provide array based sample functions
Instead of using task_cputime and doing the addition of utime and stime at all call sites, it's way simpler to have a sample array which allows indexed based checks against the expiry cache array.
--- kernel/time/posix-cpu-timers.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
kernel/time/posix-cpu-timers.c +26 -0
@@ -202,6 +202,32 @@ static u64 cpu_clock_sample(const clockid_t clkid, struct task_struct *p)return 0 ; } +static inline void store_samples (u64 *samples,u64 stime,u64 utime,u64 rtime) +{ + samples[CPUCLOCK_PROF ] = stime + utime; + samples[CPUCLOCK_VIRT ] = utime; + samples[CPUCLOCK_SCHED ] = rtime; +} + +static void task_sample_cputime (struct task_struct *p,u64 *samples) +{ +u64 stime, utime; + +task_cputime (p, &utime, &stime); +store_samples (samples, stime, utime, p->se.sum_exec_runtime); +} + +static void proc_sample_cputime_atomic (struct task_cputime_atomic *at, +u64 *samples) +{ +u64 stime, utime, rtime; + + utime =atomic64_read (&at->utime); + stime =atomic64_read (&at->stime); + rtime =atomic64_read (&at->sum_exec_runtime); +store_samples (samples, stime, utime, rtime); +} +/* * Set cputime to sum_cputime if sum_cputime > cputime. Use cmpxchg * to avoid race conditions with concurrent updates to cputime.
PATCH v2 26/38 posix-cpu-timers: Make expiry checks array based
In reply to Thomas GleixnerThe expiry cache is an array indexed by clock ids. The new sample functions allow to retrieve a corresponding array of samples.
Convert the fastpath expiry checks to make use of the new sample functions and do the comparisons on the sample and the expiry array.
Make the check for the expiry array being zero array based as well.
--- kernel/time/posix-cpu-timers.c | 85 +++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 49 deletions(-)
kernel/time/posix-cpu-timers.c +36 -49
@@ -39,7 +39,7 @@ void posix_cputimers_group_init(struct p/* * Called after updating RLIMIT_CPU to run cpu timer and update -* tsk->signal->posix_cputimers.cputime_expires expiration cache if +* tsk->signal->posix_cputimers.expiries expiration cache if * necessary. Needs siglock protection since other code may update * expiration cache as well. */
@@ -132,19 +132,9 @@ static void bump_cpu_timer(struct k_itim } } -/** -* task_cputime_zero - Check a task_cputime struct for all zero fields. -* -* @cputime: The struct to compare. -* -* Checks @cputime to see if all fields are zero. Returns true if all fields -* are zero, false if any field is nonzero. -*/ -static inline int task_cputime_zero (const struct task_cputime *cputime) +static inline bool expiry_cache_is_zero (const u64 *ec) { -if (!cputime->utime && !cputime->stime && !cputime->sum_exec_runtime) -return 1 ; -return 0 ; +return !(ec[CPUCLOCK_PROF ] | ec[CPUCLOCK_VIRT ] | ec[CPUCLOCK_SCHED ]); } static int
@@ -811,10 +801,10 @@ static void check_thread_timers(struct tcheck_dl_overrun (tsk);/* -* If cputime_expires is zero, then there are no active -* per thread CPU timers. +* If the expiry cache is zero, then there are no active per thread +* CPU timers. */ -if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires)) +if (expiry_cache_is_zero (tsk->posix_cputimers.expiries))return ;task_cputime (tsk, &utime, &stime);
@@ -860,7 +850,7 @@ static void check_thread_timers(struct t } } -if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires)) +if (expiry_cache_is_zero (tsk->posix_cputimers.expiries))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -983,7 +973,7 @@ static void check_process_timers(struct sig->posix_cputimers.expiries[CPUCLOCK_VIRT ] = virt_expires; sig->posix_cputimers.expiries[CPUCLOCK_SCHED ] = sched_expires; -if (task_cputime_zero (&sig->posix_cputimers.cputime_expires)) +if (expiry_cache_is_zero (sig->posix_cputimers.expiries))stop_process_timers (sig); sig->cputimer.checking_timer = false;
@@ -1048,26 +1038,23 @@ static void posix_cpu_timer_rearm(struct }/** -* task_cputime_expired - Compare two task_cputime entities. +* task_cputimers_expired - Compare two task_cputime entities. * -* @sample: The task_cputime structure to be checked for expiration. -* @expires: Expiration times, against which @sample will be checked. +* @samples: Array of current samples for the CPUCLOCK clocks +* @expiries: Array of expiry values for the CPUCLOCK clocks * -* Checks @sample against @expires to see if any field of @sample has expired. -* Returns true if any field of the former is greater than the corresponding -* field of the latter if the latter field is set. Otherwise returns false. +* Returns true if any mmember of @samples is greater than the corresponding +* member of @expiries if that member is non zero. False otherwise */ -static inline int task_cputime_expired (const struct task_cputime *sample, -const struct task_cputime *expires) +static inline bool task_cputimers_expired (const u64 *sample,const u64 *expiries) { -if (expires->utime && sample->utime >= expires->utime) -return 1 ; -if (expires->stime && sample->utime + sample->stime >= expires->stime) -return 1 ; -if (expires->sum_exec_runtime !=0 && - sample->sum_exec_runtime >= expires->sum_exec_runtime) -return 1 ; -return 0 ; +int i; + +for (i =0 ; i <CPUCLOCK_MAX ; i++) { +if (expiries[i] && sample[i] >= expiries[i]) +return true; + } +return false; }/**
@@ -1080,18 +1067,17 @@ static inline int task_cputime_expired(c* timers and compare them with the corresponding expiration times. Return * true if a timer has expired, else return false. */ -static inline int fastpath_timer_check (struct task_struct *tsk) +static inline bool fastpath_timer_check (struct task_struct *tsk) { +u64 *expiries = tsk->posix_cputimers.expiries;struct signal_struct *sig; -if (!task_cputime_zero (&tsk->posix_cputimers.cputime_expires)) { -struct task_cputime task_sample; +if (!expiry_cache_is_zero (expiries)) { +u64 samples[CPUCLOCK_MAX ]; -task_cputime (tsk, &task_sample.utime, &task_sample.stime); - task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime; -if (task_cputime_expired (&task_sample, - &tsk->posix_cputimers.cputime_expires)) -return 1 ; +task_sample_cputime (tsk, samples); +if (task_cputimers_expired (samples, expiries)) +return true; } sig = tsk->signal;
@@ -1111,19 +1097,20 @@ static inline int fastpath_timer_check(s*/ if (READ_ONCE (sig->cputimer.running) && !READ_ONCE (sig->cputimer.checking_timer)) { -struct task_cputime group_sample; +u64 samples[CPUCLOCK_MAX ]; -sample_cputime_atomic (&group_sample, &sig->cputimer.cputime_atomic); +proc_sample_cputime_atomic (&sig->cputimer.cputime_atomic, + samples); -if (task_cputime_expired (&group_sample, - &sig->posix_cputimers.cputime_expires)) -return 1 ; +if (task_cputimers_expired (samples, + sig->posix_cputimers.expiries)) +return true; }if (dl_task (tsk) && tsk->dl.dl_overrun) -return 1 ; +return true; -return 0 ; +return false; }/*
Re: [patch V2 26/38] posix-cpu-timers: Make expiry checks array based
Quoted 9 lines · Thomas Gleixner
The expiry cache is an array indexed by clock ids. The new sample functions allow to retrieve a corresponding array of samples.
Convert the fastpath expiry checks to make use of the new sample functions and do the comparisons on the sample and the expiry array.
Make the check for the expiry array being zero array based as well.
Signed-off-by Thomas Gleixner <[email protected]>
Just a few boring neats:
Quoted 3 lines
/**
- *task_cputime_expired- Compare twotask_cputimeentities.
+ *task_cputimers_expired- Compare twotask_cputimeentities.
s/task_cputime/clock arrays ?
Quoted 10 lines
*
- * @sample: Thetask_cputimestructure to be checked for expiration.
- * @expires: Expiration times, against which @sample will be checked.
+ * @samples: Array of current samples for the CPUCLOCK clocks
+ * @expiries: Array of expiry values for the CPUCLOCK clocks
*
- * Checks @sample against @expires to see if any field of @sample has expired.
- * Returns true if any field of the former is greater than the corresponding
- * field of the latter if the latter field is set. Otherwise returns false.
+ * Returns true if any mmember of @samples is greater than the corresponding
s/mmember/member
kernel/time/posix-cpu-timers.c static void posix_cpu_timer_rearm(struct · line 1049
Quoted 5 lines
+ * member of @expiries if that member is non zero. False otherwise */
kernel/time/posix-cpu-timers.c +1
-2-static inline int task_cputime_expired (const struct task_cputime *sample, -const struct task_cputime *expires) +static inline bool task_cputimers_expired (const u64 *sample,const u64 *expiries)
s/sample/samples to agree with above documented parameters.
Thanks.
[tip: timers/core] posix-cpu-timers: Make expiry checks array based
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 001f7971433a53bb76443cd8f5827ca27b0bc8ca Gitweb: https://git.kernel.org/tip/001f7971433a53bb76443cd8f5827ca27b0bc8ca Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:13 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:38 +02:00
posix-cpu-timers: Make expiry checks array based
The expiry cache is an array indexed by clock ids. The new sample functions allow to retrieve a corresponding array of samples.
Convert the fastpath expiry checks to make use of the new sample functions and do the comparisons on the sample and the expiry array.
Make the check for the expiry array being zero array based as well.
--- kernel/time/posix-cpu-timers.c | 85 +++++++++++++-------------------- 1 file changed, 36 insertions(+), 49 deletions(-)
kernel/time/posix-cpu-timers.c +36 -49
@@ -39,7 +39,7 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)/* * Called after updating RLIMIT_CPU to run cpu timer and update -* tsk->signal->posix_cputimers.cputime_expires expiration cache if +* tsk->signal->posix_cputimers.expiries expiration cache if * necessary. Needs siglock protection since other code may update * expiration cache as well. */
@@ -132,19 +132,9 @@ static void bump_cpu_timer(struct k_itimer *timer, u64 now) } } -/** -* task_cputime_zero - Check a task_cputime struct for all zero fields. -* -* @cputime: The struct to compare. -* -* Checks @cputime to see if all fields are zero. Returns true if all fields -* are zero, false if any field is nonzero. -*/ -static inline int task_cputime_zero (const struct task_cputime *cputime) +static inline bool expiry_cache_is_zero (const u64 *ec) { -if (!cputime->utime && !cputime->stime && !cputime->sum_exec_runtime) -return 1 ; -return 0 ; +return !(ec[CPUCLOCK_PROF ] | ec[CPUCLOCK_VIRT ] | ec[CPUCLOCK_SCHED ]); } static int
@@ -811,10 +801,10 @@ static void check_thread_timers(struct task_struct *tsk,check_dl_overrun (tsk);/* -* If cputime_expires is zero, then there are no active -* per thread CPU timers. +* If the expiry cache is zero, then there are no active per thread +* CPU timers. */ -if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires)) +if (expiry_cache_is_zero (tsk->posix_cputimers.expiries))return ;task_cputime (tsk, &utime, &stime);
@@ -860,7 +850,7 @@ static void check_thread_timers(struct task_struct *tsk, } } -if (task_cputime_zero (&tsk->posix_cputimers.cputime_expires)) +if (expiry_cache_is_zero (tsk->posix_cputimers.expiries))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -983,7 +973,7 @@ static void check_process_timers(struct task_struct *tsk, sig->posix_cputimers.expiries[CPUCLOCK_VIRT ] = virt_expires; sig->posix_cputimers.expiries[CPUCLOCK_SCHED ] = sched_expires; -if (task_cputime_zero (&sig->posix_cputimers.cputime_expires)) +if (expiry_cache_is_zero (sig->posix_cputimers.expiries))stop_process_timers (sig); sig->cputimer.checking_timer = false;
@@ -1048,26 +1038,23 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer) }/** -* task_cputime_expired - Compare two task_cputime entities. +* task_cputimers_expired - Compare two task_cputime entities. * -* @sample: The task_cputime structure to be checked for expiration. -* @expires: Expiration times, against which @sample will be checked. +* @samples: Array of current samples for the CPUCLOCK clocks +* @expiries: Array of expiry values for the CPUCLOCK clocks * -* Checks @sample against @expires to see if any field of @sample has expired. -* Returns true if any field of the former is greater than the corresponding -* field of the latter if the latter field is set. Otherwise returns false. +* Returns true if any mmember of @samples is greater than the corresponding +* member of @expiries if that member is non zero. False otherwise */ -static inline int task_cputime_expired (const struct task_cputime *sample, -const struct task_cputime *expires) +static inline bool task_cputimers_expired (const u64 *sample,const u64 *expiries) { -if (expires->utime && sample->utime >= expires->utime) -return 1 ; -if (expires->stime && sample->utime + sample->stime >= expires->stime) -return 1 ; -if (expires->sum_exec_runtime !=0 && - sample->sum_exec_runtime >= expires->sum_exec_runtime) -return 1 ; -return 0 ; +int i; + +for (i =0 ; i <CPUCLOCK_MAX ; i++) { +if (expiries[i] && sample[i] >= expiries[i]) +return true; + } +return false; }/**
@@ -1080,18 +1067,17 @@ static inline int task_cputime_expired(const struct task_cputime *sample,* timers and compare them with the corresponding expiration times. Return * true if a timer has expired, else return false. */ -static inline int fastpath_timer_check (struct task_struct *tsk) +static inline bool fastpath_timer_check (struct task_struct *tsk) { +u64 *expiries = tsk->posix_cputimers.expiries;struct signal_struct *sig; -if (!task_cputime_zero (&tsk->posix_cputimers.cputime_expires)) { -struct task_cputime task_sample; +if (!expiry_cache_is_zero (expiries)) { +u64 samples[CPUCLOCK_MAX ]; -task_cputime (tsk, &task_sample.utime, &task_sample.stime); - task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime; -if (task_cputime_expired (&task_sample, - &tsk->posix_cputimers.cputime_expires)) -return 1 ; +task_sample_cputime (tsk, samples); +if (task_cputimers_expired (samples, expiries)) +return true; } sig = tsk->signal;
@@ -1111,19 +1097,20 @@ static inline int fastpath_timer_check(struct task_struct *tsk)*/ if (READ_ONCE (sig->cputimer.running) && !READ_ONCE (sig->cputimer.checking_timer)) { -struct task_cputime group_sample; +u64 samples[CPUCLOCK_MAX ]; -sample_cputime_atomic (&group_sample, &sig->cputimer.cputime_atomic); +proc_sample_cputime_atomic (&sig->cputimer.cputime_atomic, + samples); -if (task_cputime_expired (&group_sample, - &sig->posix_cputimers.cputime_expires)) -return 1 ; +if (task_cputimers_expired (samples, + sig->posix_cputimers.expiries)) +return true; }if (dl_task (tsk) && tsk->dl.dl_overrun) -return 1 ; +return true; -return 0 ; +return false; }/*
PATCH v2 27/38 posix-cpu-timers: Remove cputime_expires
In reply to Thomas GleixnerThe last users of the magic struct cputime based expiry cache are gone. Remove the leftovers.
--- include/linux/posix-timers.h | 9 ++------- kernel/time/posix-cpu-timers.c | 10 ---------- 2 files changed, 2 insertions(+), 17 deletions(-)
include/linux/posix-timers.h +2 -7
@@ -65,19 +65,14 @@ static inline int clockid_to_fd(const cl#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data -* @cputime_expires: Earliest-expiration cache task_cputime based * @expiries: Earliest-expiration cache array based * @cpu_timers: List heads to queue posix CPU timers * * Used in task_struct and signal_struct */ struct posix_cputimers { -/* Temporary union until all users are cleaned up */ -union { -struct task_cputime cputime_expires; -u64 expiries[CPUCLOCK_MAX ]; - }; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +u64 expiries[CPUCLOCK_MAX ]; +struct list_head cpu_timers[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct)
kernel/time/posix-cpu-timers.c +0 -10
@@ -18,16 +18,6 @@#include "posix-timers.h" -static inline void temporary_check (void ) -{ -BUILD_BUG_ON (offsetof(struct task_cputime , stime) != -CPUCLOCK_PROF *sizeof (u64)); -BUILD_BUG_ON (offsetof(struct task_cputime , utime) != -CPUCLOCK_VIRT *sizeof (u64)); -BUILD_BUG_ON (offsetof(struct task_cputime , sum_exec_runtime) != -CPUCLOCK_SCHED *sizeof (u64)); -} -static void posix_cpu_timer_rearm (struct k_itimer *timer);void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit)
Re: [patch V2 27/38] posix-cpu-timers: Remove cputime_expires
Quoted 4 lines · Thomas Gleixner
The last users of the magic struct cputime based expiry cache are gone. Remove the leftovers.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Remove cputime_expires
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 46b883995c88520f2c4de6a64cccc04c69d59f83 Gitweb: https://git.kernel.org/tip/46b883995c88520f2c4de6a64cccc04c69d59f83 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:14 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:38 +02:00
posix-cpu-timers: Remove cputime_expires
The last users of the magic struct cputime based expiry cache are gone. Remove the leftovers.
--- include/linux/posix-timers.h | 9 ++------- kernel/time/posix-cpu-timers.c | 10 ---------- 2 files changed, 2 insertions(+), 17 deletions(-)
include/linux/posix-timers.h +2 -7
@@ -65,19 +65,14 @@ static inline int clockid_to_fd(const clockid_t clk)#ifdef CONFIG_POSIX_TIMERS /** * posix_cputimers - Container for posix CPU timer related data -* @cputime_expires: Earliest-expiration cache task_cputime based * @expiries: Earliest-expiration cache array based * @cpu_timers: List heads to queue posix CPU timers * * Used in task_struct and signal_struct */ struct posix_cputimers { -/* Temporary union until all users are cleaned up */ -union { -struct task_cputime cputime_expires; -u64 expiries[CPUCLOCK_MAX ]; - }; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +u64 expiries[CPUCLOCK_MAX ]; +struct list_head cpu_timers[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct)
kernel/time/posix-cpu-timers.c +0 -10
@@ -18,16 +18,6 @@#include "posix-timers.h" -static inline void temporary_check (void ) -{ -BUILD_BUG_ON (offsetof(struct task_cputime , stime) != -CPUCLOCK_PROF *sizeof (u64)); -BUILD_BUG_ON (offsetof(struct task_cputime , utime) != -CPUCLOCK_VIRT *sizeof (u64)); -BUILD_BUG_ON (offsetof(struct task_cputime , sum_exec_runtime) != -CPUCLOCK_SCHED *sizeof (u64)); -} -static void posix_cpu_timer_rearm (struct k_itimer *timer);void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit)
PATCH v2 28/38 posix-cpu-timers: Restructure expiry array
In reply to Thomas GleixnerNow that the abused struct task_cputime is gone, it's more natural to bundle the expiry cache and the list head of each clock into a struct and have an array of those structs.
Follow the hrtimer naming convention of 'bases' and rename the expiry cache to 'nextevt' and adapt all usage sites.
Generates also better code .text size shrinks by 80 bytes.
---
V2: New patch
--- include/linux/posix-timers.h | 41 ++++++++++------ kernel/time/posix-cpu-timers.c | 104 +++++++++++++++++++++-------------------- 2 files changed, 82 insertions(+), 63 deletions(-)
include/linux/posix-timers.h +27 -14
@@ -63,24 +63,33 @@ static inline int clockid_to_fd(const cl }#ifdef CONFIG_POSIX_TIMERS +/** -* posix_cputimers - Container for posix CPU timer related data -* @expiries: Earliest-expiration cache array based +* posix_cputimer_base - Container per posix CPU clock +* @nextevt: Earliest-expiration cache * @cpu_timers: List heads to queue posix CPU timers +*/ +struct posix_cputimer_base { +u64 nextevt; +struct list_head cpu_timers; +}; + +/** +* posix_cputimers - Container for posix CPU timer related data +* @bases: Base container for posix CPU clocks * * Used in task_struct and signal_struct */ struct posix_cputimers { -u64 expiries[CPUCLOCK_MAX ]; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +struct posix_cputimer_base bases[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (&pct->expiries,0 ,sizeof (pct->expiries)); -INIT_LIST_HEAD (&pct->cpu_timers[0 ]); -INIT_LIST_HEAD (&pct->cpu_timers[1 ]); -INIT_LIST_HEAD (&pct->cpu_timers[2 ]); +memset (pct->bases,0 ,sizeof (pct->bases)); +INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); +INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); +INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit);
@@ -88,19 +97,23 @@ void posix_cputimers_group_init(struct pstatic inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct,u64 runtime) { - pct->expiries[CPUCLOCK_SCHED ] = runtime; + pct->bases[CPUCLOCK_SCHED ].nextevt = runtime; }/* Init task static initializer */ -#define INIT_CPU_TIMERLISTS (c) { \ - LIST_HEAD_INIT(c.cpu_timers[0]), \ - LIST_HEAD_INIT(c.cpu_timers[1]), \ - LIST_HEAD_INIT(c.cpu_timers[2]), \ +#define INIT_CPU_TIMERBASE (b) { \ + .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ +} + +#define INIT_CPU_TIMERBASES (b) { \ + INIT_CPU_TIMERBASE(b[0]), \ + INIT_CPU_TIMERBASE(b[1]), \ + INIT_CPU_TIMERBASE(b[2]), \ }#define INIT_CPU_TIMERS (s) \ .posix_cputimers = { \ - .cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers), \ + .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ },#else struct posix_cputimers { };
kernel/time/posix-cpu-timers.c +55 -49
229 lines not on this page · raw message
Frederic Weisbecker
maintainerRe: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
Quoted 13 lines · Thomas Gleixner
/**
- *task_cputimers_expired- Compare twotask_cputimeentities.
+ *task_cputimers_expired- Check whether posix CPU timers are expired *
* @samples: Array of current samples for the CPUCLOCK clocks
- * @expiries: Array of expiry values for the CPUCLOCK clocks
+ * @pct: Pointer to aposix_cputimerscontainer
*
- * Returns true if any mmember of @samples is greater than the corresponding
- * member of @expiries if that member is non zero. False otherwise
+ * Returns true if any member of @samples is greater than the corresponding
+ * member of @pct->bases[CLK].nextevt. False otherwise
*/
kernel/time/posix-cpu-timers.c static void posix_cpu_timer_rearm(struct · line 1052
Quoted 9 lines
kernel/time/posix-cpu-timers.c +3
-2-static inline bool task_cputimers_expired (const u64 *sample,const u64 *expiries) +static inline bool +task_cputimers_expired (const u64 *sample,struct posix_cputimers *pct) {int i;for (i =0 ; i <CPUCLOCK_MAX ; i++) { -if (expiries[i] && sample[i] >= expiries[i]) +if (sample[i] >= pct->bases[i].nextevt)
You may have false positive here if you don't check if pct->bases[i].nextevt is 0. Probably no big deal by the end of the series since you change that 0 for KTIME_MAX later but right now it might hurt bisection with performance issues (locking sighand at every tick...).
[...]
kernel/time/posix-cpu-timers.c void run_posix_cpu_timers(void) · line 1185
Quoted 6 lines
kernel/time/posix-cpu-timers.c +1
-1@@ -1176,7 +1182,7 @@ void run_posix_cpu_timers(void)void set_process_cpu_timer (struct task_struct *tsk,unsigned int clkid,u64 *newval,u64 *oldval) { -u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid; +u64 now, *nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;
You're dereferencing the pointer before checking clkid sanity below.
Quoted 16 lines
kernel/time/posix-cpu-timers.c +2
-2if (WARN_ON_ONCE (clkid >=CPUCLOCK_SCHED ))return ;@@ -1207,8 +1213,8 @@ void set_process_cpu_timer(struct task_s* Update expiration cache if this is the earliest timer. CPUCLOCK_PROF * expiry cache is also used by RLIMIT_CPU!. */ -if (expires_gt (*expiry, *newval)) - *expiry = *newval; +if (expires_gt (*nextevt, *newval)) + *nextevt = *newval;tick_dep_set_signal (tsk->signal,TICK_DEP_BIT_POSIX_TIMER ); }
Re: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
Quoted 20 lines · Frederic Weisbecker
Quoted 19 lines · Thomas Gleixner
/**
- *task_cputimers_expired- Compare twotask_cputimeentities.
+ *task_cputimers_expired- Check whether posix CPU timers are expired *
* @samples: Array of current samples for the CPUCLOCK clocks
- * @expiries: Array of expiry values for the CPUCLOCK clocks
+ * @pct: Pointer to aposix_cputimerscontainer
*
- * Returns true if any mmember of @samples is greater than the corresponding
- * member of @expiries if that member is non zero. False otherwise
+ * Returns true if any member of @samples is greater than the corresponding
+ * member of @pct->bases[CLK].nextevt. False otherwise
*/kernel/time/posix-cpu-timers.c +2
-1-static inline bool task_cputimers_expired (const u64 *sample,const u64 *expiries) +static inline bool +task_cputimers_expired (const u64 *sample,struct posix_cputimers *pct) {int i;
Quoted 8 lines
kernel/time/posix-cpu-timers.c static void posix_cpu_timer_rearm(struct · line 1052
Quoted 3 lines
kernel/time/posix-cpu-timers.c +1
-1for (i =0 ; i <CPUCLOCK_MAX ; i++) { -if (expiries[i] && sample[i] >= expiries[i]) +if (sample[i] >= pct->bases[i].nextevt)You may have false positive here if you don't check if pct->bases[i].nextevt is 0. Probably no big deal by the end of the series since you change that 0 for
KTIME_MAXlater but right now it might hurt bisection with performance issues (locking sighand at every tick...).
Hrm. That should have stayed until the patch which removes that 0 state
Quoted 10 lines
[...]
kernel/time/posix-cpu-timers.c void run_posix_cpu_timers(void) · line 1185
Quoted 6 lines
kernel/time/posix-cpu-timers.c +1
-1@@ -1176,7 +1182,7 @@ void run_posix_cpu_timers(void)void set_process_cpu_timer (struct task_struct *tsk,unsigned int clkid,u64 *newval,u64 *oldval) { -u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid; +u64 now, *nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;You're dereferencing the pointer before checking clkid sanity below.
Urgh. Yes.
Thanks,
tglx
PATCH v3 28/38 posix-cpu-timers: Restructure expiry array
Now that the abused struct task_cputime is gone, it's more natural to bundle the expiry cache and the list head of each clock into a struct and have an array of those structs.
Follow the hrtimer naming convention of 'bases' and rename the expiry cache to 'nextevt' and adapt all usage sites.
Generates also better code .text size shrinks by 80 bytes.
---
V2: New patch
V3: Address review feedback from Frederic
--- include/linux/posix-timers.h | 41 ++++++++++------ kernel/time/posix-cpu-timers.c | 105 +++++++++++++++++++++-------------------- 2 files changed, 83 insertions(+), 63 deletions(-)
include/linux/posix-timers.h +27 -14
@@ -63,24 +63,33 @@ static inline int clockid_to_fd(const cl }#ifdef CONFIG_POSIX_TIMERS +/** -* posix_cputimers - Container for posix CPU timer related data -* @expiries: Earliest-expiration cache array based +* posix_cputimer_base - Container per posix CPU clock +* @nextevt: Earliest-expiration cache * @cpu_timers: List heads to queue posix CPU timers +*/ +struct posix_cputimer_base { +u64 nextevt; +struct list_head cpu_timers; +}; + +/** +* posix_cputimers - Container for posix CPU timer related data +* @bases: Base container for posix CPU clocks * * Used in task_struct and signal_struct */ struct posix_cputimers { -u64 expiries[CPUCLOCK_MAX ]; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +struct posix_cputimer_base bases[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (&pct->expiries,0 ,sizeof (pct->expiries)); -INIT_LIST_HEAD (&pct->cpu_timers[0 ]); -INIT_LIST_HEAD (&pct->cpu_timers[1 ]); -INIT_LIST_HEAD (&pct->cpu_timers[2 ]); +memset (pct->bases,0 ,sizeof (pct->bases)); +INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); +INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); +INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit);
@@ -88,19 +97,23 @@ void posix_cputimers_group_init(struct pstatic inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct,u64 runtime) { - pct->expiries[CPUCLOCK_SCHED ] = runtime; + pct->bases[CPUCLOCK_SCHED ].nextevt = runtime; }/* Init task static initializer */ -#define INIT_CPU_TIMERLISTS (c) { \ - LIST_HEAD_INIT(c.cpu_timers[0]), \ - LIST_HEAD_INIT(c.cpu_timers[1]), \ - LIST_HEAD_INIT(c.cpu_timers[2]), \ +#define INIT_CPU_TIMERBASE (b) { \ + .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ +} + +#define INIT_CPU_TIMERBASES (b) { \ + INIT_CPU_TIMERBASE(b[0]), \ + INIT_CPU_TIMERBASE(b[1]), \ + INIT_CPU_TIMERBASE(b[2]), \ }#define INIT_CPU_TIMERS (s) \ .posix_cputimers = { \ - .cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers), \ + .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ },#else struct posix_cputimers { };
kernel/time/posix-cpu-timers.c +56 -49
234 lines not on this page · raw message
Re: [patch V3 28/38] posix-cpu-timers: Restructure expiry array
Quoted 7 lines · Thomas Gleixner
Now that the abused struct
task_cputimeis gone, it's more natural to bundle the expiry cache and the list head of each clock into a struct and have an array of those structs.Follow the hrtimer naming convention of 'bases' and rename the expiry cache to 'nextevt' and adapt all usage sites.
Quoted 7 lines
Generates also better code .text size shrinks by 80 bytes.
Suggested-by Ingo Molnar <[email protected]>Signed-off-by Thomas Gleixner <[email protected]>---
V2: New patch
V3: Address review feedback from Frederic
[tip: timers/core] posix-cpu-timers: Restructure expiry array
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 87dc64480fb19a6a0fedbdff1e2557be50673287 Gitweb: https://git.kernel.org/tip/87dc64480fb19a6a0fedbdff1e2557be50673287 Author: Thomas Gleixner <[email protected]> AuthorDate: Mon, 26 Aug 2019 20:22:24 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:39 +02:00
posix-cpu-timers: Restructure expiry array
Now that the abused struct task_cputime is gone, it's more natural to bundle the expiry cache and the list head of each clock into a struct and have an array of those structs.
Follow the hrtimer naming convention of 'bases' and rename the expiry cache to 'nextevt' and adapt all usage sites.
Generates also better code .text size shrinks by 80 bytes.
--- include/linux/posix-timers.h | 41 +++++++----- kernel/time/posix-cpu-timers.c | 105 +++++++++++++++++--------------- 2 files changed, 83 insertions(+), 63 deletions(-)
include/linux/posix-timers.h +27 -14
@@ -63,24 +63,33 @@ static inline int clockid_to_fd(const clockid_t clk) }#ifdef CONFIG_POSIX_TIMERS +/** -* posix_cputimers - Container for posix CPU timer related data -* @expiries: Earliest-expiration cache array based +* posix_cputimer_base - Container per posix CPU clock +* @nextevt: Earliest-expiration cache * @cpu_timers: List heads to queue posix CPU timers +*/ +struct posix_cputimer_base { +u64 nextevt; +struct list_head cpu_timers; +}; + +/** +* posix_cputimers - Container for posix CPU timer related data +* @bases: Base container for posix CPU clocks * * Used in task_struct and signal_struct */ struct posix_cputimers { -u64 expiries[CPUCLOCK_MAX ]; -struct list_head cpu_timers[CPUCLOCK_MAX ]; +struct posix_cputimer_base bases[CPUCLOCK_MAX ]; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (&pct->expiries,0 ,sizeof (pct->expiries)); -INIT_LIST_HEAD (&pct->cpu_timers[0 ]); -INIT_LIST_HEAD (&pct->cpu_timers[1 ]); -INIT_LIST_HEAD (&pct->cpu_timers[2 ]); +memset (pct->bases,0 ,sizeof (pct->bases)); +INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); +INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); +INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit);
@@ -88,19 +97,23 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);static inline void posix_cputimers_rt_watchdog (struct posix_cputimers *pct,u64 runtime) { - pct->expiries[CPUCLOCK_SCHED ] = runtime; + pct->bases[CPUCLOCK_SCHED ].nextevt = runtime; }/* Init task static initializer */ -#define INIT_CPU_TIMERLISTS (c) { \ - LIST_HEAD_INIT(c.cpu_timers[0]), \ - LIST_HEAD_INIT(c.cpu_timers[1]), \ - LIST_HEAD_INIT(c.cpu_timers[2]), \ +#define INIT_CPU_TIMERBASE (b) { \ + .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ +} + +#define INIT_CPU_TIMERBASES (b) { \ + INIT_CPU_TIMERBASE(b[0]), \ + INIT_CPU_TIMERBASE(b[1]), \ + INIT_CPU_TIMERBASE(b[2]), \ }#define INIT_CPU_TIMERS (s) \ .posix_cputimers = { \ - .cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers), \ + .bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases), \ },#else struct posix_cputimers { };
kernel/time/posix-cpu-timers.c +56 -49
234 lines not on this page · raw message
Frederic Weisbecker
maintainerRe: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
In reply to Thomas GleixnerQuoted 11 lines · Thomas Gleixner
kernel/time/posix-cpu-timers.c +1
-1@@ -884,7 +888,7 @@ static void check_process_timers(struct struct list_head *firing) {struct signal_struct *const sig = tsk->signal; -struct list_head *timers = sig->posix_cputimers.cpu_timers; +struct posix_cputimer_base *base = sig->posix_cputimers.bases;u64 utime, ptime, virt_expires, prof_expires;u64 sum_sched_runtime, sched_expires;struct task_cputime cputime;@@ -912,9 +916,12 @@ static void check_process_timers(struct ptime = utime + cputime.stime;
kernel/time/posix-cpu-timers.c static void check_process_timers(struct · line 923
Quoted 10 lines
kernel/time/posix-cpu-timers.c +5
-3sum_sched_runtime = cputime.sum_exec_runtime; - prof_expires =check_timers_list (timers, firing, ptime); - virt_expires =check_timers_list (++timers, firing, utime); - sched_expires =check_timers_list (++timers, firing, sum_sched_runtime); + prof_expires =check_timers_list (&base[CPUCLOCK_PROF ].cpu_timers, + firing, ptime); + virt_expires =check_timers_list (&base[CPUCLOCK_VIRT ].cpu_timers, + firing, utime); + sched_expires = check_timers_list(&base[CLPCLOCK_SCHED].cpu_timers,
^^
0-day bot should have warned by now.
Re: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
Quoted 24 lines · Frederic Weisbecker
Quoted 11 lines · Thomas Gleixner
kernel/time/posix-cpu-timers.c +1
-1@@ -884,7 +888,7 @@ static void check_process_timers(struct struct list_head *firing) {struct signal_struct *const sig = tsk->signal; -struct list_head *timers = sig->posix_cputimers.cpu_timers; +struct posix_cputimer_base *base = sig->posix_cputimers.bases;u64 utime, ptime, virt_expires, prof_expires;u64 sum_sched_runtime, sched_expires;struct task_cputime cputime;@@ -912,9 +916,12 @@ static void check_process_timers(struct ptime = utime + cputime.stime;kernel/time/posix-cpu-timers.c static void check_process_timers(struct · line 923
Quoted 10 lines
kernel/time/posix-cpu-timers.c +5
-3sum_sched_runtime = cputime.sum_exec_runtime; - prof_expires =check_timers_list (timers, firing, ptime); - virt_expires =check_timers_list (++timers, firing, utime); - sched_expires =check_timers_list (++timers, firing, sum_sched_runtime); + prof_expires =check_timers_list (&base[CPUCLOCK_PROF ].cpu_timers, + firing, ptime); + virt_expires =check_timers_list (&base[CPUCLOCK_VIRT ].cpu_timers, + firing, utime); + sched_expires = check_timers_list(&base[CLPCLOCK_SCHED].cpu_timers,^^
Quoted 1 line
0-day bot should have warned by now.
It didn't but my own testing found it and I fixed it locally already
PATCH v2 29/38 posix-cpu-timers: Switch thread group sampling to array
In reply to Thomas GleixnerThat allows more simplifications in various places.
---
V2: Adopt to the per clock base struct
--- include/linux/sched/cputime.h | 2 kernel/time/itimer.c | 11 +--- kernel/time/posix-cpu-timers.c | 104 +++++++++++++++++------------------------ 3 files changed, 49 insertions(+), 68 deletions(-)
include/linux/sched/cputime.h +1 -1
@@ -61,7 +61,7 @@ extern void cputime_adjust(struct task_c* Thread group CPU time accounting. */ void thread_group_cputime (struct task_struct *tsk,struct task_cputime *times); -void thread_group_sample_cputime (struct task_struct *tsk,struct task_cputime *times); +void thread_group_sample_cputime (struct task_struct *tsk,u64 *samples);/* * The following are functions that support scheduler-internal time accounting.
kernel/time/itimer.c +3 -8
@@ -55,15 +55,10 @@ static void get_cpu_itimer(struct task_s val = it->expires; interval = it->incr;if (val) { -struct task_cputime cputime; -u64 t; +u64 t, samples[CPUCLOCK_MAX ]; -thread_group_sample_cputime (tsk, &cputime); -if (clock_id ==CPUCLOCK_PROF ) - t = cputime.utime + cputime.stime; -else -/* CPUCLOCK_VIRT */ - t = cputime.utime; +thread_group_sample_cputime (tsk, samples); + t = samples[clock_id];if (val < t)/* about to fire */
kernel/time/posix-cpu-timers.c +45 -59
189 lines not on this page · raw message
Re: [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array
Quoted 3 lines · Thomas Gleixner
That allows more simplifications in various places.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Switch thread group sampling to array
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: b7be4ef1365dcb56fdffc6689e41058b23f5996d Gitweb: https://git.kernel.org/tip/b7be4ef1365dcb56fdffc6689e41058b23f5996d Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:16 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:39 +02:00
posix-cpu-timers: Switch thread group sampling to array
That allows more simplifications in various places.
--- include/linux/sched/cputime.h | 2 +- kernel/time/itimer.c | 11 +--- kernel/time/posix-cpu-timers.c | 104 +++++++++++++------------------- 3 files changed, 49 insertions(+), 68 deletions(-)
include/linux/sched/cputime.h +1 -1
@@ -61,7 +61,7 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,* Thread group CPU time accounting. */ void thread_group_cputime (struct task_struct *tsk,struct task_cputime *times); -void thread_group_sample_cputime (struct task_struct *tsk,struct task_cputime *times); +void thread_group_sample_cputime (struct task_struct *tsk,u64 *samples);/* * The following are functions that support scheduler-internal time accounting.
kernel/time/itimer.c +3 -8
@@ -55,15 +55,10 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, val = it->expires; interval = it->incr;if (val) { -struct task_cputime cputime; -u64 t; +u64 t, samples[CPUCLOCK_MAX ]; -thread_group_sample_cputime (tsk, &cputime); -if (clock_id ==CPUCLOCK_PROF ) - t = cputime.utime + cputime.stime; -else -/* CPUCLOCK_VIRT */ - t = cputime.utime; +thread_group_sample_cputime (tsk, samples); + t = samples[clock_id];if (val < t)/* about to fire */
kernel/time/posix-cpu-timers.c +45 -59
189 lines not on this page · raw message
PATCH v2 30/38 posix-cpu-timers: Respect INFINITY for hard RTTIME limit
In reply to Thomas GleixnerThe RTIME limit expiry code does not check the hard RTTIME limit for INFINITY, i.e. being disabled. Add it.
While this could be considered an ABI breakage if something would depend on this behaviour. Though it's highly unlikely to have an effect because RLIM_INFINITY is at minimum INT_MAX and the RTTIME limit is in seconds, so the timer would fire after ~68 years.
Adding this obvious correct limit check also allows further consolidation of that code and is a prerequisite for cleaning up the 0 based checks and the rlimit setter code.
---
V2: Documented the theoretical ABI breakage in the changelong
--- kernel/time/posix-cpu-timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/posix-cpu-timers.c +1 -1
@@ -921,7 +921,7 @@ static void check_process_timers(structunsigned long hard =task_rlimit_max (tsk,RLIMIT_CPU );unsigned long psecs =div_u64 (ptime,NSEC_PER_SEC ); -if (psecs >= hard) { +if (hard !=RLIM_INFINITY && psecs >= hard) {/* * At the hard limit, we just die. * No need to calculate anything else now.
Re: [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit
Quoted 8 lines · Thomas Gleixner
The RTIME limit expiry code does not check the hard RTTIME limit for INFINITY, i.e. being disabled. Add it.
While this could be considered an ABI breakage if something would depend on this behaviour. Though it's highly unlikely to have an effect because
RLIM_INFINITYis at minimumINT_MAXand the RTTIME limit is in seconds, so the timer would fire after ~68 years.
Quoted 5 lines
Adding this obvious correct limit check also allows further consolidation of that code and is a prerequisite for cleaning up the 0 based checks and the rlimit setter code.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Respect INFINITY for hard RTTIME limit
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: fe0517f893d36636de20d0a809fc0c788ca0cade Gitweb: https://git.kernel.org/tip/fe0517f893d36636de20d0a809fc0c788ca0cade Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:17 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:39 +02:00
posix-cpu-timers: Respect INFINITY for hard RTTIME limit
The RTIME limit expiry code does not check the hard RTTIME limit for INFINITY, i.e. being disabled. Add it.
While this could be considered an ABI breakage if something would depend on this behaviour. Though it's highly unlikely to have an effect because RLIM_INFINITY is at minimum INT_MAX and the RTTIME limit is in seconds, so the timer would fire after ~68 years.
Adding this obvious correct limit check also allows further consolidation of that code and is a prerequisite for cleaning up the 0 based checks and the rlimit setter code.
--- kernel/time/posix-cpu-timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/posix-cpu-timers.c +1 -1
@@ -921,7 +921,7 @@ static void check_process_timers(struct task_struct *tsk,unsigned long hard =task_rlimit_max (tsk,RLIMIT_CPU );unsigned long psecs =div_u64 (ptime,NSEC_PER_SEC ); -if (psecs >= hard) { +if (hard !=RLIM_INFINITY && psecs >= hard) {/* * At the hard limit, we just die. * No need to calculate anything else now.
PATCH v2 31/38 rlimit: Rewrite non-sensical RLIMIT_CPU comment
In reply to Thomas GleixnerThe comment above the function which arms RLIMIT_CPU in the posix CPU timer code makes no sense at all. It claims that the kernel does not return an error code when it rejected the attempt to set RLIMIT_CPU. That's clearly bogus as the code does an error check and the rlimit is only set and activated when the permission checks are ok. In case of a rejection an appropriate error code is returned.
This is a historical and outdated comment which got dragged along even when the rlimit handling code was rewritten.
Replace it with an explanation why the setup function is not called when the rlimit value is RLIM_INFINITY and how the 'disarming' is handled.
--- kernel/sys.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
kernel/sys.c +3 -4
@@ -1576,10 +1576,9 @@ int do_prlimit(struct task_struct *tsk,task_unlock (tsk->group_leader);/* -* RLIMIT_CPU handling. Note that the kernel fails to return an error -* code if it rejected the user's attempt to set RLIMIT_CPU. This is a -* very long-standing error, and fixing it now risks breakage of -* applications, so we live with it +* RLIMIT_CPU handling. Arm the posix CPU timer if the limit is not +* infite. In case of RLIM_INFINITY the posix CPU timer code +* ignores the rlimit. */ if (!retval && new_rlim && resource == RLIMIT_CPU && new_rlim->rlim_cur != RLIM_INFINITY &&
Re: [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment
Quoted 10 lines · Thomas Gleixner
The comment above the function which arms
RLIMIT_CPUin the posix CPU timer code makes no sense at all. It claims that the kernel does not return an error code when it rejected the attempt to setRLIMIT_CPU. That's clearly bogus as the code does an error check and the rlimit is only set and activated when the permission checks are ok. In case of a rejection an appropriate error code is returned.This is a historical and outdated comment which got dragged along even when the rlimit handling code was rewritten.
Quoted 6 lines
Replace it with an explanation why the setup function is not called when the rlimit value is
RLIM_INFINITYand how the 'disarming' is handled.Signed-off-by Thomas Gleixner <[email protected]>Cc Andrew Morton <[email protected]>Cc Jiri Slaby <[email protected]>
[tip: timers/core] rlimit: Rewrite non-sensical RLIMIT_CPU comment
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 24db4dd90dd53ad6e3331b6f01cb985e466cface Gitweb: https://git.kernel.org/tip/24db4dd90dd53ad6e3331b6f01cb985e466cface Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:18 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:40 +02:00
rlimit: Rewrite non-sensical RLIMIT_CPU comment
The comment above the function which arms RLIMIT_CPU in the posix CPU timer code makes no sense at all. It claims that the kernel does not return an error code when it rejected the attempt to set RLIMIT_CPU. That's clearly bogus as the code does an error check and the rlimit is only set and activated when the permission checks are ok. In case of a rejection an appropriate error code is returned.
This is a historical and outdated comment which got dragged along even when the rlimit handling code was rewritten.
Replace it with an explanation why the setup function is not called when the rlimit value is RLIM_INFINITY and how the 'disarming' is handled.
--- kernel/sys.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
kernel/sys.c +3 -4
@@ -1576,10 +1576,9 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,task_unlock (tsk->group_leader);/* -* RLIMIT_CPU handling. Note that the kernel fails to return an error -* code if it rejected the user's attempt to set RLIMIT_CPU. This is a -* very long-standing error, and fixing it now risks breakage of -* applications, so we live with it +* RLIMIT_CPU handling. Arm the posix CPU timer if the limit is not +* infite. In case of RLIM_INFINITY the posix CPU timer code +* ignores the rlimit. */ if (!retval && new_rlim && resource == RLIMIT_CPU && new_rlim->rlim_cur != RLIM_INFINITY &&
PATCH v2 32/38 posix-cpu-timers: Get rid of zero checks
In reply to Thomas GleixnerDeactivation of the expiry cache is done by setting all clock caches to
0. That requires to have a check for zero in all places which update the expiry cache:
if (cache == 0 || new < cache) cache = new;
Use U64_MAX as the deactivated value, which allows to remove the zero checks when updating the cache and reduces it to the obvious check:
if (new < cache) cache = new;
This also removes the weird workaround in do_prlimit() which was required to convert a RLIMIT_CPU value of 0 (immediate expiry) to 1 because handing in 0 to the posix CPU timer code would have effectively disarmed it.
---
V2: Adopt to the per clock base struct and cleanup the rlimit setter code.
--- include/linux/posix-timers.h | 7 +++++-- kernel/sys.c | 9 --------- kernel/time/posix-cpu-timers.c | 36 ++++++++++++++---------------------- 3 files changed, 19 insertions(+), 33 deletions(-)
include/linux/posix-timers.h +5 -2
@@ -86,7 +86,9 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (pct->bases,0 ,sizeof (pct->bases)); + pct->bases[0 ].nextevt =U64_MAX ; + pct->bases[1 ].nextevt =U64_MAX ; + pct->bases[2 ].nextevt =U64_MAX ;INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers);INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers);INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers);
@@ -102,7 +104,8 @@ static inline void posix_cputimers_rt_wa/* Init task static initializer */ #define INIT_CPU_TIMERBASE (b) { \ - .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ + .nextevt = U64_MAX, \ + .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ }#define INIT_CPU_TIMERBASES (b) { \
kernel/sys.c +0 -9
@@ -1557,15 +1557,6 @@ int do_prlimit(struct task_struct *tsk, retval = -EPERM ;if (!retval) retval =security_task_setrlimit (tsk, resource, new_rlim); -if (resource ==RLIMIT_CPU && new_rlim->rlim_cur ==0 ) { -/* -* The caller is asking for an immediate RLIMIT_CPU -* expiry. But we use the zero value to mean "it was -* never set". So let's cheat and make it one second -* instead -*/ - new_rlim->rlim_cur =1 ; - } }if (!retval) {if (old_rlim)
kernel/time/posix-cpu-timers.c +14 -22
@@ -122,11 +122,12 @@ static void bump_cpu_timer(struct k_itim } } -static inline bool expiry_cache_is_zero (const struct posix_cputimers *pct) +/* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */ +static inline bool expiry_cache_is_inactive (const struct posix_cputimers *pct) { -return !(pct->bases[CPUCLOCK_PROF ].nextevt | - pct->bases[CPUCLOCK_VIRT ].nextevt | - pct->bases[CPUCLOCK_SCHED ].nextevt); +return !(~pct->bases[CPUCLOCK_PROF ].nextevt | + ~pct->bases[CPUCLOCK_VIRT ].nextevt | + ~pct->bases[CPUCLOCK_SCHED ].nextevt); } static int
@@ -442,11 +443,6 @@ void posix_cpu_timers_exit_group(structcleanup_timers (&tsk->signal->posix_cputimers); } -static inline int expires_gt (u64 expires,u64 new_exp) -{ -return expires ==0 || expires > new_exp; -} -/* * Insert the timer on the appropriate list before any timers that * expire later. This must be called with the sighand lock held.
@@ -483,7 +479,7 @@ static void arm_timer(struct k_itimer *t* for process timers we share expiration cache with itimers * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. */ -if (expires_gt (base->nextevt, newexp)) +if (newexp < base->nextevt) base->nextevt = newexp;if (CPUCLOCK_PERTHREAD (timer->it_clock))
@@ -753,7 +749,7 @@ check_timers_list(struct list_head *timelist_move_tail (&t->entry, firing); } -return 0 ; +return U64_MAX ; }static inline void check_dl_overrun (struct task_struct *tsk)
@@ -779,11 +775,7 @@ static void check_thread_timers(struct tif (dl_task (tsk))check_dl_overrun (tsk); -/* -* If the expiry cache is zero, then there are no active per thread -* CPU timers. -*/ -if (expiry_cache_is_zero (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (&tsk->posix_cputimers))return ;task_cputime (tsk, &utime, &stime);
@@ -833,7 +825,7 @@ static void check_thread_timers(struct t } } -if (expiry_cache_is_zero (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (&tsk->posix_cputimers))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -864,7 +856,7 @@ static void check_cpu_itimer(struct task__group_send_sig_info (signo,SEND_SIG_PRIV , tsk); } -if (it->expires && (!*expires || it->expires < *expires)) +if (it->expires && it->expires < *expires) *expires = it->expires; }
@@ -948,7 +940,7 @@ static void check_process_timers(struct } } softns = soft *NSEC_PER_SEC ; -if (!prof_exp || softns < prof_exp) +if (softns < prof_exp) prof_exp = softns; }
@@ -956,7 +948,7 @@ static void check_process_timers(struct base[CPUCLOCK_VIRT ].nextevt = virt_exp; base[CPUCLOCK_SCHED ].nextevt = sched_exp; -if (expiry_cache_is_zero (&sig->posix_cputimers)) +if (expiry_cache_is_inactive (&sig->posix_cputimers))stop_process_timers (sig); sig->cputimer.checking_timer = false;
@@ -1055,7 +1047,7 @@ static inline bool fastpath_timer_check( {struct signal_struct *sig; -if (!expiry_cache_is_zero (&tsk->posix_cputimers)) { +if (!expiry_cache_is_inactive (&tsk->posix_cputimers)) {u64 samples[CPUCLOCK_MAX ];task_sample_cputime (tsk, samples);
@@ -1199,7 +1191,7 @@ void set_process_cpu_timer(struct task_s* Update expiration cache if this is the earliest timer. CPUCLOCK_PROF * expiry cache is also used by RLIMIT_CPU!. */ -if (expires_gt (*nextevt, *newval)) +if (*newval < *nextevt) *nextevt = *newval;tick_dep_set_signal (tsk->signal,TICK_DEP_BIT_POSIX_TIMER );
Re: [patch V2 32/38] posix-cpu-timers: Get rid of zero checks
Quoted 10 lines · Thomas Gleixner
Deactivation of the expiry cache is done by setting all clock caches to
0. That requires to have a check for zero in all places which update the expiry cache:if (cache == 0 || new < cache) cache = new;Use
U64_MAXas the deactivated value, which allows to remove the zero checks when updating the cache and reduces it to the obvious check:
Quoted 8 lines
if (new < cache) cache = new;This also removes the weird workaround in
do_prlimit()which was required to convert aRLIMIT_CPUvalue of 0 (immediate expiry) to 1 because handing in 0 to the posix CPU timer code would have effectively disarmed it.Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Get rid of zero checks
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 2bbdbdae05167c688b6d3499a7dab74208b80a22 Gitweb: https://git.kernel.org/tip/2bbdbdae05167c688b6d3499a7dab74208b80a22 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:19 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:40 +02:00
posix-cpu-timers: Get rid of zero checks
Deactivation of the expiry cache is done by setting all clock caches to
0. That requires to have a check for zero in all places which update the expiry cache:
if (cache == 0 || new < cache) cache = new;
Use U64_MAX as the deactivated value, which allows to remove the zero checks when updating the cache and reduces it to the obvious check:
if (new < cache) cache = new;
This also removes the weird workaround in do_prlimit() which was required to convert a RLIMIT_CPU value of 0 (immediate expiry) to 1 because handing in 0 to the posix CPU timer code would have effectively disarmed it.
--- include/linux/posix-timers.h | 7 ++++-- kernel/sys.c | 9 +-------- kernel/time/posix-cpu-timers.c | 38 +++++++++++++-------------------- 3 files changed, 20 insertions(+), 34 deletions(-)
include/linux/posix-timers.h +5 -2
@@ -86,7 +86,9 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { -memset (pct->bases,0 ,sizeof (pct->bases)); + pct->bases[0 ].nextevt =U64_MAX ; + pct->bases[1 ].nextevt =U64_MAX ; + pct->bases[2 ].nextevt =U64_MAX ;INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers);INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers);INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers);
@@ -102,7 +104,8 @@ static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,/* Init task static initializer */ #define INIT_CPU_TIMERBASE (b) { \ - .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ + .nextevt = U64_MAX, \ + .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ }#define INIT_CPU_TIMERBASES (b) { \
kernel/sys.c +0 -9
@@ -1557,15 +1557,6 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource, retval = -EPERM ;if (!retval) retval =security_task_setrlimit (tsk, resource, new_rlim); -if (resource ==RLIMIT_CPU && new_rlim->rlim_cur ==0 ) { -/* -* The caller is asking for an immediate RLIMIT_CPU -* expiry. But we use the zero value to mean "it was -* never set". So let's cheat and make it one second -* instead -*/ - new_rlim->rlim_cur =1 ; - } }if (!retval) {if (old_rlim)
kernel/time/posix-cpu-timers.c +15 -23
@@ -122,11 +122,12 @@ static void bump_cpu_timer(struct k_itimer *timer, u64 now) } } -static inline bool expiry_cache_is_zero (const struct posix_cputimers *pct) +/* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */ +static inline bool expiry_cache_is_inactive (const struct posix_cputimers *pct) { -return !(pct->bases[CPUCLOCK_PROF ].nextevt | - pct->bases[CPUCLOCK_VIRT ].nextevt | - pct->bases[CPUCLOCK_SCHED ].nextevt); +return !(~pct->bases[CPUCLOCK_PROF ].nextevt | + ~pct->bases[CPUCLOCK_VIRT ].nextevt | + ~pct->bases[CPUCLOCK_SCHED ].nextevt); } static int
@@ -442,11 +443,6 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)cleanup_timers (&tsk->signal->posix_cputimers); } -static inline int expires_gt (u64 expires,u64 new_exp) -{ -return expires ==0 || expires > new_exp; -} -/* * Insert the timer on the appropriate list before any timers that * expire later. This must be called with the sighand lock held.
@@ -483,7 +479,7 @@ static void arm_timer(struct k_itimer *timer)* for process timers we share expiration cache with itimers * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME. */ -if (expires_gt (base->nextevt, newexp)) +if (newexp < base->nextevt) base->nextevt = newexp;if (CPUCLOCK_PERTHREAD (timer->it_clock))
@@ -753,7 +749,7 @@ check_timers_list(struct list_head *timers,list_move_tail (&t->entry, firing); } -return 0 ; +return U64_MAX ; }static inline void check_dl_overrun (struct task_struct *tsk)
@@ -779,11 +775,7 @@ static void check_thread_timers(struct task_struct *tsk,if (dl_task (tsk))check_dl_overrun (tsk); -/* -* If the expiry cache is zero, then there are no active per thread -* CPU timers. -*/ -if (expiry_cache_is_zero (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (&tsk->posix_cputimers))return ;task_cputime (tsk, &utime, &stime);
@@ -833,7 +825,7 @@ static void check_thread_timers(struct task_struct *tsk, } } -if (expiry_cache_is_zero (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (&tsk->posix_cputimers))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -864,7 +856,7 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,__group_send_sig_info (signo,SEND_SIG_PRIV , tsk); } -if (it->expires && (!*expires || it->expires < *expires)) +if (it->expires && it->expires < *expires) *expires = it->expires; }
@@ -948,7 +940,7 @@ static void check_process_timers(struct task_struct *tsk, } } softns = soft *NSEC_PER_SEC ; -if (!prof_exp || softns < prof_exp) +if (softns < prof_exp) prof_exp = softns; }
@@ -956,7 +948,7 @@ static void check_process_timers(struct task_struct *tsk, base[CPUCLOCK_VIRT ].nextevt = virt_exp; base[CPUCLOCK_SCHED ].nextevt = sched_exp; -if (expiry_cache_is_zero (&sig->posix_cputimers)) +if (expiry_cache_is_inactive (&sig->posix_cputimers))stop_process_timers (sig); sig->cputimer.checking_timer = false;
@@ -1035,7 +1027,7 @@ task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)int i;for (i =0 ; i <CPUCLOCK_MAX ; i++) { -if (pct->bases[i].nextevt && sample[i] >= pct->bases[i].nextevt) +if (sample[i] >= pct->bases[i].nextevt)return true; }return false;
@@ -1055,7 +1047,7 @@ static inline bool fastpath_timer_check(struct task_struct *tsk) {struct signal_struct *sig; -if (!expiry_cache_is_zero (&tsk->posix_cputimers)) { +if (!expiry_cache_is_inactive (&tsk->posix_cputimers)) {u64 samples[CPUCLOCK_MAX ];task_sample_cputime (tsk, samples);
@@ -1200,7 +1192,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,* Update expiration cache if this is the earliest timer. CPUCLOCK_PROF * expiry cache is also used by RLIMIT_CPU!. */ -if (expires_gt (*nextevt, *newval)) +if (*newval < *nextevt) *nextevt = *newval;tick_dep_set_signal (tsk->signal,TICK_DEP_BIT_POSIX_TIMER );
PATCH v2 33/38 posix-cpu-timers: Consolidate timer expiry further
In reply to Thomas GleixnerWith the array based samples and expiry cache, the expiry function can use a loop to collect timers from the clock specific lists.
---
V2: Adopt to the per clock base struct
--- kernel/time/posix-cpu-timers.c | 63 +++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 33 deletions(-)
kernel/time/posix-cpu-timers.c +30 -33
@@ -752,6 +752,18 @@ check_timers_list(struct list_head *timereturn U64_MAX ; } +static void collect_posix_cputimers (struct posix_cputimers *pct, +u64 *samples,struct list_head *firing) +{ +struct posix_cputimer_base *base = pct->bases; +int i; + +for (i =0 ; i <CPUCLOCK_MAX ; i++, base++) { + base->nextevt =check_timers_list (&base->cpu_timers, firing, + samples[i]); + } +} +static inline void check_dl_overrun (struct task_struct *tsk) {if (tsk->dl.dl_overrun) {
@@ -768,25 +780,18 @@ static inline void check_dl_overrun(strustatic void check_thread_timers (struct task_struct *tsk,struct list_head *firing) { -struct posix_cputimer_base *base = tsk->posix_cputimers.bases; +struct posix_cputimers *pct = &tsk->posix_cputimers; +u64 samples[CPUCLOCK_MAX ];unsigned long soft; -u64 stime, utime;if (dl_task (tsk))check_dl_overrun (tsk); -if (expiry_cache_is_inactive (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (pct))return ; -task_cputime (tsk, &utime, &stime); - - base->nextevt =check_timers_list (&base->cpu_timers, firing, - utime + stime); - base++; - base->nextevt =check_timers_list (&base->cpu_timers, firing, utime); - base++; - base->nextevt =check_timers_list (&base->cpu_timers, firing, - tsk->se.sum_exec_runtime); +task_sample_cputime (tsk, samples); +collect_posix_cputimers (pct, samples, firing);/* * Check for the special case thread timers.
@@ -825,7 +830,7 @@ static void check_thread_timers(struct t } } -if (expiry_cache_is_inactive (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (pct))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -869,15 +874,15 @@ static void check_process_timers(struct struct list_head *firing) {struct signal_struct *const sig = tsk->signal; -struct posix_cputimer_base *base = sig->posix_cputimers.bases; -u64 virt_exp, prof_exp, sched_exp, samples[CPUCLOCK_MAX ]; +struct posix_cputimers *pct = &sig->posix_cputimers; +u64 samples[CPUCLOCK_MAX ];unsigned long soft;/* * If cputimer is not running, then there are no active * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU). */ -if (!READ_ONCE (tsk->signal->cputimer.running)) +if (!READ_ONCE (sig->cputimer.running))return ;/*
@@ -891,21 +896,17 @@ static void check_process_timers(struct* so the sample can be taken directly. */ proc_sample_cputime_atomic (&sig->cputimer.cputime_atomic, samples); - - prof_exp =check_timers_list (&base[CPUCLOCK_PROF ].cpu_timers, - firing, samples[CPUCLOCK_PROF ]); - virt_exp =check_timers_list (&base[CPUCLOCK_VIRT ].cpu_timers, - firing, samples[CPUCLOCK_VIRT ]); - sched_exp =check_timers_list (&base[CPUCLOCK_SCHED ].cpu_timers, - firing, samples[CPUCLOCK_SCHED ]); +collect_posix_cputimers (pct, samples, firing);/* * Check for the special case process timers. */ -check_cpu_itimer (tsk, &sig->it[CPUCLOCK_PROF ], &prof_exp, +check_cpu_itimer (tsk, &sig->it[CPUCLOCK_PROF ], + &pct->bases[CPUCLOCK_PROF ].nextevt, samples[CPUCLOCK_PROF ],SIGPROF ); -check_cpu_itimer (tsk, &sig->it[CPUCLOCK_VIRT ], &virt_exp, - samples[CPUCLOCK_PROF ],SIGVTALRM ); +check_cpu_itimer (tsk, &sig->it[CPUCLOCK_VIRT ], + &pct->bases[CPUCLOCK_VIRT ].nextevt, + samples[CPUCLOCK_VIRT ],SIGVTALRM ); soft =task_rlimit (tsk,RLIMIT_CPU );if (soft !=RLIM_INFINITY ) {
@@ -940,15 +941,11 @@ static void check_process_timers(struct } } softns = soft *NSEC_PER_SEC ; -if (softns < prof_exp) - prof_exp = softns; +if (softns < pct->bases[CPUCLOCK_PROF ].nextevt) + pct->bases[CPUCLOCK_PROF ].nextevt = softns; } - base[CPUCLOCK_PROF ].nextevt = prof_exp; - base[CPUCLOCK_VIRT ].nextevt = virt_exp; - base[CPUCLOCK_SCHED ].nextevt = sched_exp; - -if (expiry_cache_is_inactive (&sig->posix_cputimers)) +if (expiry_cache_is_inactive (pct))stop_process_timers (sig); sig->cputimer.checking_timer = false;
Re: [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further
Quoted 4 lines · Thomas Gleixner
With the array based samples and expiry cache, the expiry function can use a loop to collect timers from the clock specific lists.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Consolidate timer expiry further
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 1cd07c0b94f2c320270d76edb7dd49bceb09c1df Gitweb: https://git.kernel.org/tip/1cd07c0b94f2c320270d76edb7dd49bceb09c1df Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:20 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:41 +02:00
posix-cpu-timers: Consolidate timer expiry further
With the array based samples and expiry cache, the expiry function can use a loop to collect timers from the clock specific lists.
--- kernel/time/posix-cpu-timers.c | 63 +++++++++++++++------------------ 1 file changed, 30 insertions(+), 33 deletions(-)
kernel/time/posix-cpu-timers.c +30 -33
@@ -752,6 +752,18 @@ check_timers_list(struct list_head *timers,return U64_MAX ; } +static void collect_posix_cputimers (struct posix_cputimers *pct, +u64 *samples,struct list_head *firing) +{ +struct posix_cputimer_base *base = pct->bases; +int i; + +for (i =0 ; i <CPUCLOCK_MAX ; i++, base++) { + base->nextevt =check_timers_list (&base->cpu_timers, firing, + samples[i]); + } +} +static inline void check_dl_overrun (struct task_struct *tsk) {if (tsk->dl.dl_overrun) {
@@ -768,25 +780,18 @@ static inline void check_dl_overrun(struct task_struct *tsk)static void check_thread_timers (struct task_struct *tsk,struct list_head *firing) { -struct posix_cputimer_base *base = tsk->posix_cputimers.bases; +struct posix_cputimers *pct = &tsk->posix_cputimers; +u64 samples[CPUCLOCK_MAX ];unsigned long soft; -u64 stime, utime;if (dl_task (tsk))check_dl_overrun (tsk); -if (expiry_cache_is_inactive (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (pct))return ; -task_cputime (tsk, &utime, &stime); - - base->nextevt =check_timers_list (&base->cpu_timers, firing, - utime + stime); - base++; - base->nextevt =check_timers_list (&base->cpu_timers, firing, utime); - base++; - base->nextevt =check_timers_list (&base->cpu_timers, firing, - tsk->se.sum_exec_runtime); +task_sample_cputime (tsk, samples); +collect_posix_cputimers (pct, samples, firing);/* * Check for the special case thread timers.
@@ -825,7 +830,7 @@ static void check_thread_timers(struct task_struct *tsk, } } -if (expiry_cache_is_inactive (&tsk->posix_cputimers)) +if (expiry_cache_is_inactive (pct))tick_dep_clear_task (tsk,TICK_DEP_BIT_POSIX_TIMER ); }
@@ -869,15 +874,15 @@ static void check_process_timers(struct task_struct *tsk, struct list_head *firing) {struct signal_struct *const sig = tsk->signal; -struct posix_cputimer_base *base = sig->posix_cputimers.bases; -u64 virt_exp, prof_exp, sched_exp, samples[CPUCLOCK_MAX ]; +struct posix_cputimers *pct = &sig->posix_cputimers; +u64 samples[CPUCLOCK_MAX ];unsigned long soft;/* * If cputimer is not running, then there are no active * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU). */ -if (!READ_ONCE (tsk->signal->cputimer.running)) +if (!READ_ONCE (sig->cputimer.running))return ;/*
@@ -891,21 +896,17 @@ static void check_process_timers(struct task_struct *tsk,* so the sample can be taken directly. */ proc_sample_cputime_atomic (&sig->cputimer.cputime_atomic, samples); - - prof_exp =check_timers_list (&base[CPUCLOCK_PROF ].cpu_timers, - firing, samples[CPUCLOCK_PROF ]); - virt_exp =check_timers_list (&base[CPUCLOCK_VIRT ].cpu_timers, - firing, samples[CPUCLOCK_VIRT ]); - sched_exp =check_timers_list (&base[CPUCLOCK_SCHED ].cpu_timers, - firing, samples[CPUCLOCK_SCHED ]); +collect_posix_cputimers (pct, samples, firing);/* * Check for the special case process timers. */ -check_cpu_itimer (tsk, &sig->it[CPUCLOCK_PROF ], &prof_exp, +check_cpu_itimer (tsk, &sig->it[CPUCLOCK_PROF ], + &pct->bases[CPUCLOCK_PROF ].nextevt, samples[CPUCLOCK_PROF ],SIGPROF ); -check_cpu_itimer (tsk, &sig->it[CPUCLOCK_VIRT ], &virt_exp, - samples[CPUCLOCK_PROF ],SIGVTALRM ); +check_cpu_itimer (tsk, &sig->it[CPUCLOCK_VIRT ], + &pct->bases[CPUCLOCK_VIRT ].nextevt, + samples[CPUCLOCK_VIRT ],SIGVTALRM ); soft =task_rlimit (tsk,RLIMIT_CPU );if (soft !=RLIM_INFINITY ) {
@@ -940,15 +941,11 @@ static void check_process_timers(struct task_struct *tsk, } } softns = soft *NSEC_PER_SEC ; -if (softns < prof_exp) - prof_exp = softns; +if (softns < pct->bases[CPUCLOCK_PROF ].nextevt) + pct->bases[CPUCLOCK_PROF ].nextevt = softns; } - base[CPUCLOCK_PROF ].nextevt = prof_exp; - base[CPUCLOCK_VIRT ].nextevt = virt_exp; - base[CPUCLOCK_SCHED ].nextevt = sched_exp; - -if (expiry_cache_is_inactive (&sig->posix_cputimers)) +if (expiry_cache_is_inactive (pct))stop_process_timers (sig); sig->cputimer.checking_timer = false;
PATCH v2 34/38 posix-cpu-timers: Get rid of 64bit divisions
In reply to Thomas GleixnerInstead of dividing A to match the units of B it's more efficient to multiply B to match the units of A.
---
V2: Fix the dropped update of the expiry cache when the soft limit increased
--- kernel/time/posix-cpu-timers.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
kernel/time/posix-cpu-timers.c +14 -10
@@ -798,10 +798,11 @@ static void check_thread_timers(struct t*/ soft =task_rlimit (tsk,RLIMIT_RTTIME );if (soft !=RLIM_INFINITY ) { +/* Task RT timeout is accounted in jiffies. RTTIME is usec */ +unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC /HZ );unsigned long hard =task_rlimit_max (tsk,RLIMIT_RTTIME ); -if (hard !=RLIM_INFINITY && - tsk->rt.timeout >DIV_ROUND_UP (hard,USEC_PER_SEC /HZ )) { +if (hard !=RLIM_INFINITY && rtim >= hard) {/* * At the hard limit, we just die. * No need to calculate anything else now.
@@ -813,7 +814,7 @@ static void check_thread_timers(struct t__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk);return ; } -if (tsk->rt.timeout >DIV_ROUND_UP (soft,USEC_PER_SEC /HZ )) { +if (rtim >= soft) {/* * At the soft limit, send a SIGXCPU every second. */
@@ -910,11 +911,13 @@ static void check_process_timers(struct soft =task_rlimit (tsk,RLIMIT_CPU );if (soft !=RLIM_INFINITY ) { -u64 softns, ptime = samples[CPUCLOCK_PROF ]; +/* RLIMIT_CPU is in seconds. Samples are nanoseconds */ unsigned long hard =task_rlimit_max (tsk,RLIMIT_CPU ); -unsigned long psecs =div_u64 (ptime,NSEC_PER_SEC ); +u64 ptime = samples[CPUCLOCK_PROF ]; +u64 softns = (u64 )soft *NSEC_PER_SEC ; +u64 hardns = (u64 )hard *NSEC_PER_SEC ; -if (hard !=RLIM_INFINITY && psecs >= hard) { +if (hard !=RLIM_INFINITY && ptime >= hardns) {/* * At the hard limit, we just die. * No need to calculate anything else now.
@@ -926,7 +929,7 @@ static void check_process_timers(struct__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk);return ; } -if (psecs >= soft) { +if (ptime >= softns) {/* * At the soft limit, send a SIGXCPU every second. */
@@ -936,11 +939,12 @@ static void check_process_timers(struct }__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk);if (soft < hard) { - soft++; - sig->rlim[RLIMIT_CPU ].rlim_cur = soft; + sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; + softns +=NSEC_PER_SEC ; } } - softns = soft *NSEC_PER_SEC ; + +/* Update the expiry cache */ if (softns < pct->bases[CPUCLOCK_PROF ].nextevt) pct->bases[CPUCLOCK_PROF ].nextevt = softns; }
Re: [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions
Quoted 13 lines · Thomas Gleixner
Instead of dividing A to match the units of B it's more efficient to multiply B to match the units of A.
Signed-off-by Thomas Gleixner <[email protected]>---
V2: Fix the dropped update of the expiry cache when the soft limit increased--- kernel/time/posix-cpu-timers.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
kernel/time/posix-cpu-timers.c static void check_thread_timers(struct t · line 802
Quoted 5 lines
kernel/time/posix-cpu-timers.c +2
-0@@ -798,10 +798,11 @@ static void check_thread_timers(struct t*/ soft =task_rlimit (tsk,RLIMIT_RTTIME );if (soft !=RLIM_INFINITY ) { +/* Task RT timeout is accounted in jiffies. RTTIME is usec */ +unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC /HZ );
jiffies_to_usecs() ?
[tip: timers/core] posix-cpu-timers: Get rid of 64bit divisions
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 8ea1de90a5eccdc18c8f05f8596bae8660a3ff9a Gitweb: https://git.kernel.org/tip/8ea1de90a5eccdc18c8f05f8596bae8660a3ff9a Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:21 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:41 +02:00
posix-cpu-timers: Get rid of 64bit divisions
Instead of dividing A to match the units of B it's more efficient to multiply B to match the units of A.
--- kernel/time/posix-cpu-timers.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-)
kernel/time/posix-cpu-timers.c +14 -10
@@ -798,10 +798,11 @@ static void check_thread_timers(struct task_struct *tsk,*/ soft =task_rlimit (tsk,RLIMIT_RTTIME );if (soft !=RLIM_INFINITY ) { +/* Task RT timeout is accounted in jiffies. RTTIME is usec */ +unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC /HZ );unsigned long hard =task_rlimit_max (tsk,RLIMIT_RTTIME ); -if (hard !=RLIM_INFINITY && - tsk->rt.timeout >DIV_ROUND_UP (hard,USEC_PER_SEC /HZ )) { +if (hard !=RLIM_INFINITY && rtim >= hard) {/* * At the hard limit, we just die. * No need to calculate anything else now.
@@ -813,7 +814,7 @@ static void check_thread_timers(struct task_struct *tsk,__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk);return ; } -if (tsk->rt.timeout >DIV_ROUND_UP (soft,USEC_PER_SEC /HZ )) { +if (rtim >= soft) {/* * At the soft limit, send a SIGXCPU every second. */
@@ -910,11 +911,13 @@ static void check_process_timers(struct task_struct *tsk, soft =task_rlimit (tsk,RLIMIT_CPU );if (soft !=RLIM_INFINITY ) { -u64 softns, ptime = samples[CPUCLOCK_PROF ]; +/* RLIMIT_CPU is in seconds. Samples are nanoseconds */ unsigned long hard =task_rlimit_max (tsk,RLIMIT_CPU ); -unsigned long psecs =div_u64 (ptime,NSEC_PER_SEC ); +u64 ptime = samples[CPUCLOCK_PROF ]; +u64 softns = (u64 )soft *NSEC_PER_SEC ; +u64 hardns = (u64 )hard *NSEC_PER_SEC ; -if (hard !=RLIM_INFINITY && psecs >= hard) { +if (hard !=RLIM_INFINITY && ptime >= hardns) {/* * At the hard limit, we just die. * No need to calculate anything else now.
@@ -926,7 +929,7 @@ static void check_process_timers(struct task_struct *tsk,__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk);return ; } -if (psecs >= soft) { +if (ptime >= softns) {/* * At the soft limit, send a SIGXCPU every second. */
@@ -936,11 +939,12 @@ static void check_process_timers(struct task_struct *tsk, }__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk);if (soft < hard) { - soft++; - sig->rlim[RLIMIT_CPU ].rlim_cur = soft; + sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; + softns +=NSEC_PER_SEC ; } } - softns = soft *NSEC_PER_SEC ; + +/* Update the expiry cache */ if (softns < pct->bases[CPUCLOCK_PROF ].nextevt) pct->bases[CPUCLOCK_PROF ].nextevt = softns; }
PATCH v2 35/38 posix-cpu-timers: Remove pointless comparisons
In reply to Thomas GleixnerThe soft RLIMIT expiry code checks whether the soft limit is greater than the hard limit. That's pointless because if the soft RLIMIT is greater than the hard RLIMIT then that code cannot be reached as the hard RLIMIT check is before that and already killed the process.
Remove it.
---
V2: Fixup vs. the previous patch changes
--- kernel/time/posix-cpu-timers.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
kernel/time/posix-cpu-timers.c +7 -9
@@ -814,15 +814,14 @@ static void check_thread_timers(struct t__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk);return ; } +if (rtim >= soft) {/* * At the soft limit, send a SIGXCPU every second. */ -if (soft < hard) { - soft +=USEC_PER_SEC ; - tsk->signal->rlim[RLIMIT_RTTIME ].rlim_cur = - soft; - } + soft +=USEC_PER_SEC ; + tsk->signal->rlim[RLIMIT_RTTIME ].rlim_cur = soft; +if (print_fatal_signals) {pr_info ("RT Watchdog Timeout (soft): %s[%d]\n" , tsk->comm,task_pid_nr (tsk));
@@ -938,10 +937,9 @@ static void check_process_timers(struct tsk->comm, task_pid_nr(tsk)); }__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); -if (soft < hard) { - sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; - softns +=NSEC_PER_SEC ; - } + + sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; + softns +=NSEC_PER_SEC ; }/* Update the expiry cache */
Re: [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons
Quoted 8 lines · Thomas Gleixner
The soft RLIMIT expiry code checks whether the soft limit is greater than the hard limit. That's pointless because if the soft RLIMIT is greater than the hard RLIMIT then that code cannot be reached as the hard RLIMIT check is before that and already killed the process.
Remove it.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Remove pointless comparisons
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: dd6702241337bcd0bae01d2644b7bae1a496d937 Gitweb: https://git.kernel.org/tip/dd6702241337bcd0bae01d2644b7bae1a496d937 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:22 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:42 +02:00
posix-cpu-timers: Remove pointless comparisons
The soft RLIMIT expiry code checks whether the soft limit is greater than the hard limit. That's pointless because if the soft RLIMIT is greater than the hard RLIMIT then that code cannot be reached as the hard RLIMIT check is before that and already killed the process.
Remove it.
--- kernel/time/posix-cpu-timers.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
kernel/time/posix-cpu-timers.c +7 -9
@@ -814,15 +814,14 @@ static void check_thread_timers(struct task_struct *tsk,__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk);return ; } +if (rtim >= soft) {/* * At the soft limit, send a SIGXCPU every second. */ -if (soft < hard) { - soft +=USEC_PER_SEC ; - tsk->signal->rlim[RLIMIT_RTTIME ].rlim_cur = - soft; - } + soft +=USEC_PER_SEC ; + tsk->signal->rlim[RLIMIT_RTTIME ].rlim_cur = soft; +if (print_fatal_signals) {pr_info ("RT Watchdog Timeout (soft): %s[%d]\n" , tsk->comm,task_pid_nr (tsk));
@@ -938,10 +937,9 @@ static void check_process_timers(struct task_struct *tsk, tsk->comm, task_pid_nr(tsk)); }__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); -if (soft < hard) { - sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; - softns +=NSEC_PER_SEC ; - } + + sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; + softns +=NSEC_PER_SEC ; }/* Update the expiry cache */
PATCH v2 36/38 posix-cpu-timers: Deduplicate rlimit handling
In reply to Thomas GleixnerBoth thread and process expiry functions have the same functionality for sending signals for soft and hard RLIMITs duplicated in 4 different ways.
Split it out into a common function and cleanup the callsites.
---
V2: Restore the dropped (u64) casts
--- kernel/time/posix-cpu-timers.c | 67 +++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 42 deletions(-)
kernel/time/posix-cpu-timers.c +25 -42
@@ -772,6 +772,20 @@ static inline void check_dl_overrun(stru } } +static bool check_rlimit (u64 time,u64 limit,int signo,bool rt,bool hard) +{ +if (time < limit) +return false; + +if (print_fatal_signals) { +pr_info ("%s Watchdog Timeout (%s): %s[%d]\n" , + rt ?"RT" :"CPU" , hard ?"hard" :"soft" , + current->comm,task_pid_nr (current)); + } +__group_send_sig_info (signo,SEND_SIG_PRIV , current); +return true; +} +/* * Check for any per-thread CPU timers that have fired and move them off * the tsk->cpu_timers[N] list onto the firing list. Here we update the
@@ -799,34 +813,18 @@ static void check_thread_timers(struct t soft =task_rlimit (tsk,RLIMIT_RTTIME );if (soft !=RLIM_INFINITY ) {/* Task RT timeout is accounted in jiffies. RTTIME is usec */ -unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC /HZ ); +unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC /HZ );unsigned long hard =task_rlimit_max (tsk,RLIMIT_RTTIME ); -if (hard !=RLIM_INFINITY && rtim >= hard) { -/* -* At the hard limit, we just die. -* No need to calculate anything else now. -*/ -if (print_fatal_signals) { -pr_info ("CPU Watchdog Timeout (hard): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk); +/* At the hard limit, send SIGKILL. No further action. */ +if (hard !=RLIM_INFINITY && +check_rlimit (rttime, hard,SIGKILL , true, true))return ; - } -if (rtim >= soft) { -/* -* At the soft limit, send a SIGXCPU every second. -*/ +/* At the soft limit, send a SIGXCPU every second */ +if (check_rlimit (rttime, soft,SIGXCPU , true, false)) { soft +=USEC_PER_SEC ; tsk->signal->rlim[RLIMIT_RTTIME ].rlim_cur = soft; - -if (print_fatal_signals) { -pr_info ("RT Watchdog Timeout (soft): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); } }
@@ -916,28 +914,13 @@ static void check_process_timers(structu64 softns = (u64 )soft *NSEC_PER_SEC ;u64 hardns = (u64 )hard *NSEC_PER_SEC ; -if (hard !=RLIM_INFINITY && ptime >= hardns) { -/* -* At the hard limit, we just die. -* No need to calculate anything else now. -*/ -if (print_fatal_signals) { -pr_info ("RT Watchdog Timeout (hard): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk); +/* At the hard limit, send SIGKILL. No further action. */ +if (hard !=RLIM_INFINITY && +check_rlimit (ptime, hardns,SIGKILL , false, true))return ; - } -if (ptime >= softns) { -/* -* At the soft limit, send a SIGXCPU every second. -*/ -if (print_fatal_signals) { -pr_info ("CPU Watchdog Timeout (soft): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); +/* At the soft limit, send a SIGXCPU every second */ +if (check_rlimit (ptime, softns,SIGXCPU , false, false)) { sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; softns +=NSEC_PER_SEC ; }
Re: [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling
Quoted 7 lines · Thomas Gleixner
Both thread and process expiry functions have the same functionality for sending signals for soft and hard RLIMITs duplicated in 4 different ways.
Split it out into a common function and cleanup the callsites.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] posix-cpu-timers: Deduplicate rlimit handling
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 8991afe2640d05a805eba01277856e8549cdc838 Gitweb: https://git.kernel.org/tip/8991afe2640d05a805eba01277856e8549cdc838 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:23 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:42 +02:00
posix-cpu-timers: Deduplicate rlimit handling
Both thread and process expiry functions have the same functionality for sending signals for soft and hard RLIMITs duplicated in 4 different ways.
Split it out into a common function and cleanup the callsites.
--- kernel/time/posix-cpu-timers.c | 67 ++++++++++++--------------------- 1 file changed, 25 insertions(+), 42 deletions(-)
kernel/time/posix-cpu-timers.c +25 -42
@@ -772,6 +772,20 @@ static inline void check_dl_overrun(struct task_struct *tsk) } } +static bool check_rlimit (u64 time,u64 limit,int signo,bool rt,bool hard) +{ +if (time < limit) +return false; + +if (print_fatal_signals) { +pr_info ("%s Watchdog Timeout (%s): %s[%d]\n" , + rt ?"RT" :"CPU" , hard ?"hard" :"soft" , + current->comm,task_pid_nr (current)); + } +__group_send_sig_info (signo,SEND_SIG_PRIV , current); +return true; +} +/* * Check for any per-thread CPU timers that have fired and move them off * the tsk->cpu_timers[N] list onto the firing list. Here we update the
@@ -799,34 +813,18 @@ static void check_thread_timers(struct task_struct *tsk, soft =task_rlimit (tsk,RLIMIT_RTTIME );if (soft !=RLIM_INFINITY ) {/* Task RT timeout is accounted in jiffies. RTTIME is usec */ -unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC /HZ ); +unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC /HZ );unsigned long hard =task_rlimit_max (tsk,RLIMIT_RTTIME ); -if (hard !=RLIM_INFINITY && rtim >= hard) { -/* -* At the hard limit, we just die. -* No need to calculate anything else now. -*/ -if (print_fatal_signals) { -pr_info ("CPU Watchdog Timeout (hard): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk); +/* At the hard limit, send SIGKILL. No further action. */ +if (hard !=RLIM_INFINITY && +check_rlimit (rttime, hard,SIGKILL , true, true))return ; - } -if (rtim >= soft) { -/* -* At the soft limit, send a SIGXCPU every second. -*/ +/* At the soft limit, send a SIGXCPU every second */ +if (check_rlimit (rttime, soft,SIGXCPU , true, false)) { soft +=USEC_PER_SEC ; tsk->signal->rlim[RLIMIT_RTTIME ].rlim_cur = soft; - -if (print_fatal_signals) { -pr_info ("RT Watchdog Timeout (soft): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); } }
@@ -916,28 +914,13 @@ static void check_process_timers(struct task_struct *tsk,u64 softns = (u64 )soft *NSEC_PER_SEC ;u64 hardns = (u64 )hard *NSEC_PER_SEC ; -if (hard !=RLIM_INFINITY && ptime >= hardns) { -/* -* At the hard limit, we just die. -* No need to calculate anything else now. -*/ -if (print_fatal_signals) { -pr_info ("RT Watchdog Timeout (hard): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGKILL ,SEND_SIG_PRIV , tsk); +/* At the hard limit, send SIGKILL. No further action. */ +if (hard !=RLIM_INFINITY && +check_rlimit (ptime, hardns,SIGKILL , false, true))return ; - } -if (ptime >= softns) { -/* -* At the soft limit, send a SIGXCPU every second. -*/ -if (print_fatal_signals) { -pr_info ("CPU Watchdog Timeout (soft): %s[%d]\n" , - tsk->comm,task_pid_nr (tsk)); - } -__group_send_sig_info (SIGXCPU ,SEND_SIG_PRIV , tsk); +/* At the soft limit, send a SIGXCPU every second */ +if (check_rlimit (ptime, softns,SIGXCPU , false, false)) { sig->rlim[RLIMIT_CPU ].rlim_cur = soft +1 ; softns +=NSEC_PER_SEC ; }
PATCH v2 37/38 posix-cpu-timers: Move state tracking to struct posix_cputimers
In reply to Thomas GleixnerPut it where it belongs and clean up the ifdeffery in fork completely.
---
V2: Adopt to the per clock base struct
--- include/linux/posix-timers.h | 8 ++++ include/linux/sched/cputime.h | 9 +++-- include/linux/sched/signal.h | 6 --- init/init_task.c | 2 - kernel/fork.c | 6 --- kernel/time/posix-cpu-timers.c | 73 ++++++++++++++++++++++------------------- 6 files changed, 54 insertions(+), 50 deletions(-)
include/linux/posix-timers.h +8 -0
@@ -77,15 +77,23 @@ struct posix_cputimer_base {/** * posix_cputimers - Container for posix CPU timer related data * @bases: Base container for posix CPU clocks +* @timers_active: Timers are queued. +* @expiry_active: Timer expiry is active. Used for +* process wide timers to avoid multiple +* task trying to handle expiry concurrently * * Used in task_struct and signal_struct */ struct posix_cputimers {struct posix_cputimer_base bases[CPUCLOCK_MAX ]; +unsigned int timers_active; +unsigned int expiry_active; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { + pct->timers_active =0 ; + pct->expiry_active =0 ; pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ;
include/linux/sched/cputime.h +6 -3
@@ -70,7 +70,7 @@ void thread_group_sample_cputime(struct*/ /** -* get_running_cputimer - return &tsk->signal->cputimer if cputimer is running +* get_running_cputimer - return &tsk->signal->cputimer if cputimers are active * * @tsk: Pointer to target task. */
@@ -80,8 +80,11 @@ struct thread_group_cputimer *get_runnin {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; -/* Check if cputimer isn't running. This is accessed without locking. */ -if (!READ_ONCE (cputimer->running)) +/* +* Check whether posix CPU timers are active. If not the thread +* group accounting is not active either. Lockless check. +*/ +if (!READ_ONCE (tsk->signal->posix_cputimers.timers_active))return NULL ;/*
include/linux/sched/signal.h +0 -6
@@ -57,18 +57,12 @@ struct task_cputime_atomic {/** * struct thread_group_cputimer - thread group interval timer counts * @cputime_atomic: atomic thread group interval timers. -* @running: true when there are timers running and -* @cputime_atomic receives updates. -* @checking_timer: true when a thread in the group is in the -* process of checking for thread group timers. * * This structure contains the version of task_cputime, above, that is * used for thread group CPU timer calculations. */ struct thread_group_cputimer {struct task_cputime_atomic cputime_atomic; -bool running; -bool checking_timer; };struct multiprocess_signals {
init/init_task.c +0 -2
@@ -30,8 +30,6 @@ static struct signal_struct init_signals .posix_timers = LIST_HEAD_INIT(init_signals.posix_timers), .cputimer = { .cputime_atomic = INIT_CPUTIME_ATOMIC, - .running = false, - .checking_timer = false, },#endif INIT_CPU_TIMERS (init_signals)
kernel/fork.c +0 -6
@@ -1517,7 +1517,6 @@ void __cleanup_sighand(struct sighand_st } } -#ifdef CONFIG_POSIX_TIMERS /* * Initialize POSIX timer handling for a thread group. */
@@ -1528,12 +1527,7 @@ static void posix_cpu_timers_init_group( cpu_limit =READ_ONCE (sig->rlim[RLIMIT_CPU ].rlim_cur);posix_cputimers_group_init (pct, cpu_limit); -if (cpu_limit !=RLIM_INFINITY ) - sig->cputimer.running = true; } -#else -static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { } -#endif static int copy_signal (unsigned long clone_flags,struct task_struct *tsk) {
kernel/time/posix-cpu-timers.c +40 -33
160 lines not on this page · raw message
Frederic Weisbecker
maintainerRe: [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers
Quoted 17 lines · Thomas Gleixner
Put it where it belongs and clean up the ifdeffery in fork completely.
Signed-off-by Thomas Gleixner <[email protected]>---
V2: Adopt to the per clock base struct--- include/linux/posix-timers.h | 8 ++++ include/linux/sched/cputime.h | 9 +++-- include/linux/sched/signal.h | 6 --- init/init_task.c | 2 - kernel/fork.c | 6 --- kernel/time/posix-cpu-timers.c | 73 ++++++++++++++++++++++------------------- 6 files changed, 54 insertions(+), 50 deletions(-)
include/linux/posix-timers.h struct posix_cputimer_base { · line 83
Quoted 7 lines
include/linux/posix-timers.h +4
-0@@ -77,15 +77,23 @@ struct posix_cputimer_base {/** * posix_cputimers - Container for posix CPU timer related data * @bases: Base container for posix CPU clocks +* @timers_active: Timers are queued. +* @expiry_active: Timer expiry is active. Used for +* process wide timers to avoid multiple +* task trying to handle expiry concurrently
So those two fields are also added to struct task_struct but unused there, right?
Quoted 8 lines
include/linux/posix-timers.h +2
-0* * Used in task_struct and signal_struct */ struct posix_cputimers {struct posix_cputimer_base bases[CPUCLOCK_MAX ]; +unsigned int timers_active; +unsigned int expiry_active; };
Re: [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers
Quoted 15 lines · Frederic Weisbecker
Quoted 14 lines · Thomas Gleixner
Put it where it belongs and clean up the ifdeffery in fork completely.
Signed-off-by Thomas Gleixner <[email protected]>---
V2: Adopt to the per clock base struct--- include/linux/posix-timers.h | 8 ++++ include/linux/sched/cputime.h | 9 +++-- include/linux/sched/signal.h | 6 --- init/init_task.c | 2 - kernel/fork.c | 6 --- kernel/time/posix-cpu-timers.c | 73 ++++++++++++++++++++++------------------- 6 files changed, 54 insertions(+), 50 deletions(-)
Quoted 13 lines
include/linux/posix-timers.h struct posix_cputimer_base { · line 83
Quoted 10 lines
include/linux/posix-timers.h +4
-0@@ -77,15 +77,23 @@ struct posix_cputimer_base {/** * posix_cputimers - Container for posix CPU timer related data * @bases: Base container for posix CPU clocks +* @timers_active: Timers are queued. +* @expiry_active: Timer expiry is active. Used for +* process wide timers to avoid multiple +* task trying to handle expiry concurrently So those two fields are also added to struct
task_structbut unused there, right?
Yes. I did not come up with a smart way to avoid that, but lemme think about it some more.
Thanks,
tglx
[tip: timers/core] posix-cpu-timers: Move state tracking to struct posix_cputimers
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 244d49e30653658d4e7e9b2b8427777cbbc5affe Gitweb: https://git.kernel.org/tip/244d49e30653658d4e7e9b2b8427777cbbc5affe Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:24 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:42 +02:00
posix-cpu-timers: Move state tracking to struct posix_cputimers
Put it where it belongs and clean up the ifdeffery in fork completely.
--- include/linux/posix-timers.h | 8 ++++- include/linux/sched/cputime.h | 9 ++-- include/linux/sched/signal.h | 6 +--- init/init_task.c | 2 +- kernel/fork.c | 6 +--- kernel/time/posix-cpu-timers.c | 73 ++++++++++++++++++--------------- 6 files changed, 54 insertions(+), 50 deletions(-)
include/linux/posix-timers.h +8 -0
@@ -77,15 +77,23 @@ struct posix_cputimer_base {/** * posix_cputimers - Container for posix CPU timer related data * @bases: Base container for posix CPU clocks +* @timers_active: Timers are queued. +* @expiry_active: Timer expiry is active. Used for +* process wide timers to avoid multiple +* task trying to handle expiry concurrently * * Used in task_struct and signal_struct */ struct posix_cputimers {struct posix_cputimer_base bases[CPUCLOCK_MAX ]; +unsigned int timers_active; +unsigned int expiry_active; };static inline void posix_cputimers_init (struct posix_cputimers *pct) { + pct->timers_active =0 ; + pct->expiry_active =0 ; pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ;
include/linux/sched/cputime.h +6 -3
@@ -70,7 +70,7 @@ void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples);*/ /** -* get_running_cputimer - return &tsk->signal->cputimer if cputimer is running +* get_running_cputimer - return &tsk->signal->cputimer if cputimers are active * * @tsk: Pointer to target task. */
@@ -80,8 +80,11 @@ struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk) {struct thread_group_cputimer *cputimer = &tsk->signal->cputimer; -/* Check if cputimer isn't running. This is accessed without locking. */ -if (!READ_ONCE (cputimer->running)) +/* +* Check whether posix CPU timers are active. If not the thread +* group accounting is not active either. Lockless check. +*/ +if (!READ_ONCE (tsk->signal->posix_cputimers.timers_active))return NULL ;/*
include/linux/sched/signal.h +0 -6
@@ -57,18 +57,12 @@ struct task_cputime_atomic {/** * struct thread_group_cputimer - thread group interval timer counts * @cputime_atomic: atomic thread group interval timers. -* @running: true when there are timers running and -* @cputime_atomic receives updates. -* @checking_timer: true when a thread in the group is in the -* process of checking for thread group timers. * * This structure contains the version of task_cputime, above, that is * used for thread group CPU timer calculations. */ struct thread_group_cputimer {struct task_cputime_atomic cputime_atomic; -bool running; -bool checking_timer; };struct multiprocess_signals {
init/init_task.c +0 -2
@@ -30,8 +30,6 @@ static struct signal_struct init_signals = { .posix_timers = LIST_HEAD_INIT(init_signals.posix_timers), .cputimer = { .cputime_atomic = INIT_CPUTIME_ATOMIC, - .running = false, - .checking_timer = false, },#endif INIT_CPU_TIMERS (init_signals)
kernel/fork.c +0 -6
@@ -1517,7 +1517,6 @@ void __cleanup_sighand(struct sighand_struct *sighand) } } -#ifdef CONFIG_POSIX_TIMERS /* * Initialize POSIX timer handling for a thread group. */
@@ -1528,12 +1527,7 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig) cpu_limit =READ_ONCE (sig->rlim[RLIMIT_CPU ].rlim_cur);posix_cputimers_group_init (pct, cpu_limit); -if (cpu_limit !=RLIM_INFINITY ) - sig->cputimer.running = true; } -#else -static inline void posix_cpu_timers_init_group (struct signal_struct *sig) { } -#endif static int copy_signal (unsigned long clone_flags,struct task_struct *tsk) {
kernel/time/posix-cpu-timers.c +40 -33
160 lines not on this page · raw message
PATCH v2 38/38 posix-cpu-timers: Utilize timerqueue for storage
In reply to Thomas GleixnerUsing a linear O(N) search for timer insertion affects execution time and D-cache footprint badly with a larger number of timers.
Switch the storage to a timerqueue which is already used for hrtimers and alarmtimers. It does not affect the size of struct k_itimer as it.alarm is still larger.
The extra list head for the expiry list will go away later once the expiry is moved into task work context.
---
V2: Adopt to the per clock base struct
--- include/linux/posix-timers.h | 65 ++++++++++---- include/linux/timerqueue.h | 10 ++ kernel/time/posix-cpu-timers.c | 183 ++++++++++++++++++++--------------------- 3 files changed, 150 insertions(+), 108 deletions(-)
include/linux/posix-timers.h +49 -16
@@ -5,17 +5,11 @@#include <linux/spinlock.h> #include <linux/list.h> #include <linux/alarmtimer.h> +#include <linux/timerqueue.h> struct kernel_siginfo ;struct task_struct ; -struct cpu_timer_list { -struct list_head entry; -u64 expires; -struct task_struct *task; -int firing; -}; -/* * Bit fields within a clockid: *
@@ -65,13 +59,57 @@ static inline int clockid_to_fd(const cl#ifdef CONFIG_POSIX_TIMERS /** +* cpu_timer - Posix CPU timer representation for k_itimer +* @node: timerqueue node to queue in the task/sig +* @head: timerqueue head on which this timer is queued +* @task: Pointer to target task +* @elist: List head for the expiry list +* @firing: Timer is currently firing +*/ +struct cpu_timer { +struct timerqueue_node node; +struct timerqueue_head *head; +struct task_struct *task; +struct list_head elist; +int firing; +}; + +static inline bool cpu_timer_requeue (struct cpu_timer *ctmr) +{ +return timerqueue_add (ctmr->head, &ctmr->node); +} + +static inline bool cpu_timer_enqueue (struct timerqueue_head *head, +struct cpu_timer *ctmr) +{ + ctmr->head = head; +return timerqueue_add (head, &ctmr->node); +} + +static inline void cpu_timer_dequeue (struct cpu_timer *ctmr) +{ +if (!RB_EMPTY_NODE (&ctmr->node.node)) +timerqueue_del (ctmr->head, &ctmr->node); +} + +static inline u64 cpu_timer_getexpires (struct cpu_timer *ctmr) +{ +return ctmr->node.expires; +} + +static inline void cpu_timer_setexpires (struct cpu_timer *ctmr,u64 exp) +{ + ctmr->node.expires = exp; +} + +/** * posix_cputimer_base - Container per posix CPU clock * @nextevt: Earliest-expiration cache -* @cpu_timers: List heads to queue posix CPU timers +* @tqhead: timerqueue head for cpu_timers */ struct posix_cputimer_base {u64 nextevt; -struct list_head cpu_timers; +struct timerqueue_head tqhead; };/**
@@ -92,14 +130,10 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ; +memset (pct->bases,0 ,sizeof (pct->bases)); pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ; -INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit);
@@ -113,7 +147,6 @@ static inline void posix_cputimers_rt_wa/* Init task static initializer */ #define INIT_CPU_TIMERBASE (b) { \ .nextevt = U64_MAX, \ - .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ }#define INIT_CPU_TIMERBASES (b) { \
@@ -182,7 +215,7 @@ struct k_itimer {struct {struct hrtimer timer; } real; -struct cpu_timer_list cpu; +struct cpu_timer cpu;struct {struct alarm alarmtimer; } alarm;
include/linux/timerqueue.h +10 -0
@@ -43,6 +43,16 @@ static inline void timerqueue_init(strucRB_CLEAR_NODE (&node->node); } +static inline bool timerqueue_node_queued (struct timerqueue_node *node) +{ +return !RB_EMPTY_NODE (&node->node); +} + +static inline bool timerqueue_node_expires (struct timerqueue_node *node) +{ +return node->expires; +} +static inline void timerqueue_init_head (struct timerqueue_head *head) { head->rb_root =RB_ROOT_CACHED ;
kernel/time/posix-cpu-timers.c +91 -92
396 lines not on this page · raw message
Frederic Weisbecker
maintainerRe: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
include/linux/posix-timers.h struct posix_cputimers { · line 96
Quoted 7 lines · Thomas Gleixner
/**
include/linux/posix-timers.h +0
-2@@ -92,14 +130,10 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ;
No more need to initialize these?
Quoted 8 lines
include/linux/posix-timers.h +1
-3+memset (pct->bases,0 ,sizeof (pct->bases)); pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ; -INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }
[...]
kernel/time/posix-cpu-timers.c static int posix_cpu_timer_del(struct k_ · line 401
Quoted 11 lines
kernel/time/posix-cpu-timers.c +3
-3@@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_ sighand =lock_task_sighand (p, &flags);if (unlikely (sighand ==NULL )) {/* -* We raced with the reaping of the task. -* The deletion should have cleared us off the list. +* This raced with the reaping of the task. The exit cleanup +* should have removed this timer from the timer queue. */ -WARN_ON_ONCE (!list_empty (&timer->it.cpu.entry)); +WARN_ON_ONCE (ctmr->head ||timerqueue_node_queued (&ctmr->node));
Should we clear ctmr->head upon cleanup_timerqueue() ?
Thanks.
Quoted 24 lines
kernel/time/posix-cpu-timers.c +5
-5}else {if (timer->it.cpu.firing) ret =TIMER_RETRY ;else -list_del (&timer->it.cpu.entry); +cpu_timer_dequeue (ctmr);unlock_task_sighand (p, &flags); }@@ -412,12 +414,12 @@ static int posix_cpu_timer_del(struct k_return ret; } -static void cleanup_timers_list (struct list_head *head) +static void cleanup_timerqueue (struct timerqueue_head *head) { -struct cpu_timer_list *timer, *next; +struct timerqueue_node *node; -list_for_each_entry_safe (timer, next, head, entry) -list_del_init (&timer->entry); +while ((node =timerqueue_getnext (head))) +timerqueue_del (head, node); }
Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
Quoted 4 lines · Frederic Weisbecker
Quoted 3 lines · Thomas Gleixner
/**
(quoted diff) +0
-0@@ -92,14 +130,10 @@ struct posix_cputimers {
Quoted 8 lines
include/linux/posix-timers.h struct posix_cputimers { · line 96
Quoted 4 lines
include/linux/posix-timers.h +0
-2static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ;No more need to initialize these?
include/linux/posix-timers.h struct posix_cputimers { · line 133
Quoted 1 line
include/linux/posix-timers.h +1
-0+memset (pct->bases,0 ,sizeof (pct->bases));
memset() does that IIRC :)
Quoted 10 lines
Quoted 7 lines
include/linux/posix-timers.h +0
-3pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ; -INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }[...]
Quoted 13 lines
kernel/time/posix-cpu-timers.c static int posix_cpu_timer_del(struct k_ · line 401
Quoted 11 lines
kernel/time/posix-cpu-timers.c +3
-3@@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_ sighand =lock_task_sighand (p, &flags);if (unlikely (sighand ==NULL )) {/* -* We raced with the reaping of the task. -* The deletion should have cleared us off the list. +* This raced with the reaping of the task. The exit cleanup +* should have removed this timer from the timer queue. */ -WARN_ON_ONCE (!list_empty (&timer->it.cpu.entry)); +WARN_ON_ONCE (ctmr->head ||timerqueue_node_queued (&ctmr->node));Should we clear
ctmr->headuponcleanup_timerqueue()?
Probably.
Frederic Weisbecker
maintainerRe: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
Quoted 13 lines · Thomas Gleixner
Quoted 11 lines · Frederic Weisbecker
include/linux/posix-timers.h struct posix_cputimers { · line 96
Quoted 7 lines · Thomas Gleixner
/**
include/linux/posix-timers.h +0
-2@@ -92,14 +130,10 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ;No more need to initialize these?
Quoted 3 lines
Quoted 1 line
include/linux/posix-timers.h struct posix_cputimers { · line 133
Quoted 1 line
include/linux/posix-timers.h +1
-0+memset (pct->bases,0 ,sizeof (pct->bases));
memset()does that IIRC :)
But those two fields aren't part of pct->bases, are they? :)
Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
Quoted 14 lines · Frederic Weisbecker
Quoted 13 lines · Thomas Gleixner
Quoted 11 lines · Frederic Weisbecker
include/linux/posix-timers.h struct posix_cputimers { · line 96
Quoted 7 lines · Thomas Gleixner
/**
include/linux/posix-timers.h +0
-2@@ -92,14 +130,10 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ;No more need to initialize these?
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
include/linux/posix-timers.h struct posix_cputimers { · line 133
Quoted 1 line
include/linux/posix-timers.h +1
-0+memset (pct->bases,0 ,sizeof (pct->bases));
memset()does that IIRC :)But those two fields aren't part of
pct->bases, are they? :)
Duh. I wanted to memset() the full pile obviously.
PATCH v3 38/38 posix-cpu-timers: Utilize timerqueue for storage
Using a linear O(N) search for timer insertion affects execution time and D-cache footprint badly with a larger number of timers.
Switch the storage to a timerqueue which is already used for hrtimers and alarmtimers. It does not affect the size of struct k_itimer as it.alarm is still larger.
The extra list head for the expiry list will go away later once the expiry is moved into task work context.
---
V2: Adopt to the per clock base struct
V3: Fixup memset() and clear cputtimer::head in cleanup_timerqueue()
--- include/linux/posix-timers.h | 65 ++++++++++---- include/linux/timerqueue.h | 10 ++ kernel/time/posix-cpu-timers.c | 187 ++++++++++++++++++++--------------------- 3 files changed, 154 insertions(+), 108 deletions(-)
include/linux/posix-timers.h +49 -16
@@ -5,17 +5,11 @@#include <linux/spinlock.h> #include <linux/list.h> #include <linux/alarmtimer.h> +#include <linux/timerqueue.h> struct kernel_siginfo ;struct task_struct ; -struct cpu_timer_list { -struct list_head entry; -u64 expires; -struct task_struct *task; -int firing; -}; -/* * Bit fields within a clockid: *
@@ -65,13 +59,57 @@ static inline int clockid_to_fd(const cl#ifdef CONFIG_POSIX_TIMERS /** +* cpu_timer - Posix CPU timer representation for k_itimer +* @node: timerqueue node to queue in the task/sig +* @head: timerqueue head on which this timer is queued +* @task: Pointer to target task +* @elist: List head for the expiry list +* @firing: Timer is currently firing +*/ +struct cpu_timer { +struct timerqueue_node node; +struct timerqueue_head *head; +struct task_struct *task; +struct list_head elist; +int firing; +}; + +static inline bool cpu_timer_requeue (struct cpu_timer *ctmr) +{ +return timerqueue_add (ctmr->head, &ctmr->node); +} + +static inline bool cpu_timer_enqueue (struct timerqueue_head *head, +struct cpu_timer *ctmr) +{ + ctmr->head = head; +return timerqueue_add (head, &ctmr->node); +} + +static inline void cpu_timer_dequeue (struct cpu_timer *ctmr) +{ +if (!RB_EMPTY_NODE (&ctmr->node.node)) +timerqueue_del (ctmr->head, &ctmr->node); +} + +static inline u64 cpu_timer_getexpires (struct cpu_timer *ctmr) +{ +return ctmr->node.expires; +} + +static inline void cpu_timer_setexpires (struct cpu_timer *ctmr,u64 exp) +{ + ctmr->node.expires = exp; +} + +/** * posix_cputimer_base - Container per posix CPU clock * @nextevt: Earliest-expiration cache -* @cpu_timers: List heads to queue posix CPU timers +* @tqhead: timerqueue head for cpu_timers */ struct posix_cputimer_base {u64 nextevt; -struct list_head cpu_timers; +struct timerqueue_head tqhead; };/**
@@ -92,14 +130,10 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ; +memset (pct,0 ,sizeof (*pct)); pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ; -INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit);
@@ -113,7 +147,6 @@ static inline void posix_cputimers_rt_wa/* Init task static initializer */ #define INIT_CPU_TIMERBASE (b) { \ .nextevt = U64_MAX, \ - .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ }#define INIT_CPU_TIMERBASES (b) { \
@@ -182,7 +215,7 @@ struct k_itimer {struct {struct hrtimer timer; } real; -struct cpu_timer_list cpu; +struct cpu_timer cpu;struct {struct alarm alarmtimer; } alarm;
include/linux/timerqueue.h +10 -0
@@ -43,6 +43,16 @@ static inline void timerqueue_init(strucRB_CLEAR_NODE (&node->node); } +static inline bool timerqueue_node_queued (struct timerqueue_node *node) +{ +return !RB_EMPTY_NODE (&node->node); +} + +static inline bool timerqueue_node_expires (struct timerqueue_node *node) +{ +return node->expires; +} +static inline void timerqueue_init_head (struct timerqueue_head *head) { head->rb_root =RB_ROOT_CACHED ;
kernel/time/posix-cpu-timers.c +95 -92
400 lines not on this page · raw message
Re: [patch V3 38/38] posix-cpu-timers: Utilize timerqueue for storage
Quoted 7 lines · Thomas Gleixner
Using a linear O(N) search for timer insertion affects execution time and D-cache footprint badly with a larger number of timers.
Switch the storage to a timerqueue which is already used for hrtimers and alarmtimers. It does not affect the size of struct
k_itimeras it.alarm is still larger.
Quoted 7 lines
The extra list head for the expiry list will go away later once the expiry is moved into task work context.
Signed-off-by Thomas Gleixner <[email protected]>---
V2: Adopt to the per clock base struct
V3: Fixupmemset()and clearcputtimer::headincleanup_timerqueue()
[tip: timers/core] posix-cpu-timers: Utilize timerqueue for storage
In reply to Thomas GleixnerThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 60bda037f1dd8151e0c9ee5b09f0c091a0f643cd Gitweb: https://git.kernel.org/tip/60bda037f1dd8151e0c9ee5b09f0c091a0f643cd Author: Thomas Gleixner <[email protected]> AuthorDate: Tue, 27 Aug 2019 21:31:02 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:43 +02:00
posix-cpu-timers: Utilize timerqueue for storage
Using a linear O(N) search for timer insertion affects execution time and D-cache footprint badly with a larger number of timers.
Switch the storage to a timerqueue which is already used for hrtimers and alarmtimers. It does not affect the size of struct k_itimer as it.alarm is still larger.
The extra list head for the expiry list will go away later once the expiry is moved into task work context.
--- include/linux/posix-timers.h | 65 ++++++++--- include/linux/timerqueue.h | 10 ++- kernel/time/posix-cpu-timers.c | 189 ++++++++++++++++---------------- 3 files changed, 155 insertions(+), 109 deletions(-)
include/linux/posix-timers.h +49 -16
@@ -5,17 +5,11 @@#include <linux/spinlock.h> #include <linux/list.h> #include <linux/alarmtimer.h> +#include <linux/timerqueue.h> struct kernel_siginfo ;struct task_struct ; -struct cpu_timer_list { -struct list_head entry; -u64 expires; -struct task_struct *task; -int firing; -}; -/* * Bit fields within a clockid: *
@@ -65,13 +59,57 @@ static inline int clockid_to_fd(const clockid_t clk)#ifdef CONFIG_POSIX_TIMERS /** +* cpu_timer - Posix CPU timer representation for k_itimer +* @node: timerqueue node to queue in the task/sig +* @head: timerqueue head on which this timer is queued +* @task: Pointer to target task +* @elist: List head for the expiry list +* @firing: Timer is currently firing +*/ +struct cpu_timer { +struct timerqueue_node node; +struct timerqueue_head *head; +struct task_struct *task; +struct list_head elist; +int firing; +}; + +static inline bool cpu_timer_requeue (struct cpu_timer *ctmr) +{ +return timerqueue_add (ctmr->head, &ctmr->node); +} + +static inline bool cpu_timer_enqueue (struct timerqueue_head *head, +struct cpu_timer *ctmr) +{ + ctmr->head = head; +return timerqueue_add (head, &ctmr->node); +} + +static inline void cpu_timer_dequeue (struct cpu_timer *ctmr) +{ +if (!RB_EMPTY_NODE (&ctmr->node.node)) +timerqueue_del (ctmr->head, &ctmr->node); +} + +static inline u64 cpu_timer_getexpires (struct cpu_timer *ctmr) +{ +return ctmr->node.expires; +} + +static inline void cpu_timer_setexpires (struct cpu_timer *ctmr,u64 exp) +{ + ctmr->node.expires = exp; +} + +/** * posix_cputimer_base - Container per posix CPU clock * @nextevt: Earliest-expiration cache -* @cpu_timers: List heads to queue posix CPU timers +* @tqhead: timerqueue head for cpu_timers */ struct posix_cputimer_base {u64 nextevt; -struct list_head cpu_timers; +struct timerqueue_head tqhead; };/**
@@ -92,14 +130,10 @@ struct posix_cputimers {static inline void posix_cputimers_init (struct posix_cputimers *pct) { - pct->timers_active =0 ; - pct->expiry_active =0 ; +memset (pct,0 ,sizeof (*pct)); pct->bases[0 ].nextevt =U64_MAX ; pct->bases[1 ].nextevt =U64_MAX ; pct->bases[2 ].nextevt =U64_MAX ; -INIT_LIST_HEAD (&pct->bases[0 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[1 ].cpu_timers); -INIT_LIST_HEAD (&pct->bases[2 ].cpu_timers); }void posix_cputimers_group_init (struct posix_cputimers *pct,u64 cpu_limit);
@@ -113,7 +147,6 @@ static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,/* Init task static initializer */ #define INIT_CPU_TIMERBASE (b) { \ .nextevt = U64_MAX, \ - .cpu_timers = LIST_HEAD_INIT(b.cpu_timers), \ }#define INIT_CPU_TIMERBASES (b) { \
@@ -182,7 +215,7 @@ struct k_itimer {struct {struct hrtimer timer; } real; -struct cpu_timer_list cpu; +struct cpu_timer cpu;struct {struct alarm alarmtimer; } alarm;
include/linux/timerqueue.h +10 -0
@@ -43,6 +43,16 @@ static inline void timerqueue_init(struct timerqueue_node *node)RB_CLEAR_NODE (&node->node); } +static inline bool timerqueue_node_queued (struct timerqueue_node *node) +{ +return !RB_EMPTY_NODE (&node->node); +} + +static inline bool timerqueue_node_expires (struct timerqueue_node *node) +{ +return node->expires; +} +static inline void timerqueue_init_head (struct timerqueue_head *head) { head->rb_root =RB_ROOT_CACHED ;
kernel/time/posix-cpu-timers.c +96 -93
401 lines not on this page · raw message
Quoted 7 lines
The series applies on top of:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gittimers/coreand is available from git as well:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitWIP.timers/core
Btw, for some reason git here seems to be very unhappy about that remote:
Fetching tip
error: cannot lock ref 'refs/remotes/tip/WIP.timers/core': 'refs/remotes/tip/WIP.timers' exists; cannot create 'refs/remotes/tip/WIP.timers/core' From https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
! [new branch] WIP.timers/core -> tip/WIP.timers/core (unable to update local ref)
error: Could not fetch tip
which repeats every time I fetch. I can't of anythign particular on my side that would cause this.
Frederic Weisbecker
maintainerQuoted 10 lines · Christoph Hellwig
Quoted 7 lines
The series applies on top of:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gittimers/coreand is available from git as well:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.gitWIP.timers/coreBtw, for some reason git here seems to be very unhappy about that remote:
Quoted 8 lines
Fetching tip
error: cannot lock ref 'refs/remotes/tip/WIP.timers/core': 'refs/remotes/tip/WIP.timers' exists; cannot create 'refs/remotes/tip/WIP.timers/core' From https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
! [new branch] WIP.timers/core -> tip/WIP.timers/core (unable to update local ref)
error: Could not fetch tipwhich repeats every time I fetch. I can't of anythign particular on my side that would cause this.
Yeah I had to run "git remote prune tip" and fetch again.
Apparently there was an old remote branch tip/WIP.timers and git seem to refuse to have a new subpath branch.
Quoted 7 lines · Frederic Weisbecker
Quoted 2 lines
which repeats every time I fetch. I can't of anythign particular on my side that would cause this.
Yeah I had to run "git remote prune tip" and fetch again.
Apparently there was an old remote branch tip/WIP.timers and git seem to refuse to have a new subpath branch.
Thanks, that seems to have fixed the issue for me.
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [patch V2 18/38] sched: Move struct task_cputime to types.h
Quoted 3 lines · Thomas Gleixner
For upcoming posix-timer changes to avoid include recursion hell.
Signed-off-by Thomas Gleixner <[email protected]>
[tip: timers/core] sched: Move struct task_cputime to types.h
In reply to a message not in the archiveThe following commit has been merged into the timers/core branch of tip:
The following commit has been merged into the timers/core branch of tip:
Commit-ID: 9eacb5c7e6607aba00a7322b21cad83fc8b101c8 Gitweb: https://git.kernel.org/tip/9eacb5c7e6607aba00a7322b21cad83fc8b101c8 Author: Thomas Gleixner <[email protected]> AuthorDate: Wed, 21 Aug 2019 21:09:05 +02:00 Committer: Thomas Gleixner <[email protected]> CommitterDate: Wed, 28 Aug 2019 11:50:34 +02:00
sched: Move struct task_cputime to types.h
For upcoming posix-timer changes to avoid include recursion hell.
--- include/linux/sched.h | 17 +---------------- include/linux/sched/types.h | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 include/linux/sched/types.h
include/linux/sched.h +1 -16
@@ -25,6 +25,7 @@#include <linux/resource.h> #include <linux/latencytop.h> #include <linux/sched/prio.h> +#include <linux/sched/types.h> #include <linux/signal_types.h> #include <linux/mm_types_task.h> #include <linux/task_io_accounting.h>
@@ -245,22 +246,6 @@ struct prev_cputime {#endif }; -/** -* struct task_cputime - collected CPU time counts -* @utime: time spent in user mode, in nanoseconds -* @stime: time spent in kernel mode, in nanoseconds -* @sum_exec_runtime: total time spent on the CPU, in nanoseconds -* -* This structure groups together three kinds of CPU time that are tracked for -* threads and thread groups. Most things considering CPU time want to group -* these counts together and treat all three of them in parallel. -*/ -struct task_cputime { -u64 utime; -u64 stime; -unsigned long long sum_exec_runtime; -}; -/* Alternate field names when used on cache expirations: */ #define virt_exp utime#define prof_exp stime
include/linux/sched/types.h new file +23 -0
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_SCHED_TYPES_H +#define _LINUX_SCHED_TYPES_H + +#include <linux/types.h> + +/** +* struct task_cputime - collected CPU time counts +* @utime: time spent in user mode, in nanoseconds +* @stime: time spent in kernel mode, in nanoseconds +* @sum_exec_runtime: total time spent on the CPU, in nanoseconds +* +* This structure groups together three kinds of CPU time that are tracked for +* threads and thread groups. Most things considering CPU time want to group +* these counts together and treat all three of them in parallel. +*/ +struct task_cputime { +u64 utime; +u64 stime; +unsigned long long sum_exec_runtime; +}; + +#endif