2626#include <linux/string.h>
2727#include <linux/spinlock.h>
2828#include <linux/percpu_ida.h>
29+ #include <linux/locallock.h>
30+
31+ static DEFINE_LOCAL_IRQ_LOCK (irq_off_lock );
2932
3033struct percpu_ida_cpu {
3134 /*
@@ -148,13 +151,13 @@ int percpu_ida_alloc(struct percpu_ida *pool, int state)
148151 unsigned long flags ;
149152 int tag ;
150153
151- local_irq_save ( flags );
154+ local_lock_irqsave ( irq_off_lock , flags );
152155 tags = this_cpu_ptr (pool -> tag_cpu );
153156
154157 /* Fastpath */
155158 tag = alloc_local_tag (tags );
156159 if (likely (tag >= 0 )) {
157- local_irq_restore ( flags );
160+ local_unlock_irqrestore ( irq_off_lock , flags );
158161 return tag ;
159162 }
160163
@@ -173,6 +176,7 @@ int percpu_ida_alloc(struct percpu_ida *pool, int state)
173176
174177 if (!tags -> nr_free )
175178 alloc_global_tags (pool , tags );
179+
176180 if (!tags -> nr_free )
177181 steal_tags (pool , tags );
178182
@@ -184,7 +188,7 @@ int percpu_ida_alloc(struct percpu_ida *pool, int state)
184188 }
185189
186190 spin_unlock (& pool -> lock );
187- local_irq_restore ( flags );
191+ local_unlock_irqrestore ( irq_off_lock , flags );
188192
189193 if (tag >= 0 || state == TASK_RUNNING )
190194 break ;
@@ -196,7 +200,7 @@ int percpu_ida_alloc(struct percpu_ida *pool, int state)
196200
197201 schedule ();
198202
199- local_irq_save ( flags );
203+ local_lock_irqsave ( irq_off_lock , flags );
200204 tags = this_cpu_ptr (pool -> tag_cpu );
201205 }
202206 if (state != TASK_RUNNING )
@@ -221,7 +225,7 @@ void percpu_ida_free(struct percpu_ida *pool, unsigned tag)
221225
222226 BUG_ON (tag >= pool -> nr_tags );
223227
224- local_irq_save ( flags );
228+ local_lock_irqsave ( irq_off_lock , flags );
225229 tags = this_cpu_ptr (pool -> tag_cpu );
226230
227231 spin_lock (& tags -> lock );
@@ -253,7 +257,7 @@ void percpu_ida_free(struct percpu_ida *pool, unsigned tag)
253257 spin_unlock (& pool -> lock );
254258 }
255259
256- local_irq_restore ( flags );
260+ local_unlock_irqrestore ( irq_off_lock , flags );
257261}
258262EXPORT_SYMBOL_GPL (percpu_ida_free );
259263
@@ -345,7 +349,7 @@ int percpu_ida_for_each_free(struct percpu_ida *pool, percpu_ida_cb fn,
345349 struct percpu_ida_cpu * remote ;
346350 unsigned cpu , i , err = 0 ;
347351
348- local_irq_save ( flags );
352+ local_lock_irqsave ( irq_off_lock , flags );
349353 for_each_possible_cpu (cpu ) {
350354 remote = per_cpu_ptr (pool -> tag_cpu , cpu );
351355 spin_lock (& remote -> lock );
@@ -367,7 +371,7 @@ int percpu_ida_for_each_free(struct percpu_ida *pool, percpu_ida_cb fn,
367371 }
368372 spin_unlock (& pool -> lock );
369373out :
370- local_irq_restore ( flags );
374+ local_unlock_irqrestore ( irq_off_lock , flags );
371375 return err ;
372376}
373377EXPORT_SYMBOL_GPL (percpu_ida_for_each_free );
0 commit comments