linux/drivers/oprofile/oprof.c
<<
>>
Prefs
   1/**
   2 * @file oprof.c
   3 *
   4 * @remark Copyright 2002 OProfile authors
   5 * @remark Read the file COPYING
   6 *
   7 * @author John Levon <levon@movementarian.org>
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/init.h>
  13#include <linux/oprofile.h>
  14#include <linux/moduleparam.h>
  15#include <asm/mutex.h>
  16
  17#include "oprof.h"
  18#include "event_buffer.h"
  19#include "cpu_buffer.h"
  20#include "buffer_sync.h"
  21#include "oprofile_stats.h"
  22
  23struct oprofile_operations oprofile_ops;
  24
  25unsigned long oprofile_started;
  26unsigned long backtrace_depth;
  27static unsigned long is_setup;
  28static DEFINE_MUTEX(start_mutex);
  29
  30/* timer
  31   0 - use performance monitoring hardware if available
  32   1 - use the timer int mechanism regardless
  33 */
  34static int timer = 0;
  35
  36int oprofile_setup(void)
  37{
  38        int err;
  39
  40        mutex_lock(&start_mutex);
  41
  42        if ((err = alloc_cpu_buffers()))
  43                goto out;
  44
  45        if ((err = alloc_event_buffer()))
  46                goto out1;
  47
  48        if (oprofile_ops.setup && (err = oprofile_ops.setup()))
  49                goto out2;
  50
  51        /* Note even though this starts part of the
  52         * profiling overhead, it's necessary to prevent
  53         * us missing task deaths and eventually oopsing
  54         * when trying to process the event buffer.
  55         */
  56        if (oprofile_ops.sync_start) {
  57                int sync_ret = oprofile_ops.sync_start();
  58                switch (sync_ret) {
  59                case 0:
  60                        goto post_sync;
  61                case 1:
  62                        goto do_generic;
  63                case -1:
  64                        goto out3;
  65                default:
  66                        goto out3;
  67                }
  68        }
  69do_generic:
  70        if ((err = sync_start()))
  71                goto out3;
  72
  73post_sync:
  74        is_setup = 1;
  75        mutex_unlock(&start_mutex);
  76        return 0;
  77
  78out3:
  79        if (oprofile_ops.shutdown)
  80                oprofile_ops.shutdown();
  81out2:
  82        free_event_buffer();
  83out1:
  84        free_cpu_buffers();
  85out:
  86        mutex_unlock(&start_mutex);
  87        return err;
  88}
  89
  90
  91/* Actually start profiling (echo 1>/dev/oprofile/enable) */
  92int oprofile_start(void)
  93{
  94        int err = -EINVAL;
  95
  96        mutex_lock(&start_mutex);
  97
  98        if (!is_setup)
  99                goto out;
 100
 101        err = 0;
 102
 103        if (oprofile_started)
 104                goto out;
 105
 106        oprofile_reset_stats();
 107
 108        if ((err = oprofile_ops.start()))
 109                goto out;
 110
 111        oprofile_started = 1;
 112out:
 113        mutex_unlock(&start_mutex);
 114        return err;
 115}
 116
 117
 118/* echo 0>/dev/oprofile/enable */
 119void oprofile_stop(void)
 120{
 121        mutex_lock(&start_mutex);
 122        if (!oprofile_started)
 123                goto out;
 124        oprofile_ops.stop();
 125        oprofile_started = 0;
 126        /* wake up the daemon to read what remains */
 127        wake_up_buffer_waiter();
 128out:
 129        mutex_unlock(&start_mutex);
 130}
 131
 132
 133void oprofile_shutdown(void)
 134{
 135        mutex_lock(&start_mutex);
 136        if (oprofile_ops.sync_stop) {
 137                int sync_ret = oprofile_ops.sync_stop();
 138                switch (sync_ret) {
 139                case 0:
 140                        goto post_sync;
 141                case 1:
 142                        goto do_generic;
 143                default:
 144                        goto post_sync;
 145                }
 146        }
 147do_generic:
 148        sync_stop();
 149post_sync:
 150        if (oprofile_ops.shutdown)
 151                oprofile_ops.shutdown();
 152        is_setup = 0;
 153        free_event_buffer();
 154        free_cpu_buffers();
 155        mutex_unlock(&start_mutex);
 156}
 157
 158
 159int oprofile_set_backtrace(unsigned long val)
 160{
 161        int err = 0;
 162
 163        mutex_lock(&start_mutex);
 164
 165        if (oprofile_started) {
 166                err = -EBUSY;
 167                goto out;
 168        }
 169
 170        if (!oprofile_ops.backtrace) {
 171                err = -EINVAL;
 172                goto out;
 173        }
 174
 175        backtrace_depth = val;
 176
 177out:
 178        mutex_unlock(&start_mutex);
 179        return err;
 180}
 181
 182static int __init oprofile_init(void)
 183{
 184        int err;
 185
 186        err = oprofile_arch_init(&oprofile_ops);
 187
 188        if (err < 0 || timer) {
 189                printk(KERN_INFO "oprofile: using timer interrupt.\n");
 190                oprofile_timer_init(&oprofile_ops);
 191        }
 192
 193        err = oprofilefs_register();
 194        if (err)
 195                oprofile_arch_exit();
 196
 197        return err;
 198}
 199
 200
 201static void __exit oprofile_exit(void)
 202{
 203        oprofilefs_unregister();
 204        oprofile_arch_exit();
 205}
 206
 207
 208module_init(oprofile_init);
 209module_exit(oprofile_exit);
 210
 211module_param_named(timer, timer, int, 0644);
 212MODULE_PARM_DESC(timer, "force use of timer interrupt");
 213
 214MODULE_LICENSE("GPL");
 215MODULE_AUTHOR("John Levon <levon@movementarian.org>");
 216MODULE_DESCRIPTION("OProfile system profiler");
 217
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.