diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h index f79f3649c..48f8d9a86 100644 --- a/include/arch/darwin-x86/AndroidConfig.h +++ b/include/arch/darwin-x86/AndroidConfig.h @@ -305,4 +305,14 @@ */ #define HAVE_PRINTF_ZD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 1 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 0 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h index a8176f4b6..4bc555970 100644 --- a/include/arch/freebsd-x86/AndroidConfig.h +++ b/include/arch/freebsd-x86/AndroidConfig.h @@ -363,4 +363,14 @@ */ #define HAVE_PRINTF_ZD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 1 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 0 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h index b8e871356..233752b3d 100644 --- a/include/arch/linux-arm/AndroidConfig.h +++ b/include/arch/linux-arm/AndroidConfig.h @@ -361,4 +361,14 @@ */ #define HAVE_PRINTF_ZD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 0 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 0 + #endif /* _ANDROID_CONFIG_H */ diff --git a/include/arch/linux-ppc/AndroidConfig.h b/include/arch/linux-ppc/AndroidConfig.h index 774c458ab..ae2569bfa 100644 --- a/include/arch/linux-ppc/AndroidConfig.h +++ b/include/arch/linux-ppc/AndroidConfig.h @@ -323,4 +323,14 @@ */ #define HAVE_PREAD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 0 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 1 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h index cdfa2ac93..818b62824 100644 --- a/include/arch/linux-sh/AndroidConfig.h +++ b/include/arch/linux-sh/AndroidConfig.h @@ -366,4 +366,14 @@ */ #define HAVE_PRINTF_ZD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 0 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 0 + #endif /* _ANDROID_CONFIG_H */ diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h index 65216997f..e1ba3ed2a 100644 --- a/include/arch/linux-x86/AndroidConfig.h +++ b/include/arch/linux-x86/AndroidConfig.h @@ -333,4 +333,14 @@ */ #define HAVE_PRINTF_ZD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 0 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 1 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h index 9efb81a6e..ab5389238 100644 --- a/include/arch/target_linux-x86/AndroidConfig.h +++ b/include/arch/target_linux-x86/AndroidConfig.h @@ -350,4 +350,14 @@ */ #define HAVE_PRINTF_ZD 1 +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 0 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 0 + #endif /* _ANDROID_CONFIG_H */ diff --git a/include/arch/windows/AndroidConfig.h b/include/arch/windows/AndroidConfig.h index 445e75415..0274da547 100644 --- a/include/arch/windows/AndroidConfig.h +++ b/include/arch/windows/AndroidConfig.h @@ -338,4 +338,14 @@ */ /* #define HAVE_PRINTF_ZD 1 */ +/* + * Define to 1 if provides qsort_r() with a BSD style function prototype. + */ +#define HAVE_BSD_QSORT_R 0 + +/* + * Define to 1 if provides qsort_r() with a GNU style function prototype. + */ +#define HAVE_GNU_QSORT_R 0 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/cutils/qsort_r_compat.h b/include/cutils/qsort_r_compat.h new file mode 100644 index 000000000..479a1ab38 --- /dev/null +++ b/include/cutils/qsort_r_compat.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Provides a portable version of qsort_r, called qsort_r_compat, which is a + * reentrant variant of qsort that passes a user data pointer to its comparator. + * This implementation follows the BSD parameter convention. + */ + +#ifndef _LIBS_CUTILS_QSORT_R_COMPAT_H +#define _LIBS_CUTILS_QSORT_R_COMPAT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, + int (*compar)(void*, const void* , const void* )); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBS_CUTILS_QSORT_R_COMPAT_H diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 380973373..0d4916534 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -46,6 +46,7 @@ commonSources := \ record_stream.c \ process_name.c \ properties.c \ + qsort_r_compat.c \ threads.c \ sched_policy.c \ iosched_policy.c \ diff --git a/libcutils/qsort_r_compat.c b/libcutils/qsort_r_compat.c new file mode 100644 index 000000000..8971cb5bc --- /dev/null +++ b/libcutils/qsort_r_compat.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#if HAVE_BSD_QSORT_R + +/* + * BSD qsort_r parameter order is as we have defined here. + */ + +void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, + int (*compar)(void*, const void* , const void*)) { + qsort_r(base, nel, width, thunk, compar); +} + +#elif HAVE_GNU_QSORT_R + +/* + * GNU qsort_r parameter order places the thunk parameter last. + */ + +struct compar_data { + void* thunk; + int (*compar)(void*, const void* , const void*); +}; + +static int compar_wrapper(const void* a, const void* b, void* data) { + struct compar_data* compar_data = (struct compar_data*)data; + return compar_data->compar(compar_data->thunk, a, b); +} + +void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, + int (*compar)(void*, const void* , const void*)) { + struct compar_data compar_data; + compar_data.thunk = thunk; + compar_data.compar = compar; + qsort_r(base, nel, width, compar_wrapper, &compar_data); +} + +#else + +/* + * Emulate qsort_r using thread local storage to access the thunk data. + */ + +#include + +static thread_store_t compar_data_key = THREAD_STORE_INITIALIZER; + +struct compar_data { + void* thunk; + int (*compar)(void*, const void* , const void*); +}; + +static int compar_wrapper(const void* a, const void* b) { + struct compar_data* compar_data = (struct compar_data*)thread_store_get(&compar_data_key); + return compar_data->compar(compar_data->thunk, a, b); +} + +void qsort_r_compat(void* base, size_t nel, size_t width, void* thunk, + int (*compar)(void*, const void* , const void*)) { + struct compar_data compar_data; + compar_data.thunk = thunk; + compar_data.compar = compar; + thread_store_set(&compar_data_key, &compar_data, NULL); + qsort(base, nel, width, compar_wrapper); +} + +#endif