trace_hwlat.c (e7c15cd8a113335cf7154f027c9c8da1a92238ee) | trace_hwlat.c (0330f7aa8ee63d0c435c0cb4e47ea06235ee4b7f) |
---|---|
1/* 2 * trace_hwlatdetect.c - A simple Hardware Latency detector. 3 * 4 * Use this tracer to detect large system latencies induced by the behavior of 5 * certain underlying system hardware or firmware, independent of Linux itself. 6 * The code was developed originally to detect the presence of SMIs on Intel 7 * and AMD systems, although there is no dependency upon x86 herein. 8 * --- 28 unchanged lines hidden (view full) --- 37 * 38 * This file is licensed under the terms of the GNU General Public 39 * License version 2. This program is licensed "as is" without any 40 * warranty of any kind, whether express or implied. 41 */ 42#include <linux/kthread.h> 43#include <linux/tracefs.h> 44#include <linux/uaccess.h> | 1/* 2 * trace_hwlatdetect.c - A simple Hardware Latency detector. 3 * 4 * Use this tracer to detect large system latencies induced by the behavior of 5 * certain underlying system hardware or firmware, independent of Linux itself. 6 * The code was developed originally to detect the presence of SMIs on Intel 7 * and AMD systems, although there is no dependency upon x86 herein. 8 * --- 28 unchanged lines hidden (view full) --- 37 * 38 * This file is licensed under the terms of the GNU General Public 39 * License version 2. This program is licensed "as is" without any 40 * warranty of any kind, whether express or implied. 41 */ 42#include <linux/kthread.h> 43#include <linux/tracefs.h> 44#include <linux/uaccess.h> |
45#include <linux/cpumask.h> |
|
45#include <linux/delay.h> 46#include "trace.h" 47 48static struct trace_array *hwlat_trace; 49 50#define U64STR_SIZE 22 /* 20 digits max */ 51 52#define BANNER "hwlat_detector: " --- 153 unchanged lines hidden (view full) --- 206 if (sample > tr->max_latency) 207 tr->max_latency = sample; 208 } 209 210out: 211 return ret; 212} 213 | 46#include <linux/delay.h> 47#include "trace.h" 48 49static struct trace_array *hwlat_trace; 50 51#define U64STR_SIZE 22 /* 20 digits max */ 52 53#define BANNER "hwlat_detector: " --- 153 unchanged lines hidden (view full) --- 207 if (sample > tr->max_latency) 208 tr->max_latency = sample; 209 } 210 211out: 212 return ret; 213} 214 |
215static struct cpumask save_cpumask; 216static bool disable_migrate; 217 218static void move_to_next_cpu(void) 219{ 220 static struct cpumask *current_mask; 221 int next_cpu; 222 223 if (disable_migrate) 224 return; 225 226 /* Just pick the first CPU on first iteration */ 227 if (!current_mask) { 228 current_mask = &save_cpumask; 229 get_online_cpus(); 230 cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask); 231 put_online_cpus(); 232 next_cpu = cpumask_first(current_mask); 233 goto set_affinity; 234 } 235 236 /* 237 * If for some reason the user modifies the CPU affinity 238 * of this thread, than stop migrating for the duration 239 * of the current test. 240 */ 241 if (!cpumask_equal(current_mask, ¤t->cpus_allowed)) 242 goto disable; 243 244 get_online_cpus(); 245 cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask); 246 next_cpu = cpumask_next(smp_processor_id(), current_mask); 247 put_online_cpus(); 248 249 if (next_cpu >= nr_cpu_ids) 250 next_cpu = cpumask_first(current_mask); 251 252 set_affinity: 253 if (next_cpu >= nr_cpu_ids) /* Shouldn't happen! */ 254 goto disable; 255 256 cpumask_clear(current_mask); 257 cpumask_set_cpu(next_cpu, current_mask); 258 259 sched_setaffinity(0, current_mask); 260 return; 261 262 disable: 263 disable_migrate = true; 264} 265 |
|
214/* 215 * kthread_fn - The CPU time sampling/hardware latency detection kernel thread 216 * 217 * Used to periodically sample the CPU TSC via a call to get_sample. We 218 * disable interrupts, which does (intentionally) introduce latency since we 219 * need to ensure nothing else might be running (and thus preempting). 220 * Obviously this should never be used in production environments. 221 * 222 * Currently this runs on which ever CPU it was scheduled on, but most 223 * real-world hardware latency situations occur across several CPUs, 224 * but we might later generalize this if we find there are any actualy 225 * systems with alternate SMI delivery or other hardware latencies. 226 */ 227static int kthread_fn(void *data) 228{ 229 u64 interval; 230 231 while (!kthread_should_stop()) { 232 | 266/* 267 * kthread_fn - The CPU time sampling/hardware latency detection kernel thread 268 * 269 * Used to periodically sample the CPU TSC via a call to get_sample. We 270 * disable interrupts, which does (intentionally) introduce latency since we 271 * need to ensure nothing else might be running (and thus preempting). 272 * Obviously this should never be used in production environments. 273 * 274 * Currently this runs on which ever CPU it was scheduled on, but most 275 * real-world hardware latency situations occur across several CPUs, 276 * but we might later generalize this if we find there are any actualy 277 * systems with alternate SMI delivery or other hardware latencies. 278 */ 279static int kthread_fn(void *data) 280{ 281 u64 interval; 282 283 while (!kthread_should_stop()) { 284 |
285 move_to_next_cpu(); 286 |
|
233 local_irq_disable(); 234 get_sample(); 235 local_irq_enable(); 236 237 mutex_lock(&hwlat_data.lock); 238 interval = hwlat_data.sample_window - hwlat_data.sample_width; 239 mutex_unlock(&hwlat_data.lock); 240 --- 227 unchanged lines hidden (view full) --- 468static int hwlat_tracer_init(struct trace_array *tr) 469{ 470 /* Only allow one instance to enable this */ 471 if (hwlat_busy) 472 return -EBUSY; 473 474 hwlat_trace = tr; 475 | 287 local_irq_disable(); 288 get_sample(); 289 local_irq_enable(); 290 291 mutex_lock(&hwlat_data.lock); 292 interval = hwlat_data.sample_window - hwlat_data.sample_width; 293 mutex_unlock(&hwlat_data.lock); 294 --- 227 unchanged lines hidden (view full) --- 522static int hwlat_tracer_init(struct trace_array *tr) 523{ 524 /* Only allow one instance to enable this */ 525 if (hwlat_busy) 526 return -EBUSY; 527 528 hwlat_trace = tr; 529 |
530 disable_migrate = false; |
|
476 hwlat_data.count = 0; 477 tr->max_latency = 0; 478 save_tracing_thresh = tracing_thresh; 479 480 /* tracing_thresh is in nsecs, we speak in usecs */ 481 if (!tracing_thresh) 482 tracing_thresh = last_tracing_thresh; 483 --- 44 unchanged lines hidden --- | 531 hwlat_data.count = 0; 532 tr->max_latency = 0; 533 save_tracing_thresh = tracing_thresh; 534 535 /* tracing_thresh is in nsecs, we speak in usecs */ 536 if (!tracing_thresh) 537 tracing_thresh = last_tracing_thresh; 538 --- 44 unchanged lines hidden --- |