diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-06-23 18:50:18 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-06-23 18:50:18 -0700 |
| commit | 8c1ce9d6d628945ff23f844dbe9f21f5d5383b99 (patch) | |
| tree | 030e150c11f9a3252fd7a1d0c36bd6912ff9eada /kernel | |
| parent | b659a6fbb927a79acd606c4466d03cb615879f9f (diff) | |
[PATCH] rcu: avoid passing an argument to the callback function
From: Dipankar Sarma <dipankar@in.ibm.com>
This patch changes the call_rcu() API and avoids passing an argument to the
callback function as suggested by Rusty. Instead, it is assumed that the
user has embedded the rcu head into a structure that is useful in the
callback and the rcu_head pointer is passed to the callback. The callback
can use container_of() to get the pointer to its structure and work with
it. Together with the rcu-singly-link patch, it reduces the rcu_head size
by 50%. Considering that we use these in things like struct dentry and
struct dst_entry, this is good savings in space.
An example :
struct my_struct {
struct rcu_head rcu;
int x;
int y;
};
void my_rcu_callback(struct rcu_head *head)
{
struct my_struct *p = container_of(head, struct my_struct, rcu);
free(p);
}
void my_delete(struct my_struct *p)
{
...
call_rcu(&p->rcu, my_rcu_callback);
...
}
Signed-Off-By: Dipankar Sarma <dipankar@in.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/auditsc.c | 7 | ||||
| -rw-r--r-- | kernel/rcupdate.c | 26 |
2 files changed, 20 insertions, 13 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 342b57141fd9..e688c73f6a9e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -177,9 +177,10 @@ static inline int audit_add_rule(struct audit_entry *entry, return 0; } -static void audit_free_rule(void *arg) +static void audit_free_rule(struct rcu_head *head) { - kfree(arg); + struct audit_entry *e = container_of(head, struct audit_entry, rcu); + kfree(e); } /* Note that audit_add_rule and audit_del_rule are called via @@ -195,7 +196,7 @@ static inline int audit_del_rule(struct audit_rule *rule, list_for_each_entry(e, list, list) { if (!audit_compare_rule(rule, &e->rule)) { list_del_rcu(&e->list); - call_rcu(&e->rcu, audit_free_rule, e); + call_rcu(&e->rcu, audit_free_rule); return 0; } } diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index cdb59f12a5fa..7282889a5fd9 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -68,20 +68,19 @@ static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; * call_rcu - Queue an RCU update request. * @head: structure to be used for queueing the RCU updates. * @func: actual update function to be invoked after the grace period - * @arg: argument to be passed to the update function * * The update function will be invoked as soon as all CPUs have performed * a context switch or been seen in the idle loop or in a user process. * The read-side of critical section that use call_rcu() for updation must * be protected by rcu_read_lock()/rcu_read_unlock(). */ -void fastcall call_rcu(struct rcu_head *head, void (*func)(void *arg), void *arg) +void fastcall call_rcu(struct rcu_head *head, + void (*func)(struct rcu_head *rcu)) { int cpu; unsigned long flags; head->func = func; - head->arg = arg; head->next = NULL; local_irq_save(flags); cpu = smp_processor_id(); @@ -100,7 +99,7 @@ static void rcu_do_batch(struct rcu_head *list) while (list) { next = list->next; - list->func(list->arg); + list->func(list); list = next; } } @@ -358,11 +357,18 @@ void __init rcu_init(void) register_cpu_notifier(&rcu_nb); } +struct rcu_synchronize { + struct rcu_head head; + struct completion completion; +}; /* Because of FASTCALL declaration of complete, we use this wrapper */ -static void wakeme_after_rcu(void *completion) +static void wakeme_after_rcu(struct rcu_head *head) { - complete(completion); + struct rcu_synchronize *rcu; + + rcu = container_of(head, struct rcu_synchronize, head); + complete(&rcu->completion); } /** @@ -371,14 +377,14 @@ static void wakeme_after_rcu(void *completion) */ void synchronize_kernel(void) { - struct rcu_head rcu; - DECLARE_COMPLETION(completion); + struct rcu_synchronize rcu; + init_completion(&rcu.completion); /* Will wake me after RCU finished */ - call_rcu(&rcu, wakeme_after_rcu, &completion); + call_rcu(&rcu.head, wakeme_after_rcu); /* Wait for it */ - wait_for_completion(&completion); + wait_for_completion(&rcu.completion); } |
