Skip to content

Commit 4333fb9

Browse files
Villemoesmchehab
authored andcommitted
media: lib/sort.c: implement sort() variant taking context argument
Our list_sort() utility has always supported a context argument that is passed through to the comparison routine. Now there's a use case for the similar thing for sort(). This implements sort_r by simply extending the existing sort function in the obvious way. To avoid code duplication, we want to implement sort() in terms of sort_r(). The naive way to do that is static int cmp_wrapper(const void *a, const void *b, const void *ctx) { int (*real_cmp)(const void*, const void*) = ctx; return real_cmp(a, b); } sort(..., cmp) { sort_r(..., cmp_wrapper, cmp) } but this would do two indirect calls for each comparison. Instead, do as is done for the default swap functions - that only adds a cost of a single easily predicted branch to each comparison call. Aside from introducing support for the context argument, this also serves as preparation for patches that will eliminate the indirect comparison calls in common cases. Requested-by: Boris Brezillon <[email protected]> Signed-off-by: Rasmus Villemoes <[email protected]> Signed-off-by: Boris Brezillon <[email protected]> Acked-by: Andrew Morton <[email protected]> Tested-by: Philipp Zabel <[email protected]> Signed-off-by: Hans Verkuil <[email protected]> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
1 parent 4843a54 commit 4333fb9

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

include/linux/sort.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
#include <linux/types.h>
66

7+
void sort_r(void *base, size_t num, size_t size,
8+
int (*cmp)(const void *, const void *, const void *),
9+
void (*swap)(void *, void *, int),
10+
const void *priv);
11+
712
void sort(void *base, size_t num, size_t size,
813
int (*cmp)(const void *, const void *),
914
void (*swap)(void *, void *, int));

lib/sort.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,18 @@ static void do_swap(void *a, void *b, size_t size, swap_func_t swap_func)
144144
swap_func(a, b, (int)size);
145145
}
146146

147+
typedef int (*cmp_func_t)(const void *, const void *);
148+
typedef int (*cmp_r_func_t)(const void *, const void *, const void *);
149+
#define _CMP_WRAPPER ((cmp_r_func_t)0L)
150+
151+
static int do_cmp(const void *a, const void *b,
152+
cmp_r_func_t cmp, const void *priv)
153+
{
154+
if (cmp == _CMP_WRAPPER)
155+
return ((cmp_func_t)(priv))(a, b);
156+
return cmp(a, b, priv);
157+
}
158+
147159
/**
148160
* parent - given the offset of the child, find the offset of the parent.
149161
* @i: the offset of the heap element whose parent is sought. Non-zero.
@@ -171,12 +183,13 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size)
171183
}
172184

173185
/**
174-
* sort - sort an array of elements
186+
* sort_r - sort an array of elements
175187
* @base: pointer to data to sort
176188
* @num: number of elements
177189
* @size: size of each element
178190
* @cmp_func: pointer to comparison function
179191
* @swap_func: pointer to swap function or NULL
192+
* @priv: third argument passed to comparison function
180193
*
181194
* This function does a heapsort on the given array. You may provide
182195
* a swap_func function if you need to do something more than a memory
@@ -188,9 +201,10 @@ static size_t parent(size_t i, unsigned int lsbit, size_t size)
188201
* O(n*n) worst-case behavior and extra memory requirements that make
189202
* it less suitable for kernel use.
190203
*/
191-
void sort(void *base, size_t num, size_t size,
192-
int (*cmp_func)(const void *, const void *),
193-
void (*swap_func)(void *, void *, int size))
204+
void sort_r(void *base, size_t num, size_t size,
205+
int (*cmp_func)(const void *, const void *, const void *),
206+
void (*swap_func)(void *, void *, int size),
207+
const void *priv)
194208
{
195209
/* pre-scale counters for performance */
196210
size_t n = num * size, a = (num/2) * size;
@@ -238,12 +252,12 @@ void sort(void *base, size_t num, size_t size,
238252
* average, 3/4 worst-case.)
239253
*/
240254
for (b = a; c = 2*b + size, (d = c + size) < n;)
241-
b = cmp_func(base + c, base + d) >= 0 ? c : d;
255+
b = do_cmp(base + c, base + d, cmp_func, priv) >= 0 ? c : d;
242256
if (d == n) /* Special case last leaf with no sibling */
243257
b = c;
244258

245259
/* Now backtrack from "b" to the correct location for "a" */
246-
while (b != a && cmp_func(base + a, base + b) >= 0)
260+
while (b != a && do_cmp(base + a, base + b, cmp_func, priv) >= 0)
247261
b = parent(b, lsbit, size);
248262
c = b; /* Where "a" belongs */
249263
while (b != a) { /* Shift it into place */
@@ -252,4 +266,12 @@ void sort(void *base, size_t num, size_t size,
252266
}
253267
}
254268
}
269+
EXPORT_SYMBOL(sort_r);
270+
271+
void sort(void *base, size_t num, size_t size,
272+
int (*cmp_func)(const void *, const void *),
273+
void (*swap_func)(void *, void *, int size))
274+
{
275+
return sort_r(base, num, size, _CMP_WRAPPER, swap_func, cmp_func);
276+
}
255277
EXPORT_SYMBOL(sort);

0 commit comments

Comments
 (0)