Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / oprofile / oprof.c
index a85d33d..b82a7b5 100644 (file)
@@ -5,6 +5,10 @@
  * @remark Read the file COPYING
  *
  * @author John Levon <levon@movementarian.org>
+ *
+ * Modified by Aravind Menon for Xen
+ * These modifications are:
+ * Copyright (C) 2005 Hewlett-Packard Co.
  */
 
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/oprofile.h>
 #include <linux/moduleparam.h>
-#include <asm/semaphore.h>
+#include <asm/mutex.h>
 
 #include "oprof.h"
 #include "event_buffer.h"
 #include "cpu_buffer.h"
 #include "buffer_sync.h"
 #include "oprofile_stats.h"
-struct oprofile_operations * oprofile_ops;
+
+struct oprofile_operations oprofile_ops;
+
 unsigned long oprofile_started;
+unsigned long backtrace_depth;
 static unsigned long is_setup;
-static DECLARE_MUTEX(start_sem);
+static DEFINE_MUTEX(start_mutex);
 
 /* timer
    0 - use performance monitoring hardware if available
@@ -31,11 +37,37 @@ static DECLARE_MUTEX(start_sem);
  */
 static int timer = 0;
 
+int oprofile_set_active(int active_domains[], unsigned int adomains)
+{
+       int err;
+
+       if (!oprofile_ops.set_active)
+               return -EINVAL;
+
+       mutex_lock(&start_mutex);
+       err = oprofile_ops.set_active(active_domains, adomains);
+       mutex_unlock(&start_mutex);
+       return err;
+}
+
+int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
+{
+       int err;
+
+       if (!oprofile_ops.set_passive)
+               return -EINVAL;
+
+       mutex_lock(&start_mutex);
+       err = oprofile_ops.set_passive(passive_domains, pdomains);
+       mutex_unlock(&start_mutex);
+       return err;
+}
+
 int oprofile_setup(void)
 {
        int err;
  
-       down(&start_sem);
+       mutex_lock(&start_mutex);
 
        if ((err = alloc_cpu_buffers()))
                goto out;
@@ -43,7 +75,7 @@ int oprofile_setup(void)
        if ((err = alloc_event_buffer()))
                goto out1;
  
-       if (oprofile_ops->setup && (err = oprofile_ops->setup()))
+       if (oprofile_ops.setup && (err = oprofile_ops.setup()))
                goto out2;
  
        /* Note even though this starts part of the
@@ -55,18 +87,18 @@ int oprofile_setup(void)
                goto out3;
 
        is_setup = 1;
-       up(&start_sem);
+       mutex_unlock(&start_mutex);
        return 0;
  
 out3:
-       if (oprofile_ops->shutdown)
-               oprofile_ops->shutdown();
+       if (oprofile_ops.shutdown)
+               oprofile_ops.shutdown();
 out2:
        free_event_buffer();
 out1:
        free_cpu_buffers();
 out:
-       up(&start_sem);
+       mutex_unlock(&start_mutex);
        return err;
 }
 
@@ -76,7 +108,7 @@ int oprofile_start(void)
 {
        int err = -EINVAL;
  
-       down(&start_sem);
+       mutex_lock(&start_mutex);
  
        if (!is_setup)
                goto out;
@@ -88,12 +120,12 @@ int oprofile_start(void)
  
        oprofile_reset_stats();
 
-       if ((err = oprofile_ops->start()))
+       if ((err = oprofile_ops.start()))
                goto out;
 
        oprofile_started = 1;
 out:
-       up(&start_sem); 
+       mutex_unlock(&start_mutex);
        return err;
 }
 
@@ -101,63 +133,70 @@ out:
 /* echo 0>/dev/oprofile/enable */
 void oprofile_stop(void)
 {
-       down(&start_sem);
+       mutex_lock(&start_mutex);
        if (!oprofile_started)
                goto out;
-       oprofile_ops->stop();
+       oprofile_ops.stop();
        oprofile_started = 0;
        /* wake up the daemon to read what remains */
        wake_up_buffer_waiter();
 out:
-       up(&start_sem);
+       mutex_unlock(&start_mutex);
 }
 
 
 void oprofile_shutdown(void)
 {
-       down(&start_sem);
+       mutex_lock(&start_mutex);
        sync_stop();
-       if (oprofile_ops->shutdown)
-               oprofile_ops->shutdown(); 
+       if (oprofile_ops.shutdown)
+               oprofile_ops.shutdown();
        is_setup = 0;
        free_event_buffer();
        free_cpu_buffers();
-       up(&start_sem);
+       mutex_unlock(&start_mutex);
 }
 
 
-extern void timer_init(struct oprofile_operations ** ops);
+int oprofile_set_backtrace(unsigned long val)
+{
+       int err = 0;
 
+       mutex_lock(&start_mutex);
 
-static int __init oprofile_init(void)
-{
-       /* Architecture must fill in the interrupt ops and the
-        * logical CPU type, or we can fall back to the timer
-        * interrupt profiler.
-        */
-       int err = oprofile_arch_init(&oprofile_ops);
+       if (oprofile_started) {
+               err = -EBUSY;
+               goto out;
+       }
 
-       if (err == -ENODEV || timer) {
-               timer_init(&oprofile_ops);
-               err = 0;
-       } else if (err) {
+       if (!oprofile_ops.backtrace) {
+               err = -EINVAL;
                goto out;
        }
 
-       if (!oprofile_ops->cpu_type) {
-               printk(KERN_ERR "oprofile: cpu_type not set !\n");
-               err = -EFAULT;
-       } else {
-               err = oprofilefs_register();
+       backtrace_depth = val;
+
+out:
+       mutex_unlock(&start_mutex);
+       return err;
+}
+
+static int __init oprofile_init(void)
+{
+       int err;
+
+       err = oprofile_arch_init(&oprofile_ops);
+
+       if (err < 0 || timer) {
+               printk(KERN_INFO "oprofile: using timer interrupt.\n");
+               oprofile_timer_init(&oprofile_ops);
        }
+
+       err = oprofilefs_register();
        if (err)
-               goto out_exit;
-out:
+               oprofile_arch_exit();
+
        return err;
-out_exit:
-       oprofile_arch_exit();
-       goto out;
 }