~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/kernel/smpboot.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /kernel/smpboot.c (Version linux-6.12-rc7) and /kernel/smpboot.c (Version linux-5.10.228)


** Warning: Cannot open xref database.

  1 // SPDX-License-Identifier: GPL-2.0-only            1 
  2 /*                                                
  3  * Common SMP CPU bringup/teardown functions      
  4  */                                               
  5 #include <linux/cpu.h>                            
  6 #include <linux/err.h>                            
  7 #include <linux/smp.h>                            
  8 #include <linux/delay.h>                          
  9 #include <linux/init.h>                           
 10 #include <linux/list.h>                           
 11 #include <linux/slab.h>                           
 12 #include <linux/sched.h>                          
 13 #include <linux/sched/task.h>                     
 14 #include <linux/export.h>                         
 15 #include <linux/percpu.h>                         
 16 #include <linux/kthread.h>                        
 17 #include <linux/smpboot.h>                        
 18                                                   
 19 #include "smpboot.h"                              
 20                                                   
 21 #ifdef CONFIG_SMP                                 
 22                                                   
 23 #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD             
 24 /*                                                
 25  * For the hotplug case we keep the task struc    
 26  * them.                                          
 27  */                                               
 28 static DEFINE_PER_CPU(struct task_struct *, id    
 29                                                   
 30 struct task_struct *idle_thread_get(unsigned i    
 31 {                                                 
 32         struct task_struct *tsk = per_cpu(idle    
 33                                                   
 34         if (!tsk)                                 
 35                 return ERR_PTR(-ENOMEM);          
 36         return tsk;                               
 37 }                                                 
 38                                                   
 39 void __init idle_thread_set_boot_cpu(void)        
 40 {                                                 
 41         per_cpu(idle_threads, smp_processor_id    
 42 }                                                 
 43                                                   
 44 /**                                               
 45  * idle_init - Initialize the idle thread for     
 46  * @cpu:        The cpu for which the idle thr    
 47  *                                                
 48  * Creates the thread if it does not exist.       
 49  */                                               
 50 static __always_inline void idle_init(unsigned    
 51 {                                                 
 52         struct task_struct *tsk = per_cpu(idle    
 53                                                   
 54         if (!tsk) {                               
 55                 tsk = fork_idle(cpu);             
 56                 if (IS_ERR(tsk))                  
 57                         pr_err("SMP: fork_idle    
 58                 else                              
 59                         per_cpu(idle_threads,     
 60         }                                         
 61 }                                                 
 62                                                   
 63 /**                                               
 64  * idle_threads_init - Initialize idle threads    
 65  */                                               
 66 void __init idle_threads_init(void)               
 67 {                                                 
 68         unsigned int cpu, boot_cpu;               
 69                                                   
 70         boot_cpu = smp_processor_id();            
 71                                                   
 72         for_each_possible_cpu(cpu) {              
 73                 if (cpu != boot_cpu)              
 74                         idle_init(cpu);           
 75         }                                         
 76 }                                                 
 77 #endif                                            
 78                                                   
 79 #endif /* #ifdef CONFIG_SMP */                    
 80                                                   
 81 static LIST_HEAD(hotplug_threads);                
 82 static DEFINE_MUTEX(smpboot_threads_lock);        
 83                                                   
 84 struct smpboot_thread_data {                      
 85         unsigned int                    cpu;      
 86         unsigned int                    status    
 87         struct smp_hotplug_thread       *ht;      
 88 };                                                
 89                                                   
 90 enum {                                            
 91         HP_THREAD_NONE = 0,                       
 92         HP_THREAD_ACTIVE,                         
 93         HP_THREAD_PARKED,                         
 94 };                                                
 95                                                   
 96 /**                                               
 97  * smpboot_thread_fn - percpu hotplug thread l    
 98  * @data:       thread data pointer               
 99  *                                                
100  * Checks for thread stop and park conditions.    
101  * setup, cleanup, park and unpark functions f    
102  * thread.                                        
103  *                                                
104  * Returns 1 when the thread should exit, 0 ot    
105  */                                               
106 static int smpboot_thread_fn(void *data)          
107 {                                                 
108         struct smpboot_thread_data *td = data;    
109         struct smp_hotplug_thread *ht = td->ht    
110                                                   
111         while (1) {                               
112                 set_current_state(TASK_INTERRU    
113                 preempt_disable();                
114                 if (kthread_should_stop()) {      
115                         __set_current_state(TA    
116                         preempt_enable();         
117                         /* cleanup must mirror    
118                         if (ht->cleanup && td-    
119                                 ht->cleanup(td    
120                         kfree(td);                
121                         return 0;                 
122                 }                                 
123                                                   
124                 if (kthread_should_park()) {      
125                         __set_current_state(TA    
126                         preempt_enable();         
127                         if (ht->park && td->st    
128                                 BUG_ON(td->cpu    
129                                 ht->park(td->c    
130                                 td->status = H    
131                         }                         
132                         kthread_parkme();         
133                         /* We might have been     
134                         continue;                 
135                 }                                 
136                                                   
137                 BUG_ON(td->cpu != smp_processo    
138                                                   
139                 /* Check for state change setu    
140                 switch (td->status) {             
141                 case HP_THREAD_NONE:              
142                         __set_current_state(TA    
143                         preempt_enable();         
144                         if (ht->setup)            
145                                 ht->setup(td->    
146                         td->status = HP_THREAD    
147                         continue;                 
148                                                   
149                 case HP_THREAD_PARKED:            
150                         __set_current_state(TA    
151                         preempt_enable();         
152                         if (ht->unpark)           
153                                 ht->unpark(td-    
154                         td->status = HP_THREAD    
155                         continue;                 
156                 }                                 
157                                                   
158                 if (!ht->thread_should_run(td-    
159                         preempt_enable_no_resc    
160                         schedule();               
161                 } else {                          
162                         __set_current_state(TA    
163                         preempt_enable();         
164                         ht->thread_fn(td->cpu)    
165                 }                                 
166         }                                         
167 }                                                 
168                                                   
169 static int                                        
170 __smpboot_create_thread(struct smp_hotplug_thr    
171 {                                                 
172         struct task_struct *tsk = *per_cpu_ptr    
173         struct smpboot_thread_data *td;           
174                                                   
175         if (tsk)                                  
176                 return 0;                         
177                                                   
178         td = kzalloc_node(sizeof(*td), GFP_KER    
179         if (!td)                                  
180                 return -ENOMEM;                   
181         td->cpu = cpu;                            
182         td->ht = ht;                              
183                                                   
184         tsk = kthread_create_on_cpu(smpboot_th    
185                                     ht->thread    
186         if (IS_ERR(tsk)) {                        
187                 kfree(td);                        
188                 return PTR_ERR(tsk);              
189         }                                         
190         kthread_set_per_cpu(tsk, cpu);            
191         /*                                        
192          * Park the thread so that it could st    
193          * when it is available.                  
194          */                                       
195         kthread_park(tsk);                        
196         get_task_struct(tsk);                     
197         *per_cpu_ptr(ht->store, cpu) = tsk;       
198         if (ht->create) {                         
199                 /*                                
200                  * Make sure that the task has    
201                  * into park position, before     
202                  * callback. At least the migr    
203                  * requires that the task is o    
204                  */                               
205                 if (!wait_task_inactive(tsk, T    
206                         WARN_ON(1);               
207                 else                              
208                         ht->create(cpu);          
209         }                                         
210         return 0;                                 
211 }                                                 
212                                                   
213 int smpboot_create_threads(unsigned int cpu)      
214 {                                                 
215         struct smp_hotplug_thread *cur;           
216         int ret = 0;                              
217                                                   
218         mutex_lock(&smpboot_threads_lock);        
219         list_for_each_entry(cur, &hotplug_thre    
220                 ret = __smpboot_create_thread(    
221                 if (ret)                          
222                         break;                    
223         }                                         
224         mutex_unlock(&smpboot_threads_lock);      
225         return ret;                               
226 }                                                 
227                                                   
228 static void smpboot_unpark_thread(struct smp_h    
229 {                                                 
230         struct task_struct *tsk = *per_cpu_ptr    
231                                                   
232         if (!ht->selfparking)                     
233                 kthread_unpark(tsk);              
234 }                                                 
235                                                   
236 int smpboot_unpark_threads(unsigned int cpu)      
237 {                                                 
238         struct smp_hotplug_thread *cur;           
239                                                   
240         mutex_lock(&smpboot_threads_lock);        
241         list_for_each_entry(cur, &hotplug_thre    
242                 smpboot_unpark_thread(cur, cpu    
243         mutex_unlock(&smpboot_threads_lock);      
244         return 0;                                 
245 }                                                 
246                                                   
247 static void smpboot_park_thread(struct smp_hot    
248 {                                                 
249         struct task_struct *tsk = *per_cpu_ptr    
250                                                   
251         if (tsk && !ht->selfparking)              
252                 kthread_park(tsk);                
253 }                                                 
254                                                   
255 int smpboot_park_threads(unsigned int cpu)        
256 {                                                 
257         struct smp_hotplug_thread *cur;           
258                                                   
259         mutex_lock(&smpboot_threads_lock);        
260         list_for_each_entry_reverse(cur, &hotp    
261                 smpboot_park_thread(cur, cpu);    
262         mutex_unlock(&smpboot_threads_lock);      
263         return 0;                                 
264 }                                                 
265                                                   
266 static void smpboot_destroy_threads(struct smp    
267 {                                                 
268         unsigned int cpu;                         
269                                                   
270         /* We need to destroy also the parked     
271         for_each_possible_cpu(cpu) {              
272                 struct task_struct *tsk = *per    
273                                                   
274                 if (tsk) {                        
275                         kthread_stop_put(tsk);    
276                         *per_cpu_ptr(ht->store    
277                 }                                 
278         }                                         
279 }                                                 
280                                                   
281 /**                                               
282  * smpboot_register_percpu_thread - Register a    
283  *                                          to    
284  * @plug_thread:        Hotplug thread descrip    
285  *                                                
286  * Creates and starts the threads on all onlin    
287  */                                               
288 int smpboot_register_percpu_thread(struct smp_    
289 {                                                 
290         unsigned int cpu;                         
291         int ret = 0;                              
292                                                   
293         cpus_read_lock();                         
294         mutex_lock(&smpboot_threads_lock);        
295         for_each_online_cpu(cpu) {                
296                 ret = __smpboot_create_thread(    
297                 if (ret) {                        
298                         smpboot_destroy_thread    
299                         goto out;                 
300                 }                                 
301                 smpboot_unpark_thread(plug_thr    
302         }                                         
303         list_add(&plug_thread->list, &hotplug_    
304 out:                                              
305         mutex_unlock(&smpboot_threads_lock);      
306         cpus_read_unlock();                       
307         return ret;                               
308 }                                                 
309 EXPORT_SYMBOL_GPL(smpboot_register_percpu_thre    
310                                                   
311 /**                                               
312  * smpboot_unregister_percpu_thread - Unregist    
313  * @plug_thread:        Hotplug thread descrip    
314  *                                                
315  * Stops all threads on all possible cpus.        
316  */                                               
317 void smpboot_unregister_percpu_thread(struct s    
318 {                                                 
319         cpus_read_lock();                         
320         mutex_lock(&smpboot_threads_lock);        
321         list_del(&plug_thread->list);             
322         smpboot_destroy_threads(plug_thread);     
323         mutex_unlock(&smpboot_threads_lock);      
324         cpus_read_unlock();                       
325 }                                                 
326 EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_th    
327                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php