LCOV - code coverage report
Current view: top level - drivers/oprofile - oprof.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 69 0.0 %
Date: 2014-02-18 Functions: 0 7 0.0 %
Branches: 0 43 0.0 %

           Branch data     Line data    Source code
       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 <linux/workqueue.h>
      16                 :            : #include <linux/time.h>
      17                 :            : #include <linux/mutex.h>
      18                 :            : 
      19                 :            : #include "oprof.h"
      20                 :            : #include "event_buffer.h"
      21                 :            : #include "cpu_buffer.h"
      22                 :            : #include "buffer_sync.h"
      23                 :            : #include "oprofile_stats.h"
      24                 :            : 
      25                 :            : struct oprofile_operations oprofile_ops;
      26                 :            : 
      27                 :            : unsigned long oprofile_started;
      28                 :            : unsigned long oprofile_backtrace_depth;
      29                 :            : static unsigned long is_setup;
      30                 :            : static DEFINE_MUTEX(start_mutex);
      31                 :            : 
      32                 :            : /* timer
      33                 :            :    0 - use performance monitoring hardware if available
      34                 :            :    1 - use the timer int mechanism regardless
      35                 :            :  */
      36                 :            : static int timer = 0;
      37                 :            : 
      38                 :          0 : int oprofile_setup(void)
      39                 :            : {
      40                 :            :         int err;
      41                 :            : 
      42                 :          0 :         mutex_lock(&start_mutex);
      43                 :            : 
      44         [ #  # ]:          0 :         if ((err = alloc_cpu_buffers()))
      45                 :            :                 goto out;
      46                 :            : 
      47         [ #  # ]:          0 :         if ((err = alloc_event_buffer()))
      48                 :            :                 goto out1;
      49                 :            : 
      50 [ #  # ][ #  # ]:          0 :         if (oprofile_ops.setup && (err = oprofile_ops.setup()))
      51                 :            :                 goto out2;
      52                 :            : 
      53                 :            :         /* Note even though this starts part of the
      54                 :            :          * profiling overhead, it's necessary to prevent
      55                 :            :          * us missing task deaths and eventually oopsing
      56                 :            :          * when trying to process the event buffer.
      57                 :            :          */
      58         [ #  # ]:          0 :         if (oprofile_ops.sync_start) {
      59                 :          0 :                 int sync_ret = oprofile_ops.sync_start();
      60      [ #  #  # ]:          0 :                 switch (sync_ret) {
      61                 :            :                 case 0:
      62                 :            :                         goto post_sync;
      63                 :            :                 case 1:
      64                 :            :                         goto do_generic;
      65                 :            :                 case -1:
      66                 :            :                         goto out3;
      67                 :            :                 default:
      68                 :            :                         goto out3;
      69                 :            :                 }
      70                 :            :         }
      71                 :            : do_generic:
      72         [ #  # ]:          0 :         if ((err = sync_start()))
      73                 :            :                 goto out3;
      74                 :            : 
      75                 :            : post_sync:
      76                 :          0 :         is_setup = 1;
      77                 :          0 :         mutex_unlock(&start_mutex);
      78                 :          0 :         return 0;
      79                 :            : 
      80                 :            : out3:
      81         [ #  # ]:          0 :         if (oprofile_ops.shutdown)
      82                 :          0 :                 oprofile_ops.shutdown();
      83                 :            : out2:
      84                 :          0 :         free_event_buffer();
      85                 :            : out1:
      86                 :          0 :         free_cpu_buffers();
      87                 :            : out:
      88                 :          0 :         mutex_unlock(&start_mutex);
      89                 :          0 :         return err;
      90                 :            : }
      91                 :            : 
      92                 :            : #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX
      93                 :            : 
      94                 :            : static void switch_worker(struct work_struct *work);
      95                 :            : static DECLARE_DELAYED_WORK(switch_work, switch_worker);
      96                 :            : 
      97                 :            : static void start_switch_worker(void)
      98                 :            : {
      99                 :            :         if (oprofile_ops.switch_events)
     100                 :            :                 schedule_delayed_work(&switch_work, oprofile_time_slice);
     101                 :            : }
     102                 :            : 
     103                 :            : static void stop_switch_worker(void)
     104                 :            : {
     105                 :            :         cancel_delayed_work_sync(&switch_work);
     106                 :            : }
     107                 :            : 
     108                 :            : static void switch_worker(struct work_struct *work)
     109                 :            : {
     110                 :            :         if (oprofile_ops.switch_events())
     111                 :            :                 return;
     112                 :            : 
     113                 :            :         atomic_inc(&oprofile_stats.multiplex_counter);
     114                 :            :         start_switch_worker();
     115                 :            : }
     116                 :            : 
     117                 :            : /* User inputs in ms, converts to jiffies */
     118                 :            : int oprofile_set_timeout(unsigned long val_msec)
     119                 :            : {
     120                 :            :         int err = 0;
     121                 :            :         unsigned long time_slice;
     122                 :            : 
     123                 :            :         mutex_lock(&start_mutex);
     124                 :            : 
     125                 :            :         if (oprofile_started) {
     126                 :            :                 err = -EBUSY;
     127                 :            :                 goto out;
     128                 :            :         }
     129                 :            : 
     130                 :            :         if (!oprofile_ops.switch_events) {
     131                 :            :                 err = -EINVAL;
     132                 :            :                 goto out;
     133                 :            :         }
     134                 :            : 
     135                 :            :         time_slice = msecs_to_jiffies(val_msec);
     136                 :            :         if (time_slice == MAX_JIFFY_OFFSET) {
     137                 :            :                 err = -EINVAL;
     138                 :            :                 goto out;
     139                 :            :         }
     140                 :            : 
     141                 :            :         oprofile_time_slice = time_slice;
     142                 :            : 
     143                 :            : out:
     144                 :            :         mutex_unlock(&start_mutex);
     145                 :            :         return err;
     146                 :            : 
     147                 :            : }
     148                 :            : 
     149                 :            : #else
     150                 :            : 
     151                 :            : static inline void start_switch_worker(void) { }
     152                 :            : static inline void stop_switch_worker(void) { }
     153                 :            : 
     154                 :            : #endif
     155                 :            : 
     156                 :            : /* Actually start profiling (echo 1>/dev/oprofile/enable) */
     157                 :          0 : int oprofile_start(void)
     158                 :            : {
     159                 :            :         int err = -EINVAL;
     160                 :            : 
     161                 :          0 :         mutex_lock(&start_mutex);
     162                 :            : 
     163         [ #  # ]:          0 :         if (!is_setup)
     164                 :            :                 goto out;
     165                 :            : 
     166                 :            :         err = 0;
     167                 :            : 
     168         [ #  # ]:          0 :         if (oprofile_started)
     169                 :            :                 goto out;
     170                 :            : 
     171                 :          0 :         oprofile_reset_stats();
     172                 :            : 
     173         [ #  # ]:          0 :         if ((err = oprofile_ops.start()))
     174                 :            :                 goto out;
     175                 :            : 
     176                 :            :         start_switch_worker();
     177                 :            : 
     178                 :          0 :         oprofile_started = 1;
     179                 :            : out:
     180                 :          0 :         mutex_unlock(&start_mutex);
     181                 :          0 :         return err;
     182                 :            : }
     183                 :            : 
     184                 :            : 
     185                 :            : /* echo 0>/dev/oprofile/enable */
     186                 :          0 : void oprofile_stop(void)
     187                 :            : {
     188                 :          0 :         mutex_lock(&start_mutex);
     189         [ #  # ]:          0 :         if (!oprofile_started)
     190                 :            :                 goto out;
     191                 :          0 :         oprofile_ops.stop();
     192                 :          0 :         oprofile_started = 0;
     193                 :            : 
     194                 :            :         stop_switch_worker();
     195                 :            : 
     196                 :            :         /* wake up the daemon to read what remains */
     197                 :          0 :         wake_up_buffer_waiter();
     198                 :            : out:
     199                 :          0 :         mutex_unlock(&start_mutex);
     200                 :          0 : }
     201                 :            : 
     202                 :            : 
     203                 :          0 : void oprofile_shutdown(void)
     204                 :            : {
     205                 :          0 :         mutex_lock(&start_mutex);
     206         [ #  # ]:          0 :         if (oprofile_ops.sync_stop) {
     207                 :          0 :                 int sync_ret = oprofile_ops.sync_stop();
     208         [ #  # ]:          0 :                 switch (sync_ret) {
     209                 :            :                 case 0:
     210                 :            :                         goto post_sync;
     211                 :            :                 case 1:
     212                 :            :                         goto do_generic;
     213                 :            :                 default:
     214                 :            :                         goto post_sync;
     215                 :            :                 }
     216                 :            :         }
     217                 :            : do_generic:
     218                 :          0 :         sync_stop();
     219                 :            : post_sync:
     220         [ #  # ]:          0 :         if (oprofile_ops.shutdown)
     221                 :          0 :                 oprofile_ops.shutdown();
     222                 :          0 :         is_setup = 0;
     223                 :          0 :         free_event_buffer();
     224                 :          0 :         free_cpu_buffers();
     225                 :          0 :         mutex_unlock(&start_mutex);
     226                 :          0 : }
     227                 :            : 
     228                 :          0 : int oprofile_set_ulong(unsigned long *addr, unsigned long val)
     229                 :            : {
     230                 :            :         int err = -EBUSY;
     231                 :            : 
     232                 :          0 :         mutex_lock(&start_mutex);
     233         [ #  # ]:          0 :         if (!oprofile_started) {
     234                 :          0 :                 *addr = val;
     235                 :            :                 err = 0;
     236                 :            :         }
     237                 :          0 :         mutex_unlock(&start_mutex);
     238                 :            : 
     239                 :          0 :         return err;
     240                 :            : }
     241                 :            : 
     242                 :            : static int timer_mode;
     243                 :            : 
     244                 :          0 : static int __init oprofile_init(void)
     245                 :            : {
     246                 :            :         int err;
     247                 :            : 
     248                 :            :         /* always init architecture to setup backtrace support */
     249                 :          0 :         timer_mode = 0;
     250                 :          0 :         err = oprofile_arch_init(&oprofile_ops);
     251         [ #  # ]:          0 :         if (!err) {
     252 [ #  # ][ #  # ]:          0 :                 if (!timer && !oprofilefs_register())
     253                 :            :                         return 0;
     254                 :          0 :                 oprofile_arch_exit();
     255                 :            :         }
     256                 :            : 
     257                 :            :         /* setup timer mode: */
     258                 :          0 :         timer_mode = 1;
     259                 :            :         /* no nmi timer mode if oprofile.timer is set */
     260                 :            :         if (timer || op_nmi_timer_init(&oprofile_ops)) {
     261                 :          0 :                 err = oprofile_timer_init(&oprofile_ops);
     262         [ #  # ]:          0 :                 if (err)
     263                 :            :                         return err;
     264                 :            :         }
     265                 :            : 
     266                 :          0 :         return oprofilefs_register();
     267                 :            : }
     268                 :            : 
     269                 :            : 
     270                 :          0 : static void __exit oprofile_exit(void)
     271                 :            : {
     272                 :          0 :         oprofilefs_unregister();
     273         [ #  # ]:          0 :         if (!timer_mode)
     274                 :          0 :                 oprofile_arch_exit();
     275                 :          0 : }
     276                 :            : 
     277                 :            : 
     278                 :            : module_init(oprofile_init);
     279                 :            : module_exit(oprofile_exit);
     280                 :            : 
     281                 :            : module_param_named(timer, timer, int, 0644);
     282                 :            : MODULE_PARM_DESC(timer, "force use of timer interrupt");
     283                 :            : 
     284                 :            : MODULE_LICENSE("GPL");
     285                 :            : MODULE_AUTHOR("John Levon <levon@movementarian.org>");
     286                 :            : MODULE_DESCRIPTION("OProfile system profiler");

Generated by: LCOV version 1.9