git: af3c78886fd8 - main - Alter the prototype of qsort_r(3) to match POSIX, which adopted the glibc-based interface.
Date: Fri, 30 Sep 2022 22:30:52 UTC
The branch main has been updated by delphij: URL: https://cgit.FreeBSD.org/src/commit/?id=af3c78886fd8d4ca5eebdbe581a459a6f6d29d6a commit af3c78886fd8d4ca5eebdbe581a459a6f6d29d6a Author: Ed Schouten <ed@FreeBSD.org> AuthorDate: 2022-09-30 22:26:30 +0000 Commit: Xin LI <delphij@FreeBSD.org> CommitDate: 2022-09-30 22:26:30 +0000 Alter the prototype of qsort_r(3) to match POSIX, which adopted the glibc-based interface. Unfortunately, the glibc maintainers, despite knowing the existence of the FreeBSD qsort_r(3) interface in 2004 and refused to add the same interface to glibc based on grounds of the lack of standardization and portability concerns, has decided it was a good idea to introduce their own qsort_r(3) interface in 2007 as a GNU extension with a slightly different and incompatible interface. With the adoption of their interface as POSIX standard, let's switch to the same prototype, there is no need to remain incompatible. C++ and C applications written for the historical FreeBSD interface get source level compatibility when building in C++ mode, or when building with a C compiler with C11 generics support, provided that the caller passes a fifth parameter of qsort_r() that exactly matches the historical FreeBSD comparator function pointer type and does not redefine the historical qsort_r(3) prototype in their source code. Symbol versioning is used to keep old binaries working. MFC: never Relnotes: yes Reviewed by: cem, imp, hps, pauamma Differential revision: https://reviews.freebsd.org/D17083 --- include/stdlib.h | 38 ++++++++++- lib/libc/gen/scandir-compat11.c | 8 +-- lib/libc/gen/scandir.c | 6 +- lib/libc/stdlib/Makefile.inc | 4 +- lib/libc/stdlib/Symbol.map | 2 +- lib/libc/stdlib/qsort.3 | 12 +++- lib/libc/stdlib/qsort.c | 16 ++++- lib/libc/stdlib/qsort_r.c | 11 ---- lib/libc/stdlib/qsort_r_compat.c | 21 ++++++ lib/libc/tests/stdlib/Makefile | 1 + lib/libc/tests/stdlib/qsort_r_compat_test.c | 92 +++++++++++++++++++++++++++ lib/libc/tests/stdlib/qsort_r_test.c | 6 +- lib/libproc/proc_sym.c | 4 +- sys/compat/linuxkpi/common/src/linux_compat.c | 4 +- sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c | 9 ++- sys/dev/drm2/drm_linux_list_sort.c | 4 +- sys/libkern/qsort.c | 10 +-- sys/netgraph/ng_ppp.c | 8 +-- sys/sys/libkern.h | 4 +- 19 files changed, 207 insertions(+), 53 deletions(-) diff --git a/include/stdlib.h b/include/stdlib.h index bf1a612190ee..754e8f5f5fd4 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -311,8 +311,8 @@ int mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *)); int mkostemp(char *, int); int mkostemps(char *, int, int); int mkostempsat(int, char *, int, int); -void qsort_r(void *, size_t, size_t, void *, - int (*)(void *, const void *, const void *)); +void qsort_r(void *, size_t, size_t, + int (*)(const void *, const void *, void *), void *); int radixsort(const unsigned char **, int, const unsigned char *, unsigned); void *reallocarray(void *, size_t, size_t) __result_use_check @@ -332,6 +332,40 @@ __int64_t __uint64_t strtouq(const char *, char **, int); +/* + * In FreeBSD 14, the prototype of qsort_r() was modified to comply with + * POSIX. The standardized qsort_r()'s order of last two parameters was + * changed, and the comparator function is now taking thunk as its last + * parameter, and both are different from the ones expected by the historical + * FreeBSD qsort_r() interface. + * + * Apply a workaround where we explicitly link against the historical + * interface, qsort_r@FBSD_1.0, in case when qsort_r() is called with + * the last parameter with a function pointer that exactly matches the + * historical FreeBSD qsort_r() comparator signature, so applications + * written for the historical interface can continue to work without + * modification. + */ +#if defined(__generic) || defined(__cplusplus) +void __qsort_r_compat(void *, size_t, size_t, void *, + int (*)(void *, const void *, const void *)); +__sym_compat(qsort_r, __qsort_r_compat, FBSD_1.0); +#endif +#if defined(__generic) && !defined(__cplusplus) +#define qsort_r(base, nel, width, arg4, arg5) \ + __generic(arg5, int (*)(void *, const void *, const void *), \ + __qsort_r_compat, qsort_r)(base, nel, width, arg4, arg5) +#elif defined(__cplusplus) +__END_DECLS +extern "C++" { +static inline void qsort_r(void *base, size_t nmemb, size_t size, + void *thunk, int (*compar)(void *, const void *, const void *)) { + __qsort_r_compat(base, nmemb, size, thunk, compar); +} +} +__BEGIN_DECLS +#endif + extern char *suboptarg; /* getsubopt(3) external variable */ #endif /* __BSD_VISIBLE */ diff --git a/lib/libc/gen/scandir-compat11.c b/lib/libc/gen/scandir-compat11.c index e6af1929a4d2..fe8d34d4b7d6 100644 --- a/lib/libc/gen/scandir-compat11.c +++ b/lib/libc/gen/scandir-compat11.c @@ -58,8 +58,8 @@ __FBSDID("$FreeBSD$"); #define SELECT(x) select(x) -static int freebsd11_scandir_thunk_cmp(void *thunk, const void *p1, - const void *p2); +static int freebsd11_scandir_thunk_cmp(const void *p1, const void *p2, + void *thunk); int freebsd11_scandir(const char *dirname, struct freebsd11_dirent ***namelist, @@ -116,7 +116,7 @@ freebsd11_scandir(const char *dirname, struct freebsd11_dirent ***namelist, closedir(dirp); if (numitems && dcomp != NULL) qsort_r(names, numitems, sizeof(struct freebsd11_dirent *), - &dcomp, freebsd11_scandir_thunk_cmp); + freebsd11_scandir_thunk_cmp, &dcomp); *namelist = names; return (numitems); @@ -141,7 +141,7 @@ freebsd11_alphasort(const struct freebsd11_dirent **d1, } static int -freebsd11_scandir_thunk_cmp(void *thunk, const void *p1, const void *p2) +freebsd11_scandir_thunk_cmp(const void *p1, const void *p2, void *thunk) { int (*dc)(const struct freebsd11_dirent **, const struct freebsd11_dirent **); diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index 496b1ddc29db..4f40678513dd 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -63,7 +63,7 @@ typedef DECLARE_BLOCK(int, select_block, const struct dirent *); typedef DECLARE_BLOCK(int, dcomp_block, const struct dirent **, const struct dirent **); #else -static int scandir_thunk_cmp(void *thunk, const void *p1, const void *p2); +static int scandir_thunk_cmp(const void *p1, const void *p2, void *thunk); #endif static int @@ -123,7 +123,7 @@ scandir_dirp(DIR *dirp, struct dirent ***namelist, qsort_b(names, numitems, sizeof(struct dirent *), (void*)dcomp); #else qsort_r(names, numitems, sizeof(struct dirent *), - &dcomp, scandir_thunk_cmp); + scandir_thunk_cmp, &dcomp); #endif *namelist = names; return (numitems); @@ -199,7 +199,7 @@ versionsort(const struct dirent **d1, const struct dirent **d2) } static int -scandir_thunk_cmp(void *thunk, const void *p1, const void *p2) +scandir_thunk_cmp(const void *p1, const void *p2, void *thunk) { int (*dc)(const struct dirent **, const struct dirent **); diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index a658fd78e862..8ace2c051b82 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -11,8 +11,8 @@ MISRCS+=C99_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \ getsubopt.c hcreate.c hcreate_r.c hdestroy_r.c heapsort.c heapsort_b.c \ hsearch_r.c imaxabs.c imaxdiv.c \ insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \ - merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c qsort_s.c \ - quick_exit.c radixsort.c rand.c \ + merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c qsort_r_compat.c \ + qsort_s.c quick_exit.c radixsort.c rand.c \ random.c reallocarray.c reallocf.c realpath.c remque.c \ set_constraint_handler_s.c strfmon.c strtoimax.c \ strtol.c strtold.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \ diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map index 6524c6097b96..7e0b141a21b6 100644 --- a/lib/libc/stdlib/Symbol.map +++ b/lib/libc/stdlib/Symbol.map @@ -49,7 +49,6 @@ FBSD_1.0 { lfind; mergesort; putenv; - qsort_r; qsort; radixsort; sradixsort; @@ -130,6 +129,7 @@ FBSD_1.6 { FBSD_1.7 { clearenv; + qsort_r; }; FBSDprivate_1.0 { diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 index 606185f9baee..6449849fc490 100644 --- a/lib/libc/stdlib/qsort.3 +++ b/lib/libc/stdlib/qsort.3 @@ -32,7 +32,7 @@ .\" @(#)qsort.3 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd January 20, 2020 +.Dd September 30, 2022 .Dt QSORT 3 .Os .Sh NAME @@ -67,8 +67,8 @@ .Fa "void *base" .Fa "size_t nmemb" .Fa "size_t size" +.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *, void *\*[rp]" .Fa "void *thunk" -.Fa "int \*[lp]*compar\*[rp]\*[lp]void *, const void *, const void *\*[rp]" .Fc .Ft int .Fo heapsort @@ -157,7 +157,7 @@ function behaves identically to .Fn qsort , except that it takes an additional argument, .Fa thunk , -which is passed unchanged as the first argument to function pointed to +which is passed unchanged as the last argument to function pointed to .Fa compar . This allows the comparison function to access additional data without using global variables, and thus @@ -436,3 +436,9 @@ K.3.6.3.2. The variants of these functions that take blocks as arguments first appeared in Mac OS X. This implementation was created by David Chisnall. +.Pp +In +.Fx 14.0 , +the prototype of +.Fn qsort_r +was updated to match POSIX. diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c index 0b99c04507d3..11a3c5508143 100644 --- a/lib/libc/stdlib/qsort.c +++ b/lib/libc/stdlib/qsort.c @@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$"); #include "libc_private.h" #if defined(I_AM_QSORT_R) +typedef int cmp_t(const void *, const void *, void *); +#elif defined(I_AM_QSORT_R_COMPAT) typedef int cmp_t(void *, const void *, const void *); #elif defined(I_AM_QSORT_S) typedef int cmp_t(const void *, const void *, void *); @@ -72,6 +74,8 @@ swapfunc(char *a, char *b, size_t es) if ((n) > 0) swapfunc(a, b, n) #if defined(I_AM_QSORT_R) +#define CMP(t, x, y) (cmp((x), (y), (t))) +#elif defined(I_AM_QSORT_R_COMPAT) #define CMP(t, x, y) (cmp((t), (x), (y))) #elif defined(I_AM_QSORT_S) #define CMP(t, x, y) (cmp((x), (y), (t))) @@ -81,7 +85,7 @@ swapfunc(char *a, char *b, size_t es) static inline char * med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk -#if !defined(I_AM_QSORT_R) && !defined(I_AM_QSORT_S) +#if !defined(I_AM_QSORT_R) && !defined(I_AM_QSORT_R_COMPAT) && !defined(I_AM_QSORT_S) __unused #endif ) @@ -97,6 +101,8 @@ __unused */ #if defined(I_AM_QSORT_R) #define local_qsort local_qsort_r +#elif defined(I_AM_QSORT_R_COMPAT) +#define local_qsort local_qsort_r_compat #elif defined(I_AM_QSORT_S) #define local_qsort local_qsort_s #endif @@ -211,10 +217,16 @@ loop: #if defined(I_AM_QSORT_R) void -qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +(qsort_r)(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk) { local_qsort_r(a, n, es, cmp, thunk); } +#elif defined(I_AM_QSORT_R_COMPAT) +void +__qsort_r_compat(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +{ + local_qsort_r_compat(a, n, es, cmp, thunk); +} #elif defined(I_AM_QSORT_S) errno_t qsort_s(void *a, rsize_t n, rsize_t es, cmp_t *cmp, void *thunk) diff --git a/lib/libc/stdlib/qsort_r.c b/lib/libc/stdlib/qsort_r.c index f489d31c2335..d86873604f59 100644 --- a/lib/libc/stdlib/qsort_r.c +++ b/lib/libc/stdlib/qsort_r.c @@ -4,16 +4,5 @@ * * $FreeBSD$ */ -#include "block_abi.h" #define I_AM_QSORT_R #include "qsort.c" - -typedef DECLARE_BLOCK(int, qsort_block, const void *, const void *); - -void -qsort_b(void *base, size_t nel, size_t width, qsort_block compar) -{ - qsort_r(base, nel, width, compar, - (int (*)(void *, const void *, const void *)) - GET_BLOCK_FUNCTION(compar)); -} diff --git a/lib/libc/stdlib/qsort_r_compat.c b/lib/libc/stdlib/qsort_r_compat.c new file mode 100644 index 000000000000..239a5f307ceb --- /dev/null +++ b/lib/libc/stdlib/qsort_r_compat.c @@ -0,0 +1,21 @@ +/* + * This file is in the public domain. Originally written by Garrett + * A. Wollman. + * + * $FreeBSD$ + */ +#include "block_abi.h" +#define I_AM_QSORT_R_COMPAT +#include "qsort.c" + +typedef DECLARE_BLOCK(int, qsort_block, const void *, const void *); + +void +qsort_b(void *base, size_t nel, size_t width, qsort_block compar) +{ + __qsort_r_compat(base, nel, width, compar, + (int (*)(void *, const void *, const void *)) + GET_BLOCK_FUNCTION(compar)); +} + +__sym_compat(qsort_r, __qsort_r_compat, FBSD_1.0); diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile index 47841a92ba32..df0ecc66b067 100644 --- a/lib/libc/tests/stdlib/Makefile +++ b/lib/libc/tests/stdlib/Makefile @@ -8,6 +8,7 @@ ATF_TESTS_C+= heapsort_test ATF_TESTS_C+= mergesort_test ATF_TESTS_C+= qsort_test ATF_TESTS_C+= qsort_b_test +ATF_TESTS_C+= qsort_r_compat_test ATF_TESTS_C+= qsort_r_test ATF_TESTS_C+= qsort_s_test ATF_TESTS_C+= set_constraint_handler_s_test diff --git a/lib/libc/tests/stdlib/qsort_r_compat_test.c b/lib/libc/tests/stdlib/qsort_r_compat_test.c new file mode 100644 index 000000000000..84fd1b116b82 --- /dev/null +++ b/lib/libc/tests/stdlib/qsort_r_compat_test.c @@ -0,0 +1,92 @@ +/*- + * Copyright (C) 2020 Edward Tomasz Napierala <trasz@FreeBSD.org> + * Copyright (C) 2004 Maxim Sobolev <sobomax@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Test for historical qsort_r(3) routine. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <stdio.h> +#include <stdlib.h> + +#include "test-sort.h" + +#define THUNK 42 + +static int +sorthelp_r(void *thunk, const void *a, const void *b) +{ + const int *oa, *ob; + + ATF_REQUIRE_EQ(*(int *)thunk, THUNK); + + oa = a; + ob = b; + /* Don't use "return *oa - *ob" since it's easy to cause overflow! */ + if (*oa > *ob) + return (1); + if (*oa < *ob) + return (-1); + return (0); +} + +ATF_TC_WITHOUT_HEAD(qsort_r_compat_test); +ATF_TC_BODY(qsort_r_compat_test, tc) +{ + int testvector[IVEC_LEN]; + int sresvector[IVEC_LEN]; + int i, j; + int thunk = THUNK; + + for (j = 2; j < IVEC_LEN; j++) { + /* Populate test vectors */ + for (i = 0; i < j; i++) + testvector[i] = sresvector[i] = initvector[i]; + + /* Sort using qsort_r(3) */ + qsort_r(testvector, j, sizeof(testvector[0]), &thunk, + sorthelp_r); + /* Sort using reference slow sorting routine */ + ssort(sresvector, j); + + /* Compare results */ + for (i = 0; i < j; i++) + ATF_CHECK_MSG(testvector[i] == sresvector[i], + "item at index %d didn't match: %d != %d", + i, testvector[i], sresvector[i]); + } +} + +ATF_TP_ADD_TCS(tp) +{ + + ATF_TP_ADD_TC(tp, qsort_r_compat_test); + + return (atf_no_error()); +} diff --git a/lib/libc/tests/stdlib/qsort_r_test.c b/lib/libc/tests/stdlib/qsort_r_test.c index c27e6d92d587..c55563eaea8a 100644 --- a/lib/libc/tests/stdlib/qsort_r_test.c +++ b/lib/libc/tests/stdlib/qsort_r_test.c @@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$"); #define THUNK 42 static int -sorthelp_r(void *thunk, const void *a, const void *b) +sorthelp_r(const void *a, const void *b, void *thunk) { const int *oa, *ob; @@ -70,8 +70,8 @@ ATF_TC_BODY(qsort_r_test, tc) testvector[i] = sresvector[i] = initvector[i]; /* Sort using qsort_r(3) */ - qsort_r(testvector, j, sizeof(testvector[0]), &thunk, - sorthelp_r); + qsort_r(testvector, j, sizeof(testvector[0]), sorthelp_r, + &thunk); /* Sort using reference slow sorting routine */ ssort(sresvector, j); diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c index 27b0fc15a2ab..fdcf133d8457 100644 --- a/lib/libproc/proc_sym.c +++ b/lib/libproc/proc_sym.c @@ -105,7 +105,7 @@ struct symsort_thunk { }; static int -symvalcmp(void *_thunk, const void *a1, const void *a2) +symvalcmp(const void *a1, const void *a2, void *_thunk) { GElf_Sym sym1, sym2; struct symsort_thunk *thunk; @@ -192,7 +192,7 @@ load_symtab(Elf *e, struct symtab *symtab, u_long sh_type) thunk.e = e; thunk.symtab = symtab; - qsort_r(symtab->index, nsyms, sizeof(u_int), &thunk, symvalcmp); + qsort_r(symtab->index, nsyms, sizeof(u_int), symvalcmp, &thunk); return (0); } diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index 6f1def64fa0f..8c5d2e4ecd16 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -2562,7 +2562,7 @@ struct list_sort_thunk { }; static inline int -linux_le_cmp(void *priv, const void *d1, const void *d2) +linux_le_cmp(const void *d1, const void *d2, void *priv) { struct list_head *le1, *le2; struct list_sort_thunk *thunk; @@ -2590,7 +2590,7 @@ list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, ar[i++] = le; thunk.cmp = cmp; thunk.priv = priv; - qsort_r(ar, count, sizeof(struct list_head *), &thunk, linux_le_cmp); + qsort_r(ar, count, sizeof(struct list_head *), linux_le_cmp, &thunk); INIT_LIST_HEAD(head); for (i = 0; i < count; i++) list_add_tail(ar[i], head); diff --git a/sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c b/sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c index 730b9d51da45..fd05648147f5 100644 --- a/sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c +++ b/sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c @@ -59,8 +59,7 @@ __FBSDID("$FreeBSD$"); #include "bhnd_nvram_storevar.h" -static int bhnd_nvstore_idx_cmp(void *ctx, - const void *lhs, const void *rhs); +static int bhnd_nvstore_idx_cmp(const void *lhs, const void *rhs, void *ctx); /** * Allocate and initialize a new path instance. @@ -198,7 +197,7 @@ bhnd_nvstore_index_append(struct bhnd_nvram_store *sc, /* sort function for bhnd_nvstore_index_prepare() */ static int -bhnd_nvstore_idx_cmp(void *ctx, const void *lhs, const void *rhs) +bhnd_nvstore_idx_cmp(const void *lhs, const void *rhs, void *ctx) { struct bhnd_nvram_store *sc; void *l_cookiep, *r_cookiep; @@ -259,8 +258,8 @@ bhnd_nvstore_index_prepare(struct bhnd_nvram_store *sc, BHND_NVSTORE_LOCK_ASSERT(sc, MA_OWNED); /* Sort the index table */ - qsort_r(index->cookiep, index->count, sizeof(index->cookiep[0]), sc, - bhnd_nvstore_idx_cmp); + qsort_r(index->cookiep, index->count, sizeof(index->cookiep[0]), + bhnd_nvstore_idx_cmp, sc); return (0); } diff --git a/sys/dev/drm2/drm_linux_list_sort.c b/sys/dev/drm2/drm_linux_list_sort.c index f9a64154c796..04cdf28180c8 100644 --- a/sys/dev/drm2/drm_linux_list_sort.c +++ b/sys/dev/drm2/drm_linux_list_sort.c @@ -37,7 +37,7 @@ struct drm_list_sort_thunk { }; static int -drm_le_cmp(void *priv, const void *d1, const void *d2) +drm_le_cmp(const void *d1, const void *d2, void *priv) { struct list_head *le1, *le2; struct drm_list_sort_thunk *thunk; @@ -68,7 +68,7 @@ drm_list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv, ar[i++] = le; thunk.cmp = cmp; thunk.priv = priv; - qsort_r(ar, count, sizeof(struct list_head *), &thunk, drm_le_cmp); + qsort_r(ar, count, sizeof(struct list_head *), drm_le_cmp, &thunk); INIT_LIST_HEAD(head); for (i = 0; i < count; i++) list_add_tail(ar[i], head); diff --git a/sys/libkern/qsort.c b/sys/libkern/qsort.c index 7602127a59d6..66ca826e265c 100644 --- a/sys/libkern/qsort.c +++ b/sys/libkern/qsort.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/libkern.h> #ifdef I_AM_QSORT_R -typedef int cmp_t(void *, const void *, const void *); +typedef int cmp_t(const void *, const void *, void *); #else typedef int cmp_t(const void *, const void *); #endif @@ -88,7 +88,7 @@ swapfunc(char *a, char *b, size_t n, int swaptype_long, int swaptype_int) if ((n) > 0) swapfunc(a, b, n, swaptype_long, swaptype_int) #ifdef I_AM_QSORT_R -#define CMP(t, x, y) (cmp((t), (x), (y))) +#define CMP(t, x, y) (cmp((x), (y), (t))) #else #define CMP(t, x, y) (cmp((x), (y))) #endif @@ -107,7 +107,7 @@ __unused #ifdef I_AM_QSORT_R void -qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +(qsort_r)(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk) #else #define thunk NULL void @@ -192,7 +192,7 @@ loop: SWAPINIT(long, a, es); /* Recurse on left partition, then iterate on right partition */ if (d1 > es) { #ifdef I_AM_QSORT_R - qsort_r(a, d1 / es, es, thunk, cmp); + qsort_r(a, d1 / es, es, cmp, thunk); #else qsort(a, d1 / es, es, cmp); #endif @@ -208,7 +208,7 @@ loop: SWAPINIT(long, a, es); /* Recurse on right partition, then iterate on left partition */ if (d2 > es) { #ifdef I_AM_QSORT_R - qsort_r(pn - d2, d2 / es, es, thunk, cmp); + qsort_r(pn - d2, d2 / es, es, cmp, thunk); #else qsort(pn - d2, d2 / es, es, cmp); #endif diff --git a/sys/netgraph/ng_ppp.c b/sys/netgraph/ng_ppp.c index 6c61bcda0ae3..aafed858a26b 100644 --- a/sys/netgraph/ng_ppp.c +++ b/sys/netgraph/ng_ppp.c @@ -322,7 +322,7 @@ static void ng_ppp_frag_timeout(node_p node, hook_p hook, void *arg1, static void ng_ppp_frag_checkstale(node_p node); static void ng_ppp_frag_reset(node_p node); static void ng_ppp_mp_strategy(node_p node, int len, int *distrib); -static int ng_ppp_intcmp(void *latency, const void *v1, const void *v2); +static int ng_ppp_intcmp(const void *v1, const void *v2, void *latency); static struct mbuf *ng_ppp_addproto(struct mbuf *m, uint16_t proto, int compOK); static struct mbuf *ng_ppp_cutproto(struct mbuf *m, uint16_t *proto); static struct mbuf *ng_ppp_prepend(struct mbuf *m, const void *buf, int len); @@ -2316,8 +2316,8 @@ ng_ppp_mp_strategy(node_p node, int len, int *distrib) } /* Sort active links by latency */ - qsort_r(sortByLatency, - priv->numActiveLinks, sizeof(*sortByLatency), latency, ng_ppp_intcmp); + qsort_r(sortByLatency, priv->numActiveLinks, sizeof(*sortByLatency), + ng_ppp_intcmp, latency); /* Find the interval we need (add links in sortByLatency[] order) */ for (numFragments = 1; @@ -2401,7 +2401,7 @@ ng_ppp_mp_strategy(node_p node, int len, int *distrib) * Compare two integers */ static int -ng_ppp_intcmp(void *latency, const void *v1, const void *v2) +ng_ppp_intcmp(const void *v1, const void *v2, void *latency) { const int index1 = *((const int *) v1); const int index2 = *((const int *) v2); diff --git a/sys/sys/libkern.h b/sys/sys/libkern.h index 41844fa7490e..8adeeb499984 100644 --- a/sys/sys/libkern.h +++ b/sys/sys/libkern.h @@ -163,8 +163,8 @@ void *memcchr(const void *s, int c, size_t n); void *memmem(const void *l, size_t l_len, const void *s, size_t s_len); void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); -void qsort_r(void *base, size_t nmemb, size_t size, void *thunk, - int (*compar)(void *, const void *, const void *)); +void qsort_r(void *base, size_t nmemb, size_t size, + int (*compar)(const void *, const void *, void *), void *thunk); u_long random(void); int scanc(u_int, const u_char *, const u_char *, int); int strcasecmp(const char *, const char *);