Skip to content

Commit c8895e2

Browse files
Daniel Bristot de Oliveirarostedt
Daniel Bristot de Oliveira
authored andcommitted
trace/osnoise: Support hotplug operations
Enable and disable osnoise/timerlat thread during on CPU hotplug online and offline operations respectivelly. Link: https://lore.kernel.org/linux-doc/[email protected]/ Link: https://lkml.kernel.org/r/39f98590b3caeb3c32f09526214058efe0e9272a.1624372313.git.bristot@redhat.com Cc: Phil Auld <[email protected]> Cc: Sebastian Andrzej Siewior <[email protected]> Cc: Kate Carcia <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Alexandre Chartre <[email protected]> Cc: Clark Willaims <[email protected]> Cc: John Kacur <[email protected]> Cc: Juri Lelli <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Suggested-by: Steven Rostedt (VMware) <[email protected]> Signed-off-by: Daniel Bristot de Oliveira <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent ba998f7 commit c8895e2

File tree

1 file changed

+135
-30
lines changed

1 file changed

+135
-30
lines changed

kernel/trace/trace_osnoise.c

Lines changed: 135 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,22 +1416,67 @@ static int timerlat_main(void *data)
14161416
#endif /* CONFIG_TIMERLAT_TRACER */
14171417

14181418
/*
1419-
* stop_per_cpu_kthread - stop per-cpu threads
1419+
* stop_kthread - stop a workload thread
1420+
*/
1421+
static void stop_kthread(unsigned int cpu)
1422+
{
1423+
struct task_struct *kthread;
1424+
1425+
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
1426+
if (kthread)
1427+
kthread_stop(kthread);
1428+
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
1429+
}
1430+
1431+
/*
1432+
* stop_per_cpu_kthread - Stop per-cpu threads
14201433
*
14211434
* Stop the osnoise sampling htread. Use this on unload and at system
14221435
* shutdown.
14231436
*/
14241437
static void stop_per_cpu_kthreads(void)
14251438
{
1426-
struct task_struct *kthread;
14271439
int cpu;
14281440

1429-
for_each_online_cpu(cpu) {
1430-
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
1431-
if (kthread)
1432-
kthread_stop(kthread);
1433-
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
1441+
get_online_cpus();
1442+
1443+
for_each_online_cpu(cpu)
1444+
stop_kthread(cpu);
1445+
1446+
put_online_cpus();
1447+
}
1448+
1449+
/*
1450+
* start_kthread - Start a workload tread
1451+
*/
1452+
static int start_kthread(unsigned int cpu)
1453+
{
1454+
struct task_struct *kthread;
1455+
void *main = osnoise_main;
1456+
char comm[24];
1457+
1458+
#ifdef CONFIG_TIMERLAT_TRACER
1459+
if (osnoise_data.timerlat_tracer) {
1460+
snprintf(comm, 24, "timerlat/%d", cpu);
1461+
main = timerlat_main;
1462+
} else {
1463+
snprintf(comm, 24, "osnoise/%d", cpu);
14341464
}
1465+
#else
1466+
snprintf(comm, 24, "osnoise/%d", cpu);
1467+
#endif
1468+
kthread = kthread_create_on_cpu(main, NULL, cpu, comm);
1469+
1470+
if (IS_ERR(kthread)) {
1471+
pr_err(BANNER "could not start sampling thread\n");
1472+
stop_per_cpu_kthreads();
1473+
return -ENOMEM;
1474+
}
1475+
1476+
per_cpu(per_cpu_osnoise_var, cpu).kthread = kthread;
1477+
wake_up_process(kthread);
1478+
1479+
return 0;
14351480
}
14361481

14371482
/*
@@ -1443,9 +1488,7 @@ static void stop_per_cpu_kthreads(void)
14431488
static int start_per_cpu_kthreads(struct trace_array *tr)
14441489
{
14451490
struct cpumask *current_mask = &save_cpumask;
1446-
struct task_struct *kthread;
1447-
char comm[24];
1448-
void *main = osnoise_main;
1491+
int retval;
14491492
int cpu;
14501493

14511494
get_online_cpus();
@@ -1457,37 +1500,91 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
14571500
* And the CPU is online.
14581501
*/
14591502
cpumask_and(current_mask, cpu_online_mask, current_mask);
1460-
put_online_cpus();
14611503

1462-
for_each_online_cpu(cpu)
1504+
for_each_possible_cpu(cpu)
14631505
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
14641506

14651507
for_each_cpu(cpu, current_mask) {
1466-
#ifdef CONFIG_TIMERLAT_TRACER
1467-
if (osnoise_data.timerlat_tracer) {
1468-
snprintf(comm, 24, "timerlat/%d", cpu);
1469-
main = timerlat_main;
1470-
} else {
1471-
snprintf(comm, 24, "osnoise/%d", cpu);
1472-
}
1473-
#else
1474-
snprintf(comm, 24, "osnoise/%d", cpu);
1475-
#endif
1476-
kthread = kthread_create_on_cpu(main, NULL, cpu, comm);
1477-
1478-
if (IS_ERR(kthread)) {
1479-
pr_err(BANNER "could not start sampling thread\n");
1508+
retval = start_kthread(cpu);
1509+
if (retval) {
14801510
stop_per_cpu_kthreads();
1481-
return -ENOMEM;
1511+
return retval;
14821512
}
1483-
1484-
per_cpu(per_cpu_osnoise_var, cpu).kthread = kthread;
1485-
wake_up_process(kthread);
14861513
}
14871514

1515+
put_online_cpus();
1516+
14881517
return 0;
14891518
}
14901519

1520+
#ifdef CONFIG_HOTPLUG_CPU
1521+
static void osnoise_hotplug_workfn(struct work_struct *dummy)
1522+
{
1523+
struct trace_array *tr = osnoise_trace;
1524+
unsigned int cpu = smp_processor_id();
1525+
1526+
1527+
mutex_lock(&trace_types_lock);
1528+
1529+
if (!osnoise_busy)
1530+
goto out_unlock_trace;
1531+
1532+
mutex_lock(&interface_lock);
1533+
get_online_cpus();
1534+
1535+
if (!cpumask_test_cpu(cpu, &osnoise_cpumask))
1536+
goto out_unlock;
1537+
1538+
if (!cpumask_test_cpu(cpu, tr->tracing_cpumask))
1539+
goto out_unlock;
1540+
1541+
start_kthread(cpu);
1542+
1543+
out_unlock:
1544+
put_online_cpus();
1545+
mutex_unlock(&interface_lock);
1546+
out_unlock_trace:
1547+
mutex_unlock(&trace_types_lock);
1548+
}
1549+
1550+
static DECLARE_WORK(osnoise_hotplug_work, osnoise_hotplug_workfn);
1551+
1552+
/*
1553+
* osnoise_cpu_init - CPU hotplug online callback function
1554+
*/
1555+
static int osnoise_cpu_init(unsigned int cpu)
1556+
{
1557+
schedule_work_on(cpu, &osnoise_hotplug_work);
1558+
return 0;
1559+
}
1560+
1561+
/*
1562+
* osnoise_cpu_die - CPU hotplug offline callback function
1563+
*/
1564+
static int osnoise_cpu_die(unsigned int cpu)
1565+
{
1566+
stop_kthread(cpu);
1567+
return 0;
1568+
}
1569+
1570+
static void osnoise_init_hotplug_support(void)
1571+
{
1572+
int ret;
1573+
1574+
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "trace/osnoise:online",
1575+
osnoise_cpu_init, osnoise_cpu_die);
1576+
if (ret < 0)
1577+
pr_warn(BANNER "Error to init cpu hotplug support\n");
1578+
1579+
return;
1580+
}
1581+
#else /* CONFIG_HOTPLUG_CPU */
1582+
static void osnoise_init_hotplug_support(void)
1583+
{
1584+
return 0;
1585+
}
1586+
#endif /* CONFIG_HOTPLUG_CPU */
1587+
14911588
/*
14921589
* osnoise_cpus_read - Read function for reading the "cpus" file
14931590
* @filp: The active open file structure
@@ -1583,7 +1680,14 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
15831680
osnoise_tracer_stop(tr);
15841681

15851682
mutex_lock(&interface_lock);
1683+
/*
1684+
* osnoise_cpumask is read by CPU hotplug operations.
1685+
*/
1686+
get_online_cpus();
1687+
15861688
cpumask_copy(&osnoise_cpumask, osnoise_cpumask_new);
1689+
1690+
put_online_cpus();
15871691
mutex_unlock(&interface_lock);
15881692

15891693
if (running)
@@ -1940,6 +2044,7 @@ __init static int init_osnoise_tracer(void)
19402044
return ret;
19412045
}
19422046
#endif
2047+
osnoise_init_hotplug_support();
19432048

19442049
init_tracefs();
19452050

0 commit comments

Comments
 (0)