[PATCH] fix OProfile locking

From: John Levon
Date: Tue Sep 14 2004 - 10:35:23 EST



Below uses get_task_mm() as discussed. It also fixes up Anton's previous
patch. Zwane's soaked this patch all night w/o problems.

regards
john


Index: linux-cvs/kernel/fork.c
===================================================================
RCS file: /home/moz/cvs//linux-2.5/kernel/fork.c,v
retrieving revision 1.212
diff -u -a -p -r1.212 fork.c
--- linux-cvs/kernel/fork.c 2 Sep 2004 21:42:48 -0000 1.212
+++ linux-cvs/kernel/fork.c 13 Sep 2004 20:39:03 -0000
@@ -483,6 +483,7 @@ void mmput(struct mm_struct *mm)
mmdrop(mm);
}
}
+EXPORT_SYMBOL_GPL(mmput);

/**
* get_task_mm - acquire a reference to the task's mm
@@ -514,6 +515,7 @@ struct mm_struct *get_task_mm(struct tas
task_unlock(task);
return mm;
}
+EXPORT_SYMBOL_GPL(get_task_mm);

/* Please note the differences between mmput and mm_release.
* mmput is called whenever we stop holding onto a mm_struct,
Index: linux-cvs/drivers/oprofile/buffer_sync.c
===================================================================
RCS file: /home/moz/cvs//linux-2.5/drivers/oprofile/buffer_sync.c,v
retrieving revision 1.24
diff -u -a -p -r1.24 buffer_sync.c
--- linux-cvs/drivers/oprofile/buffer_sync.c 27 Aug 2004 17:34:28 -0000 1.24
+++ linux-cvs/drivers/oprofile/buffer_sync.c 13 Sep 2004 20:50:51 -0000
@@ -133,7 +133,7 @@ static struct notifier_block module_load

static void end_sync(void)
{
- end_cpu_timers();
+ end_cpu_work();
/* make sure we don't leak task structs */
process_task_mortuary();
process_task_mortuary();
@@ -144,7 +144,7 @@ int sync_start(void)
{
int err;

- start_cpu_timers();
+ start_cpu_work();

err = task_handoff_register(&task_free_nb);
if (err)
@@ -339,40 +339,25 @@ static void add_sample(struct mm_struct
}
}

-
+
static void release_mm(struct mm_struct * mm)
{
- if (mm)
- up_read(&mm->mmap_sem);
+ if (!mm)
+ return;
+ up_read(&mm->mmap_sem);
+ mmput(mm);
}


-/* Take the task's mmap_sem to protect ourselves from
- * races when we do lookup_dcookie().
- */
static struct mm_struct * take_tasks_mm(struct task_struct * task)
{
- struct mm_struct * mm;
-
- /* Subtle. We don't need to keep a reference to this task's mm,
- * because, for the mm to be freed on another CPU, that would have
- * to go through the task exit notifier, which ends up sleeping
- * on the buffer_sem we hold, so we end up with mutual exclusion
- * anyway.
- */
- task_lock(task);
- mm = task->mm;
- task_unlock(task);
-
- if (mm) {
- /* needed to walk the task's VMAs */
+ struct mm_struct * mm = get_task_mm(task);
+ if (mm)
down_read(&mm->mmap_sem);
- }
-
return mm;
}
-
-
+
+
static inline int is_ctx_switch(unsigned long val)
{
return val == ~0UL;
Index: linux-cvs/drivers/oprofile/cpu_buffer.c
===================================================================
RCS file: /home/moz/cvs//linux-2.5/drivers/oprofile/cpu_buffer.c,v
retrieving revision 1.15
diff -u -a -p -r1.15 cpu_buffer.c
--- linux-cvs/drivers/oprofile/cpu_buffer.c 8 Sep 2004 14:57:38 -0000 1.15
+++ linux-cvs/drivers/oprofile/cpu_buffer.c 13 Sep 2004 20:45:29 -0000
@@ -30,7 +30,7 @@ struct oprofile_cpu_buffer cpu_buffer[NR
static void wq_sync_buffer(void *);

#define DEFAULT_TIMER_EXPIRE (HZ / 10)
-int timers_enabled;
+int work_enabled;

static void __free_cpu_buffers(int num)
{
@@ -80,11 +80,11 @@ void free_cpu_buffers(void)
}


-void start_cpu_timers(void)
+void start_cpu_work(void)
{
int i;

- timers_enabled = 1;
+ work_enabled = 1;

for_each_online_cpu(i) {
struct oprofile_cpu_buffer * b = &cpu_buffer[i];
@@ -98,11 +98,11 @@ void start_cpu_timers(void)
}


-void end_cpu_timers(void)
+void end_cpu_work(void)
{
int i;

- timers_enabled = 0;
+ work_enabled = 0;

for_each_online_cpu(i) {
struct oprofile_cpu_buffer * b = &cpu_buffer[i];
@@ -220,6 +220,6 @@ static void wq_sync_buffer(void * data)
sync_buffer(b->cpu);

/* don't re-add the work if we're shutting down */
- if (timers_enabled)
+ if (work_enabled)
schedule_delayed_work(&b->work, DEFAULT_TIMER_EXPIRE);
}
Index: linux-cvs/drivers/oprofile/cpu_buffer.h
===================================================================
RCS file: /home/moz/cvs//linux-2.5/drivers/oprofile/cpu_buffer.h,v
retrieving revision 1.7
diff -u -a -p -r1.7 cpu_buffer.h
--- linux-cvs/drivers/oprofile/cpu_buffer.h 8 Sep 2004 14:57:38 -0000 1.7
+++ linux-cvs/drivers/oprofile/cpu_buffer.h 13 Sep 2004 20:45:26 -0000
@@ -20,8 +20,8 @@ struct task_struct;
int alloc_cpu_buffers(void);
void free_cpu_buffers(void);

-void start_cpu_timers(void);
-void end_cpu_timers(void);
+void start_cpu_work(void);
+void end_cpu_work(void);

/* CPU buffer is composed of such entries (which are
* also used for context switch notes)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/