@@ -1416,22 +1416,67 @@ static int timerlat_main(void *data)
1416
1416
#endif /* CONFIG_TIMERLAT_TRACER */
1417
1417
1418
1418
/*
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
1420
1433
*
1421
1434
* Stop the osnoise sampling htread. Use this on unload and at system
1422
1435
* shutdown.
1423
1436
*/
1424
1437
static void stop_per_cpu_kthreads (void )
1425
1438
{
1426
- struct task_struct * kthread ;
1427
1439
int cpu ;
1428
1440
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 );
1434
1464
}
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 ;
1435
1480
}
1436
1481
1437
1482
/*
@@ -1443,9 +1488,7 @@ static void stop_per_cpu_kthreads(void)
1443
1488
static int start_per_cpu_kthreads (struct trace_array * tr )
1444
1489
{
1445
1490
struct cpumask * current_mask = & save_cpumask ;
1446
- struct task_struct * kthread ;
1447
- char comm [24 ];
1448
- void * main = osnoise_main ;
1491
+ int retval ;
1449
1492
int cpu ;
1450
1493
1451
1494
get_online_cpus ();
@@ -1457,37 +1500,91 @@ static int start_per_cpu_kthreads(struct trace_array *tr)
1457
1500
* And the CPU is online.
1458
1501
*/
1459
1502
cpumask_and (current_mask , cpu_online_mask , current_mask );
1460
- put_online_cpus ();
1461
1503
1462
- for_each_online_cpu (cpu )
1504
+ for_each_possible_cpu (cpu )
1463
1505
per_cpu (per_cpu_osnoise_var , cpu ).kthread = NULL ;
1464
1506
1465
1507
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 ) {
1480
1510
stop_per_cpu_kthreads ();
1481
- return - ENOMEM ;
1511
+ return retval ;
1482
1512
}
1483
-
1484
- per_cpu (per_cpu_osnoise_var , cpu ).kthread = kthread ;
1485
- wake_up_process (kthread );
1486
1513
}
1487
1514
1515
+ put_online_cpus ();
1516
+
1488
1517
return 0 ;
1489
1518
}
1490
1519
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
+
1491
1588
/*
1492
1589
* osnoise_cpus_read - Read function for reading the "cpus" file
1493
1590
* @filp: The active open file structure
@@ -1583,7 +1680,14 @@ osnoise_cpus_write(struct file *filp, const char __user *ubuf, size_t count,
1583
1680
osnoise_tracer_stop (tr );
1584
1681
1585
1682
mutex_lock (& interface_lock );
1683
+ /*
1684
+ * osnoise_cpumask is read by CPU hotplug operations.
1685
+ */
1686
+ get_online_cpus ();
1687
+
1586
1688
cpumask_copy (& osnoise_cpumask , osnoise_cpumask_new );
1689
+
1690
+ put_online_cpus ();
1587
1691
mutex_unlock (& interface_lock );
1588
1692
1589
1693
if (running )
@@ -1940,6 +2044,7 @@ __init static int init_osnoise_tracer(void)
1940
2044
return ret ;
1941
2045
}
1942
2046
#endif
2047
+ osnoise_init_hotplug_support ();
1943
2048
1944
2049
init_tracefs ();
1945
2050
0 commit comments