From b6e7b6604c8a39b388dbbf7acc0c8db5b259e764 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Sun, 8 Jan 2006 01:01:35 -0800 Subject: [PATCH] --- yaml --- r: 16887 b: refs/heads/master c: 4369ef3c3e9d3bd9b879580678778f558d481e90 h: refs/heads/master i: 16885: 4bb1eaa94fa89857781f0387cf5743e0411ca532 16883: b2300e1e0b41fd429acca28ed2b9513b64eb89fe 16879: ee325b6728d0e6a3e14c8a5fec545bcca51f6b28 v: v3 --- [refs] | 2 +- trunk/drivers/oprofile/buffer_sync.c | 30 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/[refs] b/[refs] index 50cf4c77e532..6160dad26e2d 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: eafbaa94691f6a1fa67c3b076caa3ce4e2920100 +refs/heads/master: 4369ef3c3e9d3bd9b879580678778f558d481e90 diff --git a/trunk/drivers/oprofile/buffer_sync.c b/trunk/drivers/oprofile/buffer_sync.c index 531b07313141..b2e8e49c8659 100644 --- a/trunk/drivers/oprofile/buffer_sync.c +++ b/trunk/drivers/oprofile/buffer_sync.c @@ -43,13 +43,16 @@ static void process_task_mortuary(void); * list for processing. Only after two full buffer syncs * does the task eventually get freed, because by then * we are sure we will not reference it again. + * Can be invoked from softirq via RCU callback due to + * call_rcu() of the task struct, hence the _irqsave. */ static int task_free_notify(struct notifier_block * self, unsigned long val, void * data) { + unsigned long flags; struct task_struct * task = data; - spin_lock(&task_mortuary); + spin_lock_irqsave(&task_mortuary, flags); list_add(&task->tasks, &dying_tasks); - spin_unlock(&task_mortuary); + spin_unlock_irqrestore(&task_mortuary, flags); return NOTIFY_OK; } @@ -431,25 +434,22 @@ static void increment_tail(struct oprofile_cpu_buffer * b) */ static void process_task_mortuary(void) { - struct list_head * pos; - struct list_head * pos2; + unsigned long flags; + LIST_HEAD(local_dead_tasks); struct task_struct * task; + struct task_struct * ttask; - spin_lock(&task_mortuary); + spin_lock_irqsave(&task_mortuary, flags); - list_for_each_safe(pos, pos2, &dead_tasks) { - task = list_entry(pos, struct task_struct, tasks); - list_del(&task->tasks); - free_task(task); - } + list_splice_init(&dead_tasks, &local_dead_tasks); + list_splice_init(&dying_tasks, &dead_tasks); - list_for_each_safe(pos, pos2, &dying_tasks) { - task = list_entry(pos, struct task_struct, tasks); + spin_unlock_irqrestore(&task_mortuary, flags); + + list_for_each_entry_safe(task, ttask, &local_dead_tasks, tasks) { list_del(&task->tasks); - list_add_tail(&task->tasks, &dead_tasks); + free_task(task); } - - spin_unlock(&task_mortuary); }