]> err.no Git - linux-2.6/blobdiff - drivers/oprofile/buffer_sync.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[linux-2.6] / drivers / oprofile / buffer_sync.c
index 531b0731314162e4afea759d8e52ada9bb11a1f8..b07ba2a1411949cf7751d0830617a1ac34013abe 100644 (file)
@@ -26,7 +26,9 @@
 #include <linux/profile.h>
 #include <linux/module.h>
 #include <linux/fs.h>
+#include <linux/oprofile.h>
+#include <linux/sched.h>
+
 #include "oprofile_stats.h"
 #include "event_buffer.h"
 #include "cpu_buffer.h"
@@ -43,13 +45,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;
 }
 
@@ -105,10 +110,10 @@ static int module_load_notify(struct notifier_block * self, unsigned long val, v
                return 0;
 
        /* FIXME: should we process all CPU buffers ? */
-       down(&buffer_sem);
+       mutex_lock(&buffer_mutex);
        add_event_entry(ESCAPE_CODE);
        add_event_entry(MODULE_LOADED_CODE);
-       up(&buffer_sem);
+       mutex_unlock(&buffer_mutex);
 #endif
        return 0;
 }
@@ -182,23 +187,22 @@ void sync_stop(void)
        end_sync();
 }
 
+
 /* Optimisation. We can manage without taking the dcookie sem
  * because we cannot reach this code without at least one
  * dcookie user still being registered (namely, the reader
  * of the event buffer). */
-static inline unsigned long fast_get_dcookie(struct dentry * dentry,
-       struct vfsmount * vfsmnt)
+static inline unsigned long fast_get_dcookie(struct path *path)
 {
        unsigned long cookie;
-       if (dentry->d_cookie)
-               return (unsigned long)dentry;
-       get_dcookie(dentry, vfsmnt, &cookie);
+
+       if (path->dentry->d_cookie)
+               return (unsigned long)path->dentry;
+       get_dcookie(path, &cookie);
        return cookie;
 }
 
+
 /* Look up the dcookie for the task's first VM_EXECUTABLE mapping,
  * which corresponds loosely to "application name". This is
  * not strictly necessary but allows oprofile to associate
@@ -217,8 +221,7 @@ static unsigned long get_exec_dcookie(struct mm_struct * mm)
                        continue;
                if (!(vma->vm_flags & VM_EXECUTABLE))
                        continue;
-               cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-                       vma->vm_file->f_vfsmnt);
+               cookie = fast_get_dcookie(&vma->vm_file->f_path);
                break;
        }
 
@@ -243,8 +246,7 @@ static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, o
                        continue;
 
                if (vma->vm_file) {
-                       cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-                               vma->vm_file->f_vfsmnt);
+                       cookie = fast_get_dcookie(&vma->vm_file->f_path);
                        *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
                                vma->vm_start;
                } else {
@@ -431,25 +433,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);
 }
 
 
@@ -501,7 +500,7 @@ void sync_buffer(int cpu)
        sync_buffer_state state = sb_buffer_start;
        unsigned long available;
 
-       down(&buffer_sem);
+       mutex_lock(&buffer_mutex);
  
        add_cpu_switch(cpu);
 
@@ -550,5 +549,5 @@ void sync_buffer(int cpu)
 
        mark_done(cpu);
 
-       up(&buffer_sem);
+       mutex_unlock(&buffer_mutex);
 }