@@ -186,36 +186,13 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size)
186
186
return i / 2 ;
187
187
}
188
188
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 )
219
196
{
220
197
/* pre-scale counters for performance */
221
198
size_t n = num * size , a = (num /2 ) * size ;
@@ -286,15 +263,73 @@ void sort_r(void *base, size_t num, size_t size,
286
263
b = parent (b , lsbit , size );
287
264
do_swap (base + b , base + c , size , swap_func , priv );
288
265
}
266
+
267
+ if (may_schedule )
268
+ cond_resched ();
289
269
}
290
270
291
271
n -= size ;
292
272
do_swap (base , base + n , size , swap_func , priv );
293
273
if (n == size * 2 && do_cmp (base , base + size , cmp_func , priv ) > 0 )
294
274
do_swap (base , base + size , size , swap_func , priv );
295
275
}
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
+ }
296
310
EXPORT_SYMBOL (sort_r );
297
311
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
+
298
333
void sort (void * base , size_t num , size_t size ,
299
334
cmp_func_t cmp_func ,
300
335
swap_func_t swap_func )
@@ -304,6 +339,19 @@ void sort(void *base, size_t num, size_t size,
304
339
.swap = swap_func ,
305
340
};
306
341
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 );
308
343
}
309
344
EXPORT_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