@@ -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