From: Tobias Brunner Date: Mon, 27 Jan 2014 12:41:21 +0000 (+0100) Subject: array: Add fallback for qsort_r using thread-local value X-Git-Tag: 5.1.2rc1~7^2~30 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b3613c49a22e1156836891f3c76765044e01d684;p=thirdparty%2Fstrongswan.git array: Add fallback for qsort_r using thread-local value Cygwin for example does not support qsort_r. --- diff --git a/configure.ac b/configure.ac index 649f1814b5..76981e7b40 100644 --- a/configure.ac +++ b/configure.ac @@ -528,7 +528,7 @@ AC_CHECK_FUNC( ]) CFLAGS="$save_CFLAGS" ], - [AC_MSG_FAILURE([qsort_r not found])] + [] ) AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r) diff --git a/src/libstrongswan/collections/array.c b/src/libstrongswan/collections/array.c index ed0d12e30a..642bbb349a 100644 --- a/src/libstrongswan/collections/array.c +++ b/src/libstrongswan/collections/array.c @@ -21,6 +21,10 @@ #include "array.h" +#ifndef HAVE_QSORT_R +#include +#endif + /** * Data is an allocated block, with potentially unused head and tail: * @@ -49,6 +53,11 @@ struct array_t { void *data; }; +#ifndef HAVE_QSORT_R + /* store data to replicate qsort_r in thread local storage */ + static thread_value_t *sort_data; +#endif + /** maximum number of unused head/tail elements before cleanup */ #define ARRAY_MAX_UNUSED 32 @@ -382,11 +391,17 @@ typedef struct { #ifdef HAVE_QSORT_R_GNU static int compare_elements(const void *a, const void *b, void *arg) -#else /* HAVE_QSORT_R_BSD */ +#elif HAVE_QSORT_R_BSD static int compare_elements(void *arg, const void *a, const void *b) +#else /* !HAVE_QSORT_R */ +static int compare_elements(const void *a, const void *b) #endif { +#ifdef HAVE_QSORT_R sort_data_t *data = (sort_data_t*)arg; +#else + sort_data_t *data = sort_data->get(sort_data); +#endif if (data->array->esize) { @@ -412,9 +427,12 @@ void array_sort(array_t *array, int (*cmp)(const void*,const void*,void*), #ifdef HAVE_QSORT_R_GNU qsort_r(start, array->count, get_size(array, 1), compare_elements, &data); -#else /* HAVE_QSORT_R_BSD */ +#elif HAVE_QSORT_R_BSD qsort_r(start, array->count, get_size(array, 1), &data, compare_elements); +#else /* !HAVE_QSORT_R */ + sort_data->set(sort_data, &data); + qsort(start, array->count, get_size(array, 1), compare_elements); #endif } } @@ -531,3 +549,17 @@ void array_destroy_offset(array_t *array, size_t offset) array_invoke_offset(array, offset); array_destroy(array); } + +void arrays_init() +{ +#ifndef HAVE_QSORT_R + sort_data = thread_value_create(NULL); +#endif +} + +void arrays_deinit() +{ +#ifndef HAVE_QSORT_R + sort_data->destroy(sort_data); +#endif +} diff --git a/src/libstrongswan/collections/array.h b/src/libstrongswan/collections/array.h index c6b6fcc892..ce702ebfa7 100644 --- a/src/libstrongswan/collections/array.h +++ b/src/libstrongswan/collections/array.h @@ -251,4 +251,16 @@ void array_destroy_function(array_t *array, array_callback_t cb, void *user); */ void array_destroy_offset(array_t *array, size_t offset); + +/** + * Required on some platforms to initialize thread local value to implement + * array_sort(). + */ +void arrays_init(); + +/** + * Destroys the thread local value if required. + */ +void arrays_deinit(); + #endif /** ARRAY_H_ @}*/ diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c index 0df0c42128..8472c30a58 100644 --- a/src/libstrongswan/library.c +++ b/src/libstrongswan/library.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -142,6 +143,7 @@ void library_deinit() lib->leak_detective->destroy(lib->leak_detective); } + arrays_deinit(); threads_deinit(); backtrace_deinit(); @@ -259,6 +261,7 @@ bool library_init(char *settings, const char *namespace) backtrace_init(); threads_init(); + arrays_init(); #ifdef LEAK_DETECTIVE lib->leak_detective = leak_detective_create();