summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--portability/meson.build1
-rw-r--r--portability/qsort_r.c26
-rw-r--r--portability/stdlib.h7
3 files changed, 34 insertions, 0 deletions
diff --git a/portability/meson.build b/portability/meson.build
index ae8f6bc..d077345 100644
--- a/portability/meson.build
+++ b/portability/meson.build
@@ -9,6 +9,7 @@ check_functions = [
['strlcpy', 'strlcpy.c', 'NEED_STRLCPY', 'string.h'],
['pipe2', 'pipe2.c', 'NEED_PIPE2', 'unistd.h'],
['mknodat', 'mknodat.c', 'NEED_MKNODAT', 'sys/stat.h'],
+ ['qsort_r', 'qsort_r.c', 'NEED_QSORT_R', 'stdlib.h'],
]
diff --git a/portability/qsort_r.c b/portability/qsort_r.c
new file mode 100644
index 0000000..7c5df27
--- /dev/null
+++ b/portability/qsort_r.c
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+
+struct qsortr_ctx {
+ int (*compar)(const void *, const void *, void *);
+ void *arg;
+};
+
+static __thread struct qsortr_ctx *__ctx;
+
+static int cmp_wrapper(const void *a, const void *b)
+{
+ return __ctx->compar(a, b, __ctx->arg);
+}
+
+void qsort_r(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *),
+ void *arg)
+{
+ struct qsortr_ctx ctx = {
+ .compar = compar,
+ .arg = arg,
+ };
+ __ctx = &ctx;
+ qsort(base, nmemb, size, cmp_wrapper);
+ __ctx = 0;
+}
diff --git a/portability/stdlib.h b/portability/stdlib.h
new file mode 100644
index 0000000..6254c7c
--- /dev/null
+++ b/portability/stdlib.h
@@ -0,0 +1,7 @@
+#include_next <stdlib.h>
+
+#ifdef NEED_QSORT_R
+void qsort_r(void *base, size_t nmemb, size_t size,
+ int (*compar)(const void *, const void *, void *),
+ void *arg);
+#endif