diff options
author | Gautham R Shenoy <ego@in.ibm.com> | 2007-05-09 05:34:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-09 15:30:51 -0400 |
commit | 6f7cc11aa6c7d5002e16096c7590944daece70ed (patch) | |
tree | 68a11e4b67189c44ac0f3ab579e52e134d479cf5 /include/linux/notifier.h | |
parent | 7c9cb38302e78d24e37f7d8a2ea7eed4ae5f2fa7 (diff) |
Extend notifier_call_chain to count nr_calls made
Since 2.6.18-something, the community has been bugged by the problem to
provide a clean and a stable mechanism to postpone a cpu-hotplug event as
lock_cpu_hotplug was badly broken.
This is another proposal towards solving that problem. This one is along the
lines of the solution provided in kernel/workqueue.c
Instead of having a global mechanism like lock_cpu_hotplug, we allow the
subsytems to define their own per-subsystem hot cpu mutexes. These would be
taken(released) where ever we are currently calling
lock_cpu_hotplug(unlock_cpu_hotplug).
Also, in the per-subsystem hotcpu callback function,we take this mutex before
we handle any pre-cpu-hotplug events and release it once we finish handling
the post-cpu-hotplug events. A standard means for doing this has been
provided in [PATCH 2/4] and demonstrated in [PATCH 3/4].
The ordering of these per-subsystem mutexes might still prove to be a
problem, but hopefully lockdep should help us get out of that muddle.
The patch set to be applied against linux-2.6.19-rc5 is as follows:
[PATCH 1/4] : Extend notifier_call_chain with an option to specify the
number of notifications to be sent and also count the
number of notifications actually sent.
[PATCH 2/4] : Define events CPU_LOCK_ACQUIRE and CPU_LOCK_RELEASE
and send out notifications for these in _cpu_up and
_cpu_down. This would help us standardise the acquire and
release of the subsystem locks in the hotcpu
callback functions of these subsystems.
[PATCH 3/4] : Eliminate lock_cpu_hotplug from kernel/sched.c.
[PATCH 4/4] : In workqueue_cpu_callback function, acquire(release) the
workqueue_mutex while handling
CPU_LOCK_ACQUIRE(CPU_LOCK_RELEASE).
If the per-subsystem-locking approach survives the test of time, we can expect
a slow phasing out of lock_cpu_hotplug, which has not yet been eliminated in
these patches :)
This patch:
Provide notifier_call_chain with an option to call only a specified number of
notifiers and also record the number of call to notifiers made.
The need for this enhancement was identified in the post entitled
"Slab - Eliminate lock_cpu_hotplug from slab"
(http://lkml.org/lkml/2006/10/28/92) by Ravikiran G Thirumalai and
Andrew Morton.
This patch adds two additional parameters to notifier_call_chain API namely
- int nr_to_calls : Number of notifier_functions to be called.
The don't care value is -1.
- unsigned int *nr_calls : Records the total number of notifier_funtions
called by notifier_call_chain. The don't care
value is NULL.
[michal.k.k.piotrowski@gmail.com: build fix]
Credit: Andrew Morton <akpm@osdl.org>
Signed-off-by: Gautham R Shenoy <ego@in.ibm.com>
Signed-off-by: Michal Piotrowski <michal.k.k.piotrowski@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/notifier.h')
-rw-r--r-- | include/linux/notifier.h | 52 |
1 files changed, 30 insertions, 22 deletions
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index 10a43ed0527e..e34221bf8946 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
@@ -112,32 +112,40 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh); | |||
112 | 112 | ||
113 | #ifdef __KERNEL__ | 113 | #ifdef __KERNEL__ |
114 | 114 | ||
115 | extern int atomic_notifier_chain_register(struct atomic_notifier_head *, | 115 | extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh, |
116 | struct notifier_block *); | 116 | struct notifier_block *nb); |
117 | extern int blocking_notifier_chain_register(struct blocking_notifier_head *, | 117 | extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh, |
118 | struct notifier_block *); | 118 | struct notifier_block *nb); |
119 | extern int raw_notifier_chain_register(struct raw_notifier_head *, | 119 | extern int raw_notifier_chain_register(struct raw_notifier_head *nh, |
120 | struct notifier_block *); | 120 | struct notifier_block *nb); |
121 | extern int srcu_notifier_chain_register(struct srcu_notifier_head *, | 121 | extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh, |
122 | struct notifier_block *); | 122 | struct notifier_block *nb); |
123 | 123 | ||
124 | extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *, | 124 | extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, |
125 | struct notifier_block *); | 125 | struct notifier_block *nb); |
126 | extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *, | 126 | extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, |
127 | struct notifier_block *); | 127 | struct notifier_block *nb); |
128 | extern int raw_notifier_chain_unregister(struct raw_notifier_head *, | 128 | extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, |
129 | struct notifier_block *); | 129 | struct notifier_block *nb); |
130 | extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *, | 130 | extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, |
131 | struct notifier_block *); | 131 | struct notifier_block *nb); |
132 | 132 | ||
133 | extern int atomic_notifier_call_chain(struct atomic_notifier_head *, | 133 | extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh, |
134 | unsigned long val, void *v); | 134 | unsigned long val, void *v); |
135 | extern int blocking_notifier_call_chain(struct blocking_notifier_head *, | 135 | extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh, |
136 | unsigned long val, void *v, int nr_to_call, int *nr_calls); | ||
137 | extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh, | ||
136 | unsigned long val, void *v); | 138 | unsigned long val, void *v); |
137 | extern int raw_notifier_call_chain(struct raw_notifier_head *, | 139 | extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh, |
140 | unsigned long val, void *v, int nr_to_call, int *nr_calls); | ||
141 | extern int raw_notifier_call_chain(struct raw_notifier_head *nh, | ||
138 | unsigned long val, void *v); | 142 | unsigned long val, void *v); |
139 | extern int srcu_notifier_call_chain(struct srcu_notifier_head *, | 143 | extern int __raw_notifier_call_chain(struct raw_notifier_head *nh, |
144 | unsigned long val, void *v, int nr_to_call, int *nr_calls); | ||
145 | extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh, | ||
140 | unsigned long val, void *v); | 146 | unsigned long val, void *v); |
147 | extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh, | ||
148 | unsigned long val, void *v, int nr_to_call, int *nr_calls); | ||
141 | 149 | ||
142 | #define NOTIFY_DONE 0x0000 /* Don't care */ | 150 | #define NOTIFY_DONE 0x0000 /* Don't care */ |
143 | #define NOTIFY_OK 0x0001 /* Suits me */ | 151 | #define NOTIFY_OK 0x0001 /* Suits me */ |