@@ -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 */
14241437static 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)
14431488static 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