diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2007-02-16 04:28:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-16 11:14:00 -0500 |
commit | 1f2ea0837dbc263ce2a2512c4e73c83df68a6a55 (patch) | |
tree | 8e033c747852671f3d4d2cb0bc677dab9ecfc441 /kernel/posix-cpu-timers.c | |
parent | 7460ed2844ffad7141e30271c0c3da8336e66014 (diff) |
[PATCH] posix timers: RCU optimization for clock_gettime()
Use RCU to avoid the need to acquire tasklist_lock in the single-threaded
case of clock_gettime(). It still acquires tasklist_lock when for a
(potentially multithreaded) process. This change allows realtime
applications to frequently monitor CPU consumption of individual tasks, as
requested (and now deployed) by some off-list users.
This has been in Ingo Molnar's -rt patchset since late 2005 with no
problems reported, and tests successfully on 2.6.20-rc6, so I believe that
it is long-since ready for mainline adoption.
[paulmck@linux.vnet.ibm.com: fix exit()/posix_cpu_clock_get() race spotted by Oleg]
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/posix-cpu-timers.c')
-rw-r--r-- | kernel/posix-cpu-timers.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 7c3e1e6dfb5b..657f77697415 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c | |||
@@ -304,7 +304,7 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | |||
304 | * should be able to see it. | 304 | * should be able to see it. |
305 | */ | 305 | */ |
306 | struct task_struct *p; | 306 | struct task_struct *p; |
307 | read_lock(&tasklist_lock); | 307 | rcu_read_lock(); |
308 | p = find_task_by_pid(pid); | 308 | p = find_task_by_pid(pid); |
309 | if (p) { | 309 | if (p) { |
310 | if (CPUCLOCK_PERTHREAD(which_clock)) { | 310 | if (CPUCLOCK_PERTHREAD(which_clock)) { |
@@ -312,12 +312,17 @@ int posix_cpu_clock_get(const clockid_t which_clock, struct timespec *tp) | |||
312 | error = cpu_clock_sample(which_clock, | 312 | error = cpu_clock_sample(which_clock, |
313 | p, &rtn); | 313 | p, &rtn); |
314 | } | 314 | } |
315 | } else if (p->tgid == pid && p->signal) { | 315 | } else { |
316 | error = cpu_clock_sample_group(which_clock, | 316 | read_lock(&tasklist_lock); |
317 | p, &rtn); | 317 | if (p->tgid == pid && p->signal) { |
318 | error = | ||
319 | cpu_clock_sample_group(which_clock, | ||
320 | p, &rtn); | ||
321 | } | ||
322 | read_unlock(&tasklist_lock); | ||
318 | } | 323 | } |
319 | } | 324 | } |
320 | read_unlock(&tasklist_lock); | 325 | rcu_read_unlock(); |
321 | } | 326 | } |
322 | 327 | ||
323 | if (error) | 328 | if (error) |