[PATCH] RCU signal handling

RCU tasklist_lock and RCU signal handling: send signals RCU-read-locked
instead of tasklist_lock read-locked.  This is a scalability improvement on
SMP and a preemption-latency improvement under PREEMPT_RCU.

Signed-off-by: Paul E. McKenney <paulmck@us.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Acked-by: William Irwin <wli@holomorphy.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Ingo Molnar
2006-01-08 01:01:37 -08:00
committed by Linus Torvalds
parent 4369ef3c3e
commit e56d090310
8 changed files with 143 additions and 31 deletions

View File

@@ -34,6 +34,7 @@
#include <linux/percpu.h>
#include <linux/topology.h>
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
#include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
@@ -350,8 +351,16 @@ struct sighand_struct {
atomic_t count;
struct k_sigaction action[_NSIG];
spinlock_t siglock;
struct rcu_head rcu;
};
extern void sighand_free_cb(struct rcu_head *rhp);
static inline void sighand_free(struct sighand_struct *sp)
{
call_rcu(&sp->rcu, sighand_free_cb);
}
/*
* NOTE! "signal_struct" does not have it's own
* locking, because a shared signal_struct always
@@ -844,6 +853,7 @@ struct task_struct {
int cpuset_mems_generation;
#endif
atomic_t fs_excl; /* holding fs exclusive resources */
struct rcu_head rcu;
};
static inline pid_t process_group(struct task_struct *tsk)
@@ -867,8 +877,26 @@ static inline int pid_alive(struct task_struct *p)
extern void free_task(struct task_struct *tsk);
extern void __put_task_struct(struct task_struct *tsk);
#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
#define put_task_struct(tsk) \
do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
static inline int get_task_struct_rcu(struct task_struct *t)
{
int oldusage;
do {
oldusage = atomic_read(&t->usage);
if (oldusage == 0)
return 0;
} while (cmpxchg(&t->usage.counter, oldusage, oldusage+1) != oldusage);
return 1;
}
extern void __put_task_struct_cb(struct rcu_head *rhp);
static inline void put_task_struct(struct task_struct *t)
{
if (atomic_dec_and_test(&t->usage))
call_rcu(&t->rcu, __put_task_struct_cb);
}
/*
* Per process flags