[PATCH 06/40] sched: add wakeup/sleep sched_notifiers and allow NULL notifier ops

Tejun Heo
2010-01-18T00:58:49Z

Add wakeup and sleep notifiers to sched_notifiers and allow omitting
some of the notifiers in the ops table. These will be used by
concurrency managed workqueue.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Ingo Molnar <mingo@elte.hu>
---
include/linux/sched.h | 6 ++++++
kernel/sched.c | 11 ++++++++---
2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9fc537a..a6b4e9c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1222,6 +1222,10 @@ struct sched_notifier;

/**
* sched_notifier_ops - notifiers called for scheduling events
+ * @wakeup: we're waking up
+ * notifier: struct sched_notifier for the task being woken up
+ * @sleep: we're going to bed
+ * notifier: struct sched_notifier for the task sleeping
* @in: we're about to be rescheduled:
* notifier: struct sched_notifier for the task being scheduled
* cpu: cpu we're scheduled on
@@ -1235,6 +1239,8 @@ struct sched_notifier;
* and depended upon by its users.
*/
struct sched_notifier_ops {
+ void (*wakeup)(struct sched_notifier *notifier);
+ void (*sleep)(struct sched_notifier *notifier);
void (*in)(struct sched_notifier *notifier, int cpu);
void (*out)(struct sched_notifier *notifier, struct task_struct *next);
};
diff --git a/kernel/sched.c b/kernel/sched.c
index 30b7ea8..eae624f 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -1439,7 +1439,8 @@ static inline void cpuacct_update_stats(struct task_struct *tsk,
struct hlist_node *__pos; \
\
hlist_for_each_entry(__sn, __pos, &(p)->sched_notifiers, link) \
- __sn->ops->callback(__sn , ##args); \
+ if (__sn->ops->callback) \
+ __sn->ops->callback(__sn , ##args); \
} while (0)

/**
@@ -2439,6 +2440,8 @@ static inline void ttwu_post_activation(struct task_struct *p, struct rq *rq,
rq->idle_stamp = 0;
}
#endif
+ if (success)
+ fire_sched_notifiers(p, wakeup);
}

/**
@@ -5481,10 +5484,12 @@ need_resched_nonpreemptible:
clear_tsk_need_resched(prev);

if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
- if (unlikely(signal_pending_state(prev->state, prev)))
+ if (unlikely(signal_pending_state(prev->state, prev))) {
prev->state = TASK_RUNNING;
- else
+ } else {
+ fire_sched_notifiers(prev, sleep);
deactivate_task(rq, prev, 1);
+ }
switch_count = &prev->nvcsw;
}

--
1.6.4.2