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
This commit is contained in:
parent
69d79ceb2c
commit
af3c78886f
@ -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 */
|
||||
|
||||
|
@ -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 **);
|
||||
|
@ -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 **);
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
21
lib/libc/stdlib/qsort_r_compat.c
Normal file
21
lib/libc/stdlib/qsort_r_compat.c
Normal file
@ -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);
|
@ -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
|
||||
|
92
lib/libc/tests/stdlib/qsort_r_compat_test.c
Normal file
92
lib/libc/tests/stdlib/qsort_r_compat_test.c
Normal file
@ -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());
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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 *);
|
||||
|
Loading…
x
Reference in New Issue
Block a user