]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - kernel/trace/trace_osnoise.c
tracing/osnoise: Make osnoise_main to sleep for microseconds
[mirror_ubuntu-jammy-kernel.git] / kernel / trace / trace_osnoise.c
index ce053619f289e9e17c46a3afa8785f87cd8f834c..fc491d0aee5a07bab55b1032b862335be876a5ff 100644 (file)
@@ -1249,6 +1249,37 @@ out:
 static struct cpumask osnoise_cpumask;
 static struct cpumask save_cpumask;
 
+/*
+ * osnoise_sleep - sleep until the next period
+ */
+static void osnoise_sleep(void)
+{
+       u64 interval;
+       ktime_t wake_time;
+
+       mutex_lock(&interface_lock);
+       interval = osnoise_data.sample_period - osnoise_data.sample_runtime;
+       mutex_unlock(&interface_lock);
+
+       /*
+        * differently from hwlat_detector, the osnoise tracer can run
+        * without a pause because preemption is on.
+        */
+       if (!interval) {
+               /* Let synchronize_rcu_tasks() make progress */
+               cond_resched_tasks_rcu_qs();
+               return;
+       }
+
+       wake_time = ktime_add_us(ktime_get(), interval);
+       __set_current_state(TASK_INTERRUPTIBLE);
+
+       while (schedule_hrtimeout_range(&wake_time, 0, HRTIMER_MODE_ABS)) {
+               if (kthread_should_stop())
+                       break;
+       }
+}
+
 /*
  * osnoise_main - The osnoise detection kernel thread
  *
@@ -1257,30 +1288,10 @@ static struct cpumask save_cpumask;
  */
 static int osnoise_main(void *data)
 {
-       u64 interval;
 
        while (!kthread_should_stop()) {
-
                run_osnoise();
-
-               mutex_lock(&interface_lock);
-               interval = osnoise_data.sample_period - osnoise_data.sample_runtime;
-               mutex_unlock(&interface_lock);
-
-               do_div(interval, USEC_PER_MSEC);
-
-               /*
-                * differently from hwlat_detector, the osnoise tracer can run
-                * without a pause because preemption is on.
-                */
-               if (interval < 1) {
-                       /* Let synchronize_rcu_tasks() make progress */
-                       cond_resched_tasks_rcu_qs();
-                       continue;
-               }
-
-               if (msleep_interruptible(interval))
-                       break;
+               osnoise_sleep();
        }
 
        return 0;
@@ -1856,38 +1867,38 @@ static int init_tracefs(void)
        if (!top_dir)
                return 0;
 
-       tmp = tracefs_create_file("period_us", 0640, top_dir,
+       tmp = tracefs_create_file("period_us", TRACE_MODE_WRITE, top_dir,
                                  &osnoise_period, &trace_min_max_fops);
        if (!tmp)
                goto err;
 
-       tmp = tracefs_create_file("runtime_us", 0644, top_dir,
+       tmp = tracefs_create_file("runtime_us", TRACE_MODE_WRITE, top_dir,
                                  &osnoise_runtime, &trace_min_max_fops);
        if (!tmp)
                goto err;
 
-       tmp = tracefs_create_file("stop_tracing_us", 0640, top_dir,
+       tmp = tracefs_create_file("stop_tracing_us", TRACE_MODE_WRITE, top_dir,
                                  &osnoise_stop_tracing_in, &trace_min_max_fops);
        if (!tmp)
                goto err;
 
-       tmp = tracefs_create_file("stop_tracing_total_us", 0640, top_dir,
+       tmp = tracefs_create_file("stop_tracing_total_us", TRACE_MODE_WRITE, top_dir,
                                  &osnoise_stop_tracing_total, &trace_min_max_fops);
        if (!tmp)
                goto err;
 
-       tmp = trace_create_file("cpus", 0644, top_dir, NULL, &cpus_fops);
+       tmp = trace_create_file("cpus", TRACE_MODE_WRITE, top_dir, NULL, &cpus_fops);
        if (!tmp)
                goto err;
 #ifdef CONFIG_TIMERLAT_TRACER
 #ifdef CONFIG_STACKTRACE
-       tmp = tracefs_create_file("print_stack", 0640, top_dir,
+       tmp = tracefs_create_file("print_stack", TRACE_MODE_WRITE, top_dir,
                                  &osnoise_print_stack, &trace_min_max_fops);
        if (!tmp)
                goto err;
 #endif
 
-       tmp = tracefs_create_file("timerlat_period_us", 0640, top_dir,
+       tmp = tracefs_create_file("timerlat_period_us", TRACE_MODE_WRITE, top_dir,
                                  &timerlat_period, &trace_min_max_fops);
        if (!tmp)
                goto err;
@@ -1932,6 +1943,13 @@ out_unhook_irq:
        return -EINVAL;
 }
 
+static void osnoise_unhook_events(void)
+{
+       unhook_thread_events();
+       unhook_softirq_events();
+       unhook_irq_events();
+}
+
 static int __osnoise_tracer_start(struct trace_array *tr)
 {
        int retval;
@@ -1949,7 +1967,14 @@ static int __osnoise_tracer_start(struct trace_array *tr)
 
        retval = start_per_cpu_kthreads(tr);
        if (retval) {
-               unhook_irq_events();
+               trace_osnoise_callback_enabled = false;
+               /*
+                * Make sure that ftrace_nmi_enter/exit() see
+                * trace_osnoise_callback_enabled as false before continuing.
+                */
+               barrier();
+
+               osnoise_unhook_events();
                return retval;
        }
 
@@ -1981,9 +2006,7 @@ static void osnoise_tracer_stop(struct trace_array *tr)
 
        stop_per_cpu_kthreads();
 
-       unhook_irq_events();
-       unhook_softirq_events();
-       unhook_thread_events();
+       osnoise_unhook_events();
 
        osnoise_busy = false;
 }