diff --git a/include/stdlib.h b/include/stdlib.h index e27f3a220c47..6976700a6c26 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -295,8 +295,8 @@ int mergesort_b(void *, size_t, size_t, int (^)(const void *, const void *)); #endif int mkostemp(char *, int); int mkostemps(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 __alloc_size(2) @@ -309,7 +309,7 @@ int sradixsort(const unsigned char **, int, const unsigned char *, void sranddev(void); void srandomdev(void); long long - strtonum(const char *, long long, long long, const char **); + strtonum(const char *, long long, long long, const char **); /* Deprecated interfaces, to be removed in FreeBSD 6.0. */ __int64_t diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c index d81acc8bfa64..48d5f2cfb64c 100644 --- a/lib/libc/gen/scandir.c +++ b/lib/libc/gen/scandir.c @@ -57,7 +57,7 @@ qsort_b(void *, size_t, size_t, void*); #define SELECT(x) select(x) #endif -static int alphasort_thunk(void *thunk, const void *p1, const void *p2); +static int alphasort_thunk(const void *p1, const void *p2, void *thunk); /* * The DIRSIZ macro is the minimum record length which will hold the directory @@ -132,7 +132,7 @@ scandir(const char *dirname, struct dirent ***namelist, qsort_b(names, nitems, sizeof(struct dirent *), (void*)dcomp); #else qsort_r(names, nitems, sizeof(struct dirent *), - &dcomp, alphasort_thunk); + alphasort_thunk, &dcomp); #endif *namelist = names; return (nitems); @@ -157,7 +157,7 @@ alphasort(const struct dirent **d1, const struct dirent **d2) } static int -alphasort_thunk(void *thunk, const void *p1, const void *p2) +alphasort_thunk(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 00f90e2f81e0..014af08e2422 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 quick_exit.c \ - radixsort.c rand.c \ + merge.c mergesort_b.c ptsname.c qsort.c qsort_r.c glibc_qsort_r.c \ + quick_exit.c radixsort.c rand.c \ random.c reallocarray.c reallocf.c realpath.c remque.c strfmon.c \ strtoimax.c \ strtol.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 a239a42018d6..8b73efa307b9 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; @@ -119,6 +118,7 @@ FBSD_1.4 { FBSD_1.5 { __cxa_thread_atexit; __cxa_thread_atexit_impl; + qsort_r; }; FBSDprivate_1.0 { diff --git a/lib/libc/stdlib/glibc_qsort_r.c b/lib/libc/stdlib/glibc_qsort_r.c new file mode 100644 index 000000000000..01f890d10a50 --- /dev/null +++ b/lib/libc/stdlib/glibc_qsort_r.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 Conrad Meyer + * 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. + */ + +#include +__FBSDID("$FreeBSD$"); + +#define I_AM_GLIBC_QSORT_R +#include "qsort.c" diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3 index af885ee5f762..5f1d86370560 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 February 20, 2013 +.Dd January 13, 2017 .Dt QSORT 3 .Os .Sh NAME @@ -61,8 +61,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 @@ -142,7 +142,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 final argument to the function .Fa compar . This allows the comparison function to access additional data without using global variables, and thus @@ -161,8 +161,9 @@ and .Fn heapsort are .Em not -stable, that is, if two members compare as equal, their order in -the sorted array is undefined. +stable. +That is, if two members compare as equal, their order in the sorted +array is undefined. The .Fn heapsort_b function behaves identically to diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c index 08816887cf79..cf7a03676fa3 100644 --- a/lib/libc/stdlib/qsort.c +++ b/lib/libc/stdlib/qsort.c @@ -35,11 +35,14 @@ __FBSDID("$FreeBSD$"); #include -#ifdef I_AM_QSORT_R +#if defined(I_AM_QSORT_R) typedef int cmp_t(void *, const void *, const void *); +#elif defined(I_AM_GLIBC_QSORT_R) +typedef int cmp_t(const void *, const void *, void *); #else typedef int cmp_t(const void *, const void *); #endif +#if defined(I_AM_QSORT_R) || defined(I_AM_GLIBC_QSORT_R) static inline char *med3(char *, char *, char *, cmp_t *, void *); static inline void swapfunc(char *, char *, int, int, int); @@ -89,31 +92,26 @@ swapfunc( char *a, char *b, int n, int swaptype_long, int swaptype_int) #define vecswap(a, b, n) \ if ((n) > 0) swapfunc(a, b, n, swaptype_long, swaptype_int) -#ifdef I_AM_QSORT_R +#if defined(I_AM_QSORT_R) #define CMP(t, x, y) (cmp((t), (x), (y))) -#else -#define CMP(t, x, y) (cmp((x), (y))) +#elif defined(I_AM_GLIBC_QSORT_R) +#define CMP(t, x, y) (cmp((x), (y), (t))) #endif static inline char * -med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk -#ifndef I_AM_QSORT_R -__unused -#endif -) +med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk) { return CMP(thunk, a, b) < 0 ? (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); } -#ifdef I_AM_QSORT_R +#if defined(I_AM_QSORT_R) void -qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) -#else -#define thunk NULL +__freebsd11_qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +#elif defined(I_AM_GLIBC_QSORT_R) void -qsort(void *a, size_t n, size_t es, cmp_t *cmp) +qsort_r(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk) #endif { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; @@ -187,10 +185,10 @@ loop: SWAPINIT(long, a, es); r = MIN(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) -#ifdef I_AM_QSORT_R - qsort_r(a, r / es, es, thunk, cmp); -#else - qsort(a, r / es, es, cmp); +#if defined(I_AM_QSORT_R) + __freebsd11_qsort_r(a, r / es, es, thunk, cmp); +#elif defined(I_AM_GLIBC_QSORT_R) + qsort_r(a, r / es, es, cmp, thunk); #endif if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ @@ -200,3 +198,16 @@ loop: SWAPINIT(long, a, es); } /* qsort(pn - r, r / es, es, cmp);*/ } +#else /* !I_AM_QSORT_R && !I_AM_GLIBC_QSORT_R */ +void +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +{ + + qsort_r(a, n, es, (int (*)(const void *, const void *, void *))cmp, + NULL); +} +#endif /* I_AM_QSORT_R || I_AM_GLIBC_QSORT_R */ + +#if defined(I_AM_QSORT_R) +__sym_compat(qsort_r, __freebsd11_qsort_r, FBSD_1.0); +#endif diff --git a/lib/libc/stdlib/qsort_r.c b/lib/libc/stdlib/qsort_r.c index f489d31c2335..a87f3187fd04 100644 --- a/lib/libc/stdlib/qsort_r.c +++ b/lib/libc/stdlib/qsort_r.c @@ -13,7 +13,7 @@ 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, + __freebsd11_qsort_r(base, nel, width, compar, (int (*)(void *, const void *, const void *)) GET_BLOCK_FUNCTION(compar)); } diff --git a/lib/libproc/proc_sym.c b/lib/libproc/proc_sym.c index a3c5e554a347..80e2d447106c 100644 --- a/lib/libproc/proc_sym.c +++ b/lib/libproc/proc_sym.c @@ -101,7 +101,7 @@ fail: } static int -symvalcomp(void *thunk, const void *a1, const void *a2) +symvalcomp(const void *a1, const void *a2, void *thunk) { struct symtab *symtab; GElf_Sym sym1, sym2; @@ -155,7 +155,7 @@ load_symtab(Elf *e, struct symtab *symtab, u_long sh_type) return (-1); for (u_int i = 0; i < nsyms; i++) symtab->index[i] = i; - qsort_r(symtab->index, nsyms, sizeof(u_int), symtab, symvalcomp); + qsort_r(symtab->index, nsyms, sizeof(u_int), symvalcomp, symtab); symtab->nsyms = nsyms; symtab->stridx = shdr.sh_link; return (0); diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c index 54bd33bc7ad7..e9cbcff555af 100644 --- a/sys/compat/linuxkpi/common/src/linux_compat.c +++ b/sys/compat/linuxkpi/common/src/linux_compat.c @@ -1374,7 +1374,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; @@ -1402,7 +1402,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 7230c91d2435..4e96d2a57079 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 19c5c9ecc8ed..834e1440f34a 100644 --- a/sys/dev/drm2/drm_linux_list_sort.c +++ b/sys/dev/drm2/drm_linux_list_sort.c @@ -36,7 +36,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; @@ -67,7 +67,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 bb0baee73c9f..9c5c8b18a87c 100644 --- a/sys/libkern/qsort.c +++ b/sys/libkern/qsort.c @@ -34,10 +34,11 @@ __FBSDID("$FreeBSD$"); #include #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 +#ifdef I_AM_QSORT_R static __inline char *med3(char *, char *, char *, cmp_t *, void *); static __inline void swapfunc(char *, char *, int, int); @@ -79,32 +80,18 @@ swapfunc(char *a, char *b, int n, int swaptype) #define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) -#ifdef I_AM_QSORT_R -#define CMP(t, x, y) (cmp((t), (x), (y))) -#else -#define CMP(t, x, y) (cmp((x), (y))) -#endif - static __inline char * med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk -#ifndef I_AM_QSORT_R __unused -#endif ) { - return CMP(thunk, a, b) < 0 ? - (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) - :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); + return cmp(a, b, thunk) < 0 ? + (cmp(b, c, thunk) < 0 ? b : (cmp(a, c, thunk) < 0 ? c : a )) + :(cmp(b, c, thunk) > 0 ? b : (cmp(a, c, thunk) < 0 ? a : c )); } -#ifdef I_AM_QSORT_R void -qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) -#else -#define thunk NULL -void -qsort(void *a, size_t n, size_t es, cmp_t *cmp) -#endif +qsort_r(void *a, size_t n, size_t es, cmp_t *cmp, void *thunk) { char *pa, *pb, *pc, *pd, *pl, *pm, *pn; int d, r, swaptype, swap_cnt; @@ -113,7 +100,7 @@ loop: SWAPINIT(a, es); swap_cnt = 0; if (n < 7) { for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + for (pl = pm; pl > (char *)a && cmp(pl - es, pl, thunk) > 0; pl -= es) swap(pl, pl - es); return; @@ -135,7 +122,7 @@ loop: SWAPINIT(a, es); pc = pd = (char *)a + (n - 1) * es; for (;;) { - while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) { + while (pb <= pc && (r = cmp(pb, a, thunk)) <= 0) { if (r == 0) { swap_cnt = 1; swap(pa, pb); @@ -143,7 +130,7 @@ loop: SWAPINIT(a, es); } pb += es; } - while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) { + while (pb <= pc && (r = cmp(pc, a, thunk)) >= 0) { if (r == 0) { swap_cnt = 1; swap(pc, pd); @@ -160,7 +147,7 @@ loop: SWAPINIT(a, es); } if (swap_cnt == 0) { /* Switch to insertion sort */ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) - for (pl = pm; pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + for (pl = pm; pl > (char *)a && cmp(pl - es, pl, thunk) > 0; pl -= es) swap(pl, pl - es); return; @@ -172,11 +159,7 @@ loop: SWAPINIT(a, es); r = min(pd - pc, pn - pd - es); vecswap(pb, pn - r, r); if ((r = pb - pa) > es) -#ifdef I_AM_QSORT_R - qsort_r(a, r / es, es, thunk, cmp); -#else - qsort(a, r / es, es, cmp); -#endif + qsort_r(a, r / es, es, cmp, thunk); if ((r = pd - pc) > es) { /* Iterate rather than recurse to save stack space */ a = pn - r; @@ -184,3 +167,12 @@ loop: SWAPINIT(a, es); goto loop; } } +#else /* !I_AM_QSORT_R */ +void +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +{ + + qsort_r(a, n, es, (int (*)(const void *, const void *, void *))cmp, + NULL); +} +#endif /* I_AM_QSORT_R */ diff --git a/sys/netgraph/ng_ppp.c b/sys/netgraph/ng_ppp.c index 3e27237642a1..887884a2477d 100644 --- a/sys/netgraph/ng_ppp.c +++ b/sys/netgraph/ng_ppp.c @@ -320,7 +320,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); @@ -2318,7 +2318,7 @@ 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); + priv->numActiveLinks, sizeof(*sortByLatency), ng_ppp_intcmp, latency); /* Find the interval we need (add links in sortByLatency[] order) */ for (numFragments = 1; @@ -2402,7 +2402,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 28ab3df4a1f5..25186b41e991 100644 --- a/sys/sys/libkern.h +++ b/sys/sys/libkern.h @@ -127,8 +127,8 @@ int memcmp(const void *b1, const void *b2, size_t len); 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); void srandom(u_long);