@@ -186,36 +186,13 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size)
186186 return i / 2 ;
187187}
188188
189- /**
190- * sort_r - sort an array of elements
191- * @base: pointer to data to sort
192- * @num: number of elements
193- * @size: size of each element
194- * @cmp_func: pointer to comparison function
195- * @swap_func: pointer to swap function or NULL
196- * @priv: third argument passed to comparison function
197- *
198- * This function does a heapsort on the given array. You may provide
199- * a swap_func function if you need to do something more than a memory
200- * copy (e.g. fix up pointers or auxiliary data), but the built-in swap
201- * avoids a slow retpoline and so is significantly faster.
202- *
203- * The comparison function must adhere to specific mathematical
204- * properties to ensure correct and stable sorting:
205- * - Antisymmetry: cmp_func(a, b) must return the opposite sign of
206- * cmp_func(b, a).
207- * - Transitivity: if cmp_func(a, b) <= 0 and cmp_func(b, c) <= 0, then
208- * cmp_func(a, c) <= 0.
209- *
210- * Sorting time is O(n log n) both on average and worst-case. While
211- * quicksort is slightly faster on average, it suffers from exploitable
212- * O(n*n) worst-case behavior and extra memory requirements that make
213- * it less suitable for kernel use.
214- */
215- void sort_r (void * base , size_t num , size_t size ,
216- cmp_r_func_t cmp_func ,
217- swap_r_func_t swap_func ,
218- const void * priv )
189+ #include <linux/sched.h>
190+
191+ static void __sort_r (void * base , size_t num , size_t size ,
192+ cmp_r_func_t cmp_func ,
193+ swap_r_func_t swap_func ,
194+ const void * priv ,
195+ bool may_schedule )
219196{
220197 /* pre-scale counters for performance */
221198 size_t n = num * size , a = (num /2 ) * size ;
@@ -286,15 +263,73 @@ void sort_r(void *base, size_t num, size_t size,
286263 b = parent (b , lsbit , size );
287264 do_swap (base + b , base + c , size , swap_func , priv );
288265 }
266+
267+ if (may_schedule )
268+ cond_resched ();
289269 }
290270
291271 n -= size ;
292272 do_swap (base , base + n , size , swap_func , priv );
293273 if (n == size * 2 && do_cmp (base , base + size , cmp_func , priv ) > 0 )
294274 do_swap (base , base + size , size , swap_func , priv );
295275}
276+
277+ /**
278+ * sort_r - sort an array of elements
279+ * @base: pointer to data to sort
280+ * @num: number of elements
281+ * @size: size of each element
282+ * @cmp_func: pointer to comparison function
283+ * @swap_func: pointer to swap function or NULL
284+ * @priv: third argument passed to comparison function
285+ *
286+ * This function does a heapsort on the given array. You may provide
287+ * a swap_func function if you need to do something more than a memory
288+ * copy (e.g. fix up pointers or auxiliary data), but the built-in swap
289+ * avoids a slow retpoline and so is significantly faster.
290+ *
291+ * The comparison function must adhere to specific mathematical
292+ * properties to ensure correct and stable sorting:
293+ * - Antisymmetry: cmp_func(a, b) must return the opposite sign of
294+ * cmp_func(b, a).
295+ * - Transitivity: if cmp_func(a, b) <= 0 and cmp_func(b, c) <= 0, then
296+ * cmp_func(a, c) <= 0.
297+ *
298+ * Sorting time is O(n log n) both on average and worst-case. While
299+ * quicksort is slightly faster on average, it suffers from exploitable
300+ * O(n*n) worst-case behavior and extra memory requirements that make
301+ * it less suitable for kernel use.
302+ */
303+ void sort_r (void * base , size_t num , size_t size ,
304+ cmp_r_func_t cmp_func ,
305+ swap_r_func_t swap_func ,
306+ const void * priv )
307+ {
308+ __sort_r (base , num , size , cmp_func , swap_func , priv , false);
309+ }
296310EXPORT_SYMBOL (sort_r );
297311
312+ /**
313+ * sort_r_nonatomic - sort an array of elements, with cond_resched
314+ * @base: pointer to data to sort
315+ * @num: number of elements
316+ * @size: size of each element
317+ * @cmp_func: pointer to comparison function
318+ * @swap_func: pointer to swap function or NULL
319+ * @priv: third argument passed to comparison function
320+ *
321+ * Same as sort_r, but preferred for larger arrays as it does a periodic
322+ * cond_resched().
323+ */
324+ void sort_r_nonatomic (void * base , size_t num , size_t size ,
325+ cmp_r_func_t cmp_func ,
326+ swap_r_func_t swap_func ,
327+ const void * priv )
328+ {
329+ __sort_r (base , num , size , cmp_func , swap_func , priv , true);
330+ }
331+ EXPORT_SYMBOL (sort_r_nonatomic );
332+
298333void sort (void * base , size_t num , size_t size ,
299334 cmp_func_t cmp_func ,
300335 swap_func_t swap_func )
@@ -304,6 +339,19 @@ void sort(void *base, size_t num, size_t size,
304339 .swap = swap_func ,
305340 };
306341
307- return sort_r (base , num , size , _CMP_WRAPPER , SWAP_WRAPPER , & w );
342+ return __sort_r (base , num , size , _CMP_WRAPPER , SWAP_WRAPPER , & w , false );
308343}
309344EXPORT_SYMBOL (sort );
345+
346+ void sort_nonatomic (void * base , size_t num , size_t size ,
347+ cmp_func_t cmp_func ,
348+ swap_func_t swap_func )
349+ {
350+ struct wrapper w = {
351+ .cmp = cmp_func ,
352+ .swap = swap_func ,
353+ };
354+
355+ return __sort_r (base , num , size , _CMP_WRAPPER , SWAP_WRAPPER , & w , true);
356+ }
357+ EXPORT_SYMBOL (sort_nonatomic );
0 commit comments