Lines Matching +full:wakeup +full:- +full:latency +full:- +full:us
1 // SPDX-License-Identifier: GPL-2.0
4 * Timerlat Tracer: measures the wakeup latency of a timer triggered IRQ and thread.
7 * Copyright (C) 2008-2009 Jon Masters, Red Hat, Inc. <jcm@redhat.com>
8 * Copyright (C) 2013-2016 Steven Rostedt, Red Hat, Inc. <srostedt@redhat.com>
12 * DE OLIVEIRA, Daniel Bristot, et al. Demystifying the real-time linux
13 * scheduling latency. In: 32nd Euromicro Conference on Real-Time Systems
14 * (ECRTS 2020). Schloss Dagstuhl-Leibniz-Zentrum fur Informatik, 2020.
92 * osnoise_instance_registered - check if a tr is already registered
101 if (inst->tr == tr) in osnoise_instance_registered()
110 * osnoise_register_instance - register a new trace instance
127 return -ENOMEM; in osnoise_register_instance()
129 INIT_LIST_HEAD_RCU(&inst->list); in osnoise_register_instance()
130 inst->tr = tr; in osnoise_register_instance()
131 list_add_tail_rcu(&inst->list, &osnoise_instances); in osnoise_register_instance()
137 * osnoise_unregister_instance - unregister a registered trace instance
153 if (inst->tr == tr) { in osnoise_unregister_instance()
154 list_del_rcu(&inst->list); in osnoise_unregister_instance()
220 * Per-cpu runtime information.
225 * this_cpu_osn_var - Return the per-cpu osnoise_variables on its relative CPU
254 * this_cpu_tmr_var - Return the per-cpu timerlat_variables on its relative CPU
262 * tlat_var_reset - Reset the values of the given timerlat_variables
277 if (tlat_var->kthread) in tlat_var_reset()
278 hrtimer_cancel(&tlat_var->timer); in tlat_var_reset()
288 * osn_var_reset - Reset the values of the given osnoise_variables
306 * osn_var_reset_all - Reset the value of all per-cpu osnoise_variables
358 if (!tlat_var->tracing_thread) { in timerlat_softirq_exit()
359 osn_var->softirq.arrival_time = 0; in timerlat_softirq_exit()
360 osn_var->softirq.delta_start = 0; in timerlat_softirq_exit()
373 if (!tlat_var->tracing_thread) { in timerlat_thread_exit()
374 osn_var->thread.delta_start = 0; in timerlat_thread_exit()
375 osn_var->thread.arrival_time = 0; in timerlat_thread_exit()
405 seq_puts(s, "# _-------=> irqs-off\n"); in print_osnoise_headers()
406 seq_puts(s, "# / _------=> need-resched\n"); in print_osnoise_headers()
407 seq_puts(s, "# | / _-----=> need-resched-lazy\n"); in print_osnoise_headers()
408 seq_puts(s, "# || / _----=> hardirq/softirq\n"); in print_osnoise_headers()
409 seq_puts(s, "# ||| / _---=> preempt-depth\n"); in print_osnoise_headers()
410 seq_puts(s, "# |||| / _--=> preempt-lazy-depth\n"); in print_osnoise_headers()
411 seq_puts(s, "# ||||| / _-=> migrate-disable\n"); in print_osnoise_headers()
420 seq_puts(s, " NOISE %% OF CPU NOISE +-----------------------------+\n"); in print_osnoise_headers()
422 seq_puts(s, "# TASK-PID CPU# ||||||| TIMESTAMP IN US "); in print_osnoise_headers()
423 seq_puts(s, " IN US AVAILABLE IN US HW NMI IRQ SIRQ THREAD\n"); in print_osnoise_headers()
434 seq_puts(s, "# _-----=> irqs-off\n"); in print_osnoise_headers()
435 seq_puts(s, "# / _----=> need-resched\n"); in print_osnoise_headers()
436 seq_puts(s, "# | / _---=> hardirq/softirq\n"); in print_osnoise_headers()
437 seq_puts(s, "# || / _--=> preempt-depth\n"); in print_osnoise_headers()
438 seq_puts(s, "# ||| / _-=> migrate-disable "); in print_osnoise_headers()
444 seq_puts(s, " NOISE %% OF CPU NOISE +-----------------------------+\n"); in print_osnoise_headers()
446 seq_puts(s, "# TASK-PID CPU# ||||| TIMESTAMP IN US "); in print_osnoise_headers()
447 seq_puts(s, " IN US AVAILABLE IN US HW NMI IRQ SIRQ THREAD\n"); in print_osnoise_headers()
455 * osnoise_taint - report an osnoise error.
463 buffer = inst->tr->array_buffer.buffer; \
484 entry->runtime = sample->runtime; in __record_osnoise_sample()
485 entry->noise = sample->noise; in __record_osnoise_sample()
486 entry->max_sample = sample->max_sample; in __record_osnoise_sample()
487 entry->hw_count = sample->hw_count; in __record_osnoise_sample()
488 entry->nmi_count = sample->nmi_count; in __record_osnoise_sample()
489 entry->irq_count = sample->irq_count; in __record_osnoise_sample()
490 entry->softirq_count = sample->softirq_count; in __record_osnoise_sample()
491 entry->thread_count = sample->thread_count; in __record_osnoise_sample()
508 buffer = inst->tr->array_buffer.buffer; in record_osnoise_sample()
521 seq_puts(s, "# _-------=> irqs-off\n"); in print_timerlat_headers()
522 seq_puts(s, "# / _------=> need-resched\n"); in print_timerlat_headers()
523 seq_puts(s, "# | / _-----=> need-resched-lazy\n"); in print_timerlat_headers()
524 seq_puts(s, "# || / _----=> hardirq/softirq\n"); in print_timerlat_headers()
525 seq_puts(s, "# ||| / _---=> preempt-depth\n"); in print_timerlat_headers()
526 seq_puts(s, "# |||| / _--=> preempt-lazy-depth\n"); in print_timerlat_headers()
527 seq_puts(s, "# ||||| / _-=> migrate-disable\n"); in print_timerlat_headers()
530 seq_puts(s, "# TASK-PID CPU# ||||||| TIMESTAMP ID "); in print_timerlat_headers()
531 seq_puts(s, " CONTEXT LATENCY\n"); in print_timerlat_headers()
538 seq_puts(s, "# _-----=> irqs-off\n"); in print_timerlat_headers()
539 seq_puts(s, "# / _----=> need-resched\n"); in print_timerlat_headers()
540 seq_puts(s, "# | / _---=> hardirq/softirq\n"); in print_timerlat_headers()
541 seq_puts(s, "# || / _--=> preempt-depth\n"); in print_timerlat_headers()
542 seq_puts(s, "# ||| / _-=> migrate-disable\n"); in print_timerlat_headers()
545 seq_puts(s, "# TASK-PID CPU# ||||| TIMESTAMP ID "); in print_timerlat_headers()
546 seq_puts(s, " CONTEXT LATENCY\n"); in print_timerlat_headers()
563 entry->seqnum = sample->seqnum; in __record_timerlat_sample()
564 entry->context = sample->context; in __record_timerlat_sample()
565 entry->timer_latency = sample->timer_latency; in __record_timerlat_sample()
582 buffer = inst->tr->array_buffer.buffer; in record_timerlat_sample()
605 * timerlat_save_stack - save a stack trace without printing
617 size = ARRAY_SIZE(fstack->calls); in timerlat_save_stack()
619 nr_entries = stack_trace_save(fstack->calls, size, skip); in timerlat_save_stack()
621 fstack->stack_size = nr_entries * sizeof(unsigned long); in timerlat_save_stack()
622 fstack->nr_entries = nr_entries; in timerlat_save_stack()
641 entry->size = fstack->nr_entries; in __timerlat_dump_stack()
642 memcpy(&entry->caller, fstack->calls, size); in __timerlat_dump_stack()
648 * timerlat_dump_stack - dump a stack trace previously saved
650 static void timerlat_dump_stack(u64 latency) in timerlat_dump_stack() argument
658 * trace only if latency > print_stack config, if enabled. in timerlat_dump_stack()
660 if (!osnoise_data.print_stack || osnoise_data.print_stack > latency) in timerlat_dump_stack()
665 size = fstack->stack_size; in timerlat_dump_stack()
669 buffer = inst->tr->array_buffer.buffer; in timerlat_dump_stack()
677 #define timerlat_dump_stack(u64 latency) do {} while (0) argument
687 #define time_sub(a, b) ((a) - (b))
690 * cond_move_irq_delta_start - Forward the delta_start of a running IRQ
700 if (osn_var->irq.delta_start) in cond_move_irq_delta_start()
701 osn_var->irq.delta_start += duration; in cond_move_irq_delta_start()
706 * cond_move_softirq_delta_start - Forward the delta_start of a running softirq.
716 if (osn_var->softirq.delta_start) in cond_move_softirq_delta_start()
717 osn_var->softirq.delta_start += duration; in cond_move_softirq_delta_start()
724 * cond_move_thread_delta_start - Forward the delta_start of a running thread
734 if (osn_var->thread.delta_start) in cond_move_thread_delta_start()
735 osn_var->thread.delta_start += duration; in cond_move_thread_delta_start()
739 * get_int_safe_duration - Get the duration of a window
747 * - Know if a given window is being measured.
748 * - Account its duration.
749 * - Discount the interference.
754 * ---> interrupt!
755 * delta_start -= int duration;
756 * <---
757 * duration = now - delta_start;
772 int_counter = local_read(&osn_var->int_counter); in get_int_safe_duration()
777 duration = (now - *delta_start); in get_int_safe_duration()
781 } while (int_counter != local_read(&osn_var->int_counter)); in get_int_safe_duration()
797 * set_int_safe_time - Save the current time on *time, aware of interference
810 int_counter = local_read(&osn_var->int_counter); in set_int_safe_time()
818 } while (int_counter != local_read(&osn_var->int_counter)); in set_int_safe_time()
825 * copy_int_safe_time - Copy *src into *desc aware of interference
833 int_counter = local_read(&osn_var->int_counter); in copy_int_safe_time()
841 } while (int_counter != local_read(&osn_var->int_counter)); in copy_int_safe_time()
848 * trace_osnoise_callback - NMI entry/exit callback
860 if (!osn_var->sampling) in trace_osnoise_callback()
869 osn_var->nmi.delta_start = time_get(); in trace_osnoise_callback()
870 local_inc(&osn_var->int_counter); in trace_osnoise_callback()
872 duration = time_get() - osn_var->nmi.delta_start; in trace_osnoise_callback()
874 trace_nmi_noise(osn_var->nmi.delta_start, duration); in trace_osnoise_callback()
883 osn_var->nmi.count++; in trace_osnoise_callback()
887 * osnoise_trace_irq_entry - Note the starting of an IRQ
889 * Save the starting time of an IRQ. As IRQs are non-preemptive to other IRQs,
890 * it is safe to use a single variable (ons_var->irq) to save the statistics.
899 if (!osn_var->sampling) in osnoise_trace_irq_entry()
905 osn_var->irq.arrival_time = time_get(); in osnoise_trace_irq_entry()
906 set_int_safe_time(osn_var, &osn_var->irq.delta_start); in osnoise_trace_irq_entry()
907 osn_var->irq.count++; in osnoise_trace_irq_entry()
909 local_inc(&osn_var->int_counter); in osnoise_trace_irq_entry()
913 * osnoise_irq_exit - Note the end of an IRQ, sava data and trace
923 if (!osn_var->sampling) in osnoise_trace_irq_exit()
926 duration = get_int_safe_duration(osn_var, &osn_var->irq.delta_start); in osnoise_trace_irq_exit()
927 trace_irq_noise(id, desc, osn_var->irq.arrival_time, duration); in osnoise_trace_irq_exit()
928 osn_var->irq.arrival_time = 0; in osnoise_trace_irq_exit()
934 * trace_irqentry_callback - Callback to the irq:irq_entry traceevent
945 * trace_irqexit_callback - Callback to the irq:irq_exit traceevent
952 osnoise_trace_irq_exit(irq, action->name); in trace_irqexit_callback()
972 * hook_irq_events - Hook IRQ handling events
1000 return -EINVAL; in hook_irq_events()
1004 * unhook_irq_events - Unhook IRQ handling events
1018 * trace_softirq_entry_callback - Note the starting of a softirq
1020 * Save the starting time of a softirq. As softirqs are non-preemptive to
1021 * other softirqs, it is safe to use a single variable (ons_var->softirq)
1030 if (!osn_var->sampling) in trace_softirq_entry_callback()
1036 osn_var->softirq.arrival_time = time_get(); in trace_softirq_entry_callback()
1037 set_int_safe_time(osn_var, &osn_var->softirq.delta_start); in trace_softirq_entry_callback()
1038 osn_var->softirq.count++; in trace_softirq_entry_callback()
1040 local_inc(&osn_var->int_counter); in trace_softirq_entry_callback()
1044 * trace_softirq_exit_callback - Note the end of an softirq
1054 if (!osn_var->sampling) in trace_softirq_exit_callback()
1061 duration = get_int_safe_duration(osn_var, &osn_var->softirq.delta_start); in trace_softirq_exit_callback()
1062 trace_softirq_noise(vec_nr, osn_var->softirq.arrival_time, duration); in trace_softirq_exit_callback()
1064 osn_var->softirq.arrival_time = 0; in trace_softirq_exit_callback()
1068 * hook_softirq_events - Hook softirq handling events
1090 return -EINVAL; in hook_softirq_events()
1094 * unhook_softirq_events - Unhook softirq handling events
1118 * thread_entry - Record the starting of a thread noise window
1126 if (!osn_var->sampling) in thread_entry()
1132 osn_var->thread.arrival_time = time_get(); in thread_entry()
1134 set_int_safe_time(osn_var, &osn_var->thread.delta_start); in thread_entry()
1136 osn_var->thread.count++; in thread_entry()
1137 local_inc(&osn_var->int_counter); in thread_entry()
1141 * thread_exit - Report the end of a thread noise window
1150 if (!osn_var->sampling) in thread_exit()
1157 duration = get_int_safe_duration(osn_var, &osn_var->thread.delta_start); in thread_exit()
1159 trace_thread_noise(t, osn_var->thread.arrival_time, duration); in thread_exit()
1161 osn_var->thread.arrival_time = 0; in thread_exit()
1166 * osnoise_stop_exception - Stop tracing and the tracer.
1175 tr = inst->tr; in osnoise_stop_exception()
1176 trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_, in osnoise_stop_exception()
1192 * trace_sched_migrate_callback - sched:sched_migrate_task trace event handler
1195 * timerlat user-space thread migration.
1203 if (osn_var->pid == p->pid && dest_cpu != cpu) { in trace_sched_migrate_callback()
1204 per_cpu_ptr(&per_cpu_timerlat_var, cpu)->uthread_migrate = 1; in trace_sched_migrate_callback()
1205 osnoise_taint("timerlat user-thread migrated\n"); in trace_sched_migrate_callback()
1206 osnoise_stop_exception("timerlat user-thread migrated", cpu); in trace_sched_migrate_callback()
1217 * Timerlat thread migration check is only required when running timerlat in user-space. in register_migration_monitor()
1248 * trace_sched_switch - sched:sched_switch trace event handler
1262 if ((p->pid != osn_var->pid) || !workload) in trace_sched_switch_callback()
1265 if ((n->pid != osn_var->pid) || !workload) in trace_sched_switch_callback()
1270 * hook_thread_events - Hook the instrumentation for thread noise
1281 return -EINVAL; in hook_thread_events()
1291 return -EINVAL; in hook_thread_events()
1295 * unhook_thread_events - unhook the instrumentation for thread noise
1307 * save_osn_sample_stats - Save the osnoise_sample statistics
1316 s->nmi_count = osn_var->nmi.count; in save_osn_sample_stats()
1317 s->irq_count = osn_var->irq.count; in save_osn_sample_stats()
1318 s->softirq_count = osn_var->softirq.count; in save_osn_sample_stats()
1319 s->thread_count = osn_var->thread.count; in save_osn_sample_stats()
1323 * diff_osn_sample_stats - Compute the osnoise_sample statistics
1332 s->nmi_count = osn_var->nmi.count - s->nmi_count; in diff_osn_sample_stats()
1333 s->irq_count = osn_var->irq.count - s->irq_count; in diff_osn_sample_stats()
1334 s->softirq_count = osn_var->softirq.count - s->softirq_count; in diff_osn_sample_stats()
1335 s->thread_count = osn_var->thread.count - s->thread_count; in diff_osn_sample_stats()
1339 * osnoise_stop_tracing - Stop tracing and the tracer.
1348 tr = inst->tr; in osnoise_stop_tracing()
1349 trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_, in osnoise_stop_tracing()
1361 * osnoise_has_tracing_on - Check if there is at least one instance on
1370 trace_is_on += tracer_tracing_is_on(inst->tr); in osnoise_has_tracing_on()
1377 * notify_new_max_latency - Notify a new max latency via fsnotify interface.
1379 static void notify_new_max_latency(u64 latency) in notify_new_max_latency() argument
1386 tr = inst->tr; in notify_new_max_latency()
1387 if (tracer_tracing_is_on(tr) && tr->max_latency < latency) { in notify_new_max_latency()
1388 tr->max_latency = latency; in notify_new_max_latency()
1396 * run_osnoise - Sample the time and look for osnoise
1398 * Used to capture the time, looking for potential osnoise latency repeatedly.
1417 int ret = -1; in run_osnoise()
1428 osn_var->pid = current->pid; in run_osnoise()
1436 * if threshold is 0, use the default value of 1 us. in run_osnoise()
1452 osn_var->sampling = true; in run_osnoise()
1504 int interference = int_count - last_int_count; in run_osnoise()
1544 * For the non-preemptive kernel config: let threads runs, if in run_osnoise()
1560 osn_var->sampling = false; in run_osnoise()
1605 * osnoise_sleep - sleep until the next period
1616 interval = osnoise_data.sample_period - osnoise_data.sample_runtime; in osnoise_sleep()
1639 * osnoise_migration_pending - checks if the task needs to migrate
1641 * osnoise/timerlat threads are per-cpu. If there is a pending request to
1649 if (!current->migration_pending) in osnoise_migration_pending()
1665 this_cpu_osn_var()->kthread = NULL; in osnoise_migration_pending()
1673 * osnoise_main - The osnoise detection kernel thread
1690 raw_spin_lock_irqsave(¤t->pi_lock, flags); in osnoise_main()
1691 current->flags &= ~(PF_NO_SETAFFINITY); in osnoise_main()
1692 raw_spin_unlock_irqrestore(¤t->pi_lock, flags); in osnoise_main()
1714 * timerlat_irq - hrtimer handler for timerlat.
1731 now = ktime_to_ns(hrtimer_cb_get_time(&tlat->timer)); in timerlat_irq()
1736 tlat->tracing_thread = true; in timerlat_irq()
1738 osn_var->thread.arrival_time = time_get(); in timerlat_irq()
1761 if (!IS_ENABLED(CONFIG_PREEMPT_RT) && osn_var->softirq.delta_start) { in timerlat_irq()
1762 copy_int_safe_time(osn_var, &osn_var->thread.delta_start, in timerlat_irq()
1763 &osn_var->softirq.delta_start); in timerlat_irq()
1765 copy_int_safe_time(osn_var, &osn_var->softirq.delta_start, in timerlat_irq()
1766 &osn_var->irq.delta_start); in timerlat_irq()
1768 copy_int_safe_time(osn_var, &osn_var->thread.delta_start, in timerlat_irq()
1769 &osn_var->irq.delta_start); in timerlat_irq()
1775 diff = now - tlat->abs_period; in timerlat_irq()
1777 tlat->count++; in timerlat_irq()
1778 s.seqnum = tlat->count; in timerlat_irq()
1792 * root cause of an IRQ latency. in timerlat_irq()
1802 wake_up_process(tlat->kthread); in timerlat_irq()
1808 wake_up_process(tlat->kthread); in timerlat_irq()
1817 * wait_next_period - Wait for the next period for timerlat
1824 now = hrtimer_cb_get_time(&tlat->timer); in wait_next_period()
1825 next_abs_period = ns_to_ktime(tlat->abs_period + rel_period); in wait_next_period()
1830 tlat->abs_period = (u64) ktime_to_ns(next_abs_period); in wait_next_period()
1836 next_abs_period = ns_to_ktime(tlat->abs_period + rel_period); in wait_next_period()
1837 tlat->abs_period = (u64) ktime_to_ns(next_abs_period); in wait_next_period()
1842 hrtimer_start(&tlat->timer, next_abs_period, HRTIMER_MODE_ABS_PINNED_HARD); in wait_next_period()
1848 * timerlat_main- Timerlat main
1873 raw_spin_lock_irqsave(¤t->pi_lock, flags); in timerlat_main()
1874 current->flags &= ~(PF_NO_SETAFFINITY); in timerlat_main()
1875 raw_spin_unlock_irqrestore(¤t->pi_lock, flags); in timerlat_main()
1877 tlat->count = 0; in timerlat_main()
1878 tlat->tracing_thread = false; in timerlat_main()
1880 hrtimer_setup(&tlat->timer, timerlat_irq, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD); in timerlat_main()
1881 tlat->kthread = current; in timerlat_main()
1882 osn_var->pid = current->pid; in timerlat_main()
1886 tlat->abs_period = hrtimer_cb_get_time(&tlat->timer); in timerlat_main()
1890 osn_var->sampling = 1; in timerlat_main()
1894 now = ktime_to_ns(hrtimer_cb_get_time(&tlat->timer)); in timerlat_main()
1895 diff = now - tlat->abs_period; in timerlat_main()
1897 s.seqnum = tlat->count; in timerlat_main()
1907 tlat->tracing_thread = false; in timerlat_main()
1918 hrtimer_cancel(&tlat->timer); in timerlat_main()
1930 * stop_kthread - stop a workload thread
1947 kill_pid(kthread->thread_pid, SIGKILL, 1); in stop_kthread()
1963 * stop_per_cpu_kthread - Stop per-cpu threads
1981 * start_kthread - Start a workload tread
2010 return -ENOMEM; in start_kthread()
2020 * start_per_cpu_kthread - Kick off per-cpu osnoise sampling kthreads
2091 * osnoise_cpu_init - CPU hotplug online callback function
2100 * osnoise_cpu_die - CPU hotplug offline callback function
2195 * osnoise_options_write - Write function for "options" entry
2213 return -EINVAL; in osnoise_options_write()
2216 return -EFAULT; in osnoise_options_write()
2230 return -EINVAL; in osnoise_options_write()
2255 retval = -EINVAL; in osnoise_options_write()
2271 * osnoise_cpus_read - Read function for reading the "cpus" file
2277 * Prints the "cpus" output into the user-provided buffer.
2291 return -ENOMEM; in osnoise_cpus_read()
2295 return -EINVAL; in osnoise_cpus_read()
2303 * osnoise_cpus_write - Write function for "cpus" entry
2334 return -ENOMEM; in osnoise_cpus_write()
2377 long cpu = (long) inode->i_cdev; in timerlat_fd_open()
2387 return -EINVAL; in timerlat_fd_open()
2395 * The osn_var->pid holds the single access to this file. in timerlat_fd_open()
2397 if (osn_var->pid) { in timerlat_fd_open()
2400 return -EBUSY; in timerlat_fd_open()
2404 * timerlat tracer is a per-cpu tracer. Check if the user-space too in timerlat_fd_open()
2410 if (current->nr_cpus_allowed > 1 || cpu != smp_processor_id()) { in timerlat_fd_open()
2413 return -EPERM; in timerlat_fd_open()
2419 file->private_data = inode->i_cdev; in timerlat_fd_open()
2423 osn_var->kthread = current; in timerlat_fd_open()
2424 osn_var->pid = current->pid; in timerlat_fd_open()
2432 tlat->count = 0; in timerlat_fd_open()
2434 hrtimer_setup(&tlat->timer, timerlat_irq, CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED_HARD); in timerlat_fd_open()
2441 * timerlat_fd_read - Read function for "timerlat_fd" file
2447 * Prints 1 on timerlat, the number of interferences on osnoise, -1 on error.
2453 long cpu = (long) file->private_data; in timerlat_fd_read()
2465 * While in user-space, the thread is migratable. There is nothing in timerlat_fd_read()
2470 if (tlat->uthread_migrate) { in timerlat_fd_read()
2472 return -EINVAL; in timerlat_fd_read()
2475 per_cpu_ptr(&per_cpu_timerlat_var, cpu)->uthread_migrate = 1; in timerlat_fd_read()
2479 return -EINVAL; in timerlat_fd_read()
2485 * The timerlat in user-space runs in a different order: in timerlat_fd_read()
2489 * So, skip if we are entering on read() before the first wakeup in timerlat_fd_read()
2492 if (likely(osn_var->sampling)) { in timerlat_fd_read()
2493 now = ktime_to_ns(hrtimer_cb_get_time(&tlat->timer)); in timerlat_fd_read()
2494 diff = now - tlat->abs_period; in timerlat_fd_read()
2502 s.seqnum = tlat->count; in timerlat_fd_read()
2510 tlat->tracing_thread = false; in timerlat_fd_read()
2515 tlat->tracing_thread = false; in timerlat_fd_read()
2516 tlat->kthread = current; in timerlat_fd_read()
2519 tlat->abs_period = hrtimer_cb_get_time(&tlat->timer); in timerlat_fd_read()
2521 osn_var->sampling = 1; in timerlat_fd_read()
2527 /* This is the wakeup from this cycle */ in timerlat_fd_read()
2528 now = ktime_to_ns(hrtimer_cb_get_time(&tlat->timer)); in timerlat_fd_read()
2529 diff = now - tlat->abs_period; in timerlat_fd_read()
2537 s.seqnum = tlat->count; in timerlat_fd_read()
2560 long cpu = (long) file->private_data; in timerlat_fd_release()
2568 if (tlat_var->kthread) in timerlat_fd_release()
2569 hrtimer_cancel(&tlat_var->timer); in timerlat_fd_release()
2572 osn_var->sampling = 0; in timerlat_fd_release()
2573 osn_var->pid = 0; in timerlat_fd_release()
2578 if (osn_var->kthread) { in timerlat_fd_release()
2579 put_task_struct(osn_var->kthread); in timerlat_fd_release()
2580 osn_var->kthread = NULL; in timerlat_fd_release()
2632 * latency is higher than val.
2642 * osnoise/timerlat_period: min 100 us, max 1 s
2685 return -ENOMEM; in init_timerlat_stack_tracefs()
2712 return -ENOMEM; in osnoise_create_cpu_timerlat_fd()
2726 d_inode(timerlat_fd)->i_cdev = (void *)(cpu); in osnoise_create_cpu_timerlat_fd()
2733 return -ENOMEM; in osnoise_create_cpu_timerlat_fd()
2737 * init_timerlat_tracefs - A function to initialize the timerlat interface files
2747 return -ENOMEM; in init_timerlat_tracefs()
2763 * init_tracefs - A function to initialize the tracefs interface files
2777 return -ENOMEM; in init_tracefs()
2820 return -ENOMEM; in init_tracefs()
2828 * Trace is already hooked, we are re-enabling from in osnoise_hook_events()
2836 return -EINVAL; in osnoise_hook_events()
2852 return -EINVAL; in osnoise_hook_events()
2863 * osnoise_workload_start - start the workload and hook to events
2909 * osnoise_workload_stop - stop the workload and unhook the events
2977 return -EBUSY; in osnoise_tracer_init()
2979 tr->max_latency = 0; in osnoise_tracer_init()
3044 return -EBUSY; in timerlat_tracer_init()
3053 tr->max_latency = 0; in timerlat_tracer_init()