Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102788077
D17083.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
17 KB
Referenced Files
None
Subscribers
None
D17083.diff
View Options
diff --git a/include/stdlib.h b/include/stdlib.h
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -311,8 +311,8 @@
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 @@
__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
--- a/lib/libc/gen/scandir-compat11.c
+++ b/lib/libc/gen/scandir-compat11.c
@@ -58,8 +58,8 @@
#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 @@
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 @@
}
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
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -63,7 +63,7 @@
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 @@
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 @@
}
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
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -11,8 +11,8 @@
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
--- a/lib/libc/stdlib/Symbol.map
+++ b/lib/libc/stdlib/Symbol.map
@@ -49,7 +49,6 @@
lfind;
mergesort;
putenv;
- qsort_r;
qsort;
radixsort;
sradixsort;
@@ -130,6 +129,7 @@
FBSD_1.7 {
clearenv;
+ qsort_r;
};
FBSDprivate_1.0 {
diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3
--- 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 @@
.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 @@
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
--- a/lib/libc/stdlib/qsort.c
+++ b/lib/libc/stdlib/qsort.c
@@ -42,6 +42,8 @@
#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 @@
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 @@
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 @@
*/
#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 @@
#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
--- 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.c b/lib/libc/stdlib/qsort_r_compat.c
copy from lib/libc/stdlib/qsort_r.c
copy to lib/libc/stdlib/qsort_r_compat.c
--- a/lib/libc/stdlib/qsort_r.c
+++ b/lib/libc/stdlib/qsort_r_compat.c
@@ -5,7 +5,7 @@
* $FreeBSD$
*/
#include "block_abi.h"
-#define I_AM_QSORT_R
+#define I_AM_QSORT_R_COMPAT
#include "qsort.c"
typedef DECLARE_BLOCK(int, qsort_block, const void *, const void *);
@@ -13,7 +13,9 @@
void
qsort_b(void *base, size_t nel, size_t width, qsort_block compar)
{
- qsort_r(base, nel, width, 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
--- a/lib/libc/tests/stdlib/Makefile
+++ b/lib/libc/tests/stdlib/Makefile
@@ -8,6 +8,7 @@
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_test.c b/lib/libc/tests/stdlib/qsort_r_compat_test.c
copy from lib/libc/tests/stdlib/qsort_r_test.c
copy to lib/libc/tests/stdlib/qsort_r_compat_test.c
--- a/lib/libc/tests/stdlib/qsort_r_test.c
+++ b/lib/libc/tests/stdlib/qsort_r_compat_test.c
@@ -26,7 +26,7 @@
*/
/*
- * Test for qsort_r(3) routine.
+ * Test for historical qsort_r(3) routine.
*/
#include <sys/cdefs.h>
@@ -56,8 +56,8 @@
return (0);
}
-ATF_TC_WITHOUT_HEAD(qsort_r_test);
-ATF_TC_BODY(qsort_r_test, tc)
+ATF_TC_WITHOUT_HEAD(qsort_r_compat_test);
+ATF_TC_BODY(qsort_r_compat_test, tc)
{
int testvector[IVEC_LEN];
int sresvector[IVEC_LEN];
@@ -86,7 +86,7 @@
ATF_TP_ADD_TCS(tp)
{
- ATF_TP_ADD_TC(tp, qsort_r_test);
+ 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
--- a/lib/libc/tests/stdlib/qsort_r_test.c
+++ b/lib/libc/tests/stdlib/qsort_r_test.c
@@ -40,7 +40,7 @@
#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 @@
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
--- a/lib/libproc/proc_sym.c
+++ b/lib/libproc/proc_sym.c
@@ -105,7 +105,7 @@
};
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 @@
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
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -2562,7 +2562,7 @@
};
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 @@
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
--- a/sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c
+++ b/sys/dev/bhnd/nvram/bhnd_nvram_store_subr.c
@@ -59,8 +59,7 @@
#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 @@
/* 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_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
--- a/sys/dev/drm2/drm_linux_list_sort.c
+++ b/sys/dev/drm2/drm_linux_list_sort.c
@@ -37,7 +37,7 @@
};
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 @@
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
--- a/sys/libkern/qsort.c
+++ b/sys/libkern/qsort.c
@@ -36,7 +36,7 @@
#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 @@
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 @@
#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 @@
/* 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 @@
/* 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
--- a/sys/netgraph/ng_ppp.c
+++ b/sys/netgraph/ng_ppp.c
@@ -322,7 +322,7 @@
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 @@
}
/* 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 @@
* 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
--- a/sys/sys/libkern.h
+++ b/sys/sys/libkern.h
@@ -163,8 +163,8 @@
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 *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 18, 5:11 AM (21 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14690188
Default Alt Text
D17083.diff (17 KB)
Attached To
Mode
D17083: Alter the prototype of qsort_r(3) to match POSIX, which adopted the glibc-based interface.
Attached
Detach File
Event Timeline
Log In to Comment