From af3c78886fd8d4ca5eebdbe581a459a6f6d29d6a Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Fri, 30 Sep 2022 15:26:30 -0700 Subject: 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 --- 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 ++-- 6 files changed, 19 insertions(+), 20 deletions(-) (limited to 'sys') 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 #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 *); -- cgit v1.3