From 8351950deef456c65601b5f0cc0ab4511a67ee70 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Thu, 15 Jul 2010 06:34:32 +0000 Subject: [PATCH] Add native Windows thread support instead of using pthread (less overhead). On other OS, pthread is still used by default. Pass --enable-win32-threads to activate thread support on Windows. SVN revision: 50262 --- legacy/eet/ChangeLog | 6 + legacy/eet/Makefile.am | 8 ++ legacy/eet/configure.ac | 15 ++- legacy/eet/eet.pc.in | 2 +- legacy/eet/m4/efl_pthread.m4 | 130 --------------------- legacy/eet/m4/efl_threads.m4 | 189 +++++++++++++++++++++++++++++++ legacy/eet/src/lib/eet_lib.c | 53 ++++++--- legacy/eet/src/tests/eet_suite.c | 68 +++++++++-- 8 files changed, 315 insertions(+), 156 deletions(-) delete mode 100644 legacy/eet/m4/efl_pthread.m4 create mode 100644 legacy/eet/m4/efl_threads.m4 diff --git a/legacy/eet/ChangeLog b/legacy/eet/ChangeLog index 92c57971b5..735ee4920d 100644 --- a/legacy/eet/ChangeLog +++ b/legacy/eet/ChangeLog @@ -399,3 +399,9 @@ * Moved Eet.h into $includedir/eet-MAJOR_VERSION/ +2010-07-15 Vincent Torri + + * Add native Windows thread support instead of using pthread + (less overhead). On other OS, pthread is still used by default. + Pass --enable-win32-threads to activate thread support on + Windows. diff --git a/legacy/eet/Makefile.am b/legacy/eet/Makefile.am index 3cd86200c0..1d8eacb17c 100644 --- a/legacy/eet/Makefile.am +++ b/legacy/eet/Makefile.am @@ -31,6 +31,14 @@ autogen.sh \ eet.pc.in \ eet.spec.in \ eet.spec \ +m4/ac_attribute.m4 \ +m4/ac_path_generic.m4 \ +m4/efl_binary.m4 \ +m4/efl_coverage.m4 \ +m4/efl_doxygen.m4 \ +m4/efl_fnmatch.m4 \ +m4/efl_tests.m4 \ +m4/efl_threads.m4 \ README.in \ README diff --git a/legacy/eet/configure.ac b/legacy/eet/configure.ac index 80639c0170..a5b407693a 100644 --- a/legacy/eet/configure.ac +++ b/legacy/eet/configure.ac @@ -322,7 +322,18 @@ AC_MSG_RESULT(${have_signature}) # pthread library -EFL_CHECK_PTHREAD(["no"], [have_pthread="yes"], [have_pthread="no"]) +EFL_CHECK_THREADS(["no"], + [ + if test "x${_efl_have_posix_threads}" = "xyes" ; then + have_threads="POSIX" + else + if test "x${_efl_have_win32_threads}" = "xyes" ; then + have_threads="Win32" + else + have_threads="no" + fi + fi], + [have_threads="no"]) ### Checks for header files @@ -461,7 +472,7 @@ if test "x${have_gnutls}" = "xyes" || test "x${have_openssl}" = "xyes" ; then echo " Cipher support.....: ${have_cipher}" echo " Signature..........: ${have_signature}" fi -echo " Thread Support.......: ${have_pthread}" +echo " Thread Support.......: ${have_threads}" echo echo " Old eet file format..: ${old_eet_file_format}" echo diff --git a/legacy/eet/eet.pc.in b/legacy/eet/eet.pc.in index f7a3bf1097..30a926f474 100644 --- a/legacy/eet/eet.pc.in +++ b/legacy/eet/eet.pc.in @@ -8,6 +8,6 @@ Description: Library for speedy data storage, retrieval, and compression @pkgconfig_requires_private@: @requirement_eet@ Version: @VERSION@ Libs: -L${libdir} -leet -Libs.private: @EET_LIBS@ @EFL_FNMATCH_LIBS@ @LIBGCRYPT_LIBS@ -ljpeg -lz -lm +Libs.private: @EET_LIBS@ @EFL_FNMATCH_LIBS@ @LIBGCRYPT_LIBS@ @EFL_PTHREAD_LIBS@ -ljpeg -lz -lm Cflags: -I${includedir}/eet-@VMAJ@ Cflags.private: @LIBGCRYPT_CFLAGS@ diff --git a/legacy/eet/m4/efl_pthread.m4 b/legacy/eet/m4/efl_pthread.m4 deleted file mode 100644 index b90a045618..0000000000 --- a/legacy/eet/m4/efl_pthread.m4 +++ /dev/null @@ -1,130 +0,0 @@ -dnl Copyright (C) 2010 Vincent Torri -dnl That code is public domain and can be freely used or copied. - -dnl Macro that check if several pthread library is available or not. - -dnl Usage: EFL_CHECK_PTHREAD(want_pthread_spin[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Call AC_SUBST(EFL_PTHREAD_CFLAGS) -dnl Call AC_SUBST(EFL_PTHREAD_LIBS) -dnl Define EFL_HAVE_PTHREAD -dnl Define EFL_HAVE_PTHREAD_SPINLOCK - -AC_DEFUN([EFL_CHECK_PTHREAD], -[ - -dnl configure option - -AC_ARG_ENABLE([pthread], - [AC_HELP_STRING([--disable-pthread], [enable POSIX threads code @<:@default=auto@:>@])], - [ - if test "x${enableval}" = "xyes" ; then - _efl_enable_pthread="yes" - else - _efl_enable_pthread="no" - fi - ], - [_efl_enable_pthread="auto"]) - -AC_MSG_CHECKING([whether to build POSIX threads code]) -AC_MSG_RESULT([${_efl_enable_pthread}]) - -dnl check if the compiler supports pthreads - -case "$host_os" in - mingw*) - _efl_pthread_cflags="" - _efl_pthread_libs="-lpthreadGC2" - ;; - solaris*) - _efl_pthread_cflags="-mt" - _efl_pthread_libs="-mt" - ;; - *) - _efl_pthread_cflags="-pthread" - _efl_pthread_libs="-pthread" - ;; -esac - -_efl_have_pthread="no" - -if test "x${_efl_enable_pthread}" = "xyes" || test "x${_efl_enable_pthread}" = "xauto" ; then - - SAVE_CFLAGS=${CFLAGS} - CFLAGS="${CFLAGS} ${_efl_pthread_cflags}" - SAVE_LIBS=${LIBS} - LIBS="${LIBS} ${_efl_pthread_libs}" - AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include - ]], - [[ -pthread_t id; -id = pthread_self(); - ]])], - [_efl_have_pthread="yes"], - [_efl_have_pthread="no"]) - CFLAGS=${SAVE_CFLAGS} - LIBS=${SAVE_LIBS} - -fi - -AC_MSG_CHECKING([whether system support POSIX threads]) -AC_MSG_RESULT([${_efl_have_pthread}]) -if test "$x{_efl_enable_pthread}" = "xyes" && test "x${_efl_have_pthread}" = "xno"; then - AC_MSG_ERROR([pthread support requested but not found.]) -fi - -EFL_PTHREAD_CFLAGS="" -EFL_PTHREAD_LIBS="" -if test "x${_efl_have_pthread}" = "xyes" ; then - EFL_PTHREAD_CFLAGS=${_efl_pthread_cflags} - EFL_PTHREAD_LIBS=${_efl_pthread_libs} -fi - -AC_SUBST(EFL_PTHREAD_CFLAGS) -AC_SUBST(EFL_PTHREAD_LIBS) - -if test "x${_efl_have_pthread}" = "xyes" ; then - AC_DEFINE(EFL_HAVE_PTHREAD, 1, [Define to mention that POSIX threads are supported]) -fi - -dnl check if the compiler supports pthreads spinlock - -_efl_have_pthread_spinlock="no" - -if test "x${_efl_have_pthread}" = "xyes" && test "x$1" = "xyes" ; then - - SAVE_CFLAGS=${CFLAGS} - CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}" - SAVE_LIBS=${LIBS} - LIBS="${LIBS} ${EFL_PTHREAD_LIBS}" - AC_LINK_IFELSE( - [AC_LANG_PROGRAM([[ -#include - ]], - [[ -pthread_spinlock_t lock; -int res; -res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE); - ]])], - [_efl_have_pthread_spinlock="yes"], - [_efl_have_pthread_spinlock="no"]) - CFLAGS=${SAVE_CFLAGS} - LIBS=${SAVE_LIBS} - -fi - -AC_MSG_CHECKING([whether to build POSIX threads spinlock code]) -AC_MSG_RESULT([${_efl_have_pthread_spinlock}]) -if test "x${_efl_enable_pthread}" = "xyes" && test "x${_efl_have_pthread_spinlock}" = "xno" && test "x$1" = "xyes" ; then - AC_MSG_WARN([pthread support requested but spinlocks are not supported]) -fi - -if test "x${_efl_have_pthread_spinlock}" = "xyes" ; then - AC_DEFINE(EFL_HAVE_PTHREAD_SPINLOCK, 1, [Define to mention that POSIX threads spinlocks are supported]) -fi - -AS_IF([test "x$_efl_have_pthread" = "xyes"], [$2], [$3]) -AS_IF([test "x$_efl_have_pthread_spinlock" = "xyes"], [$4], [$5]) - -]) diff --git a/legacy/eet/m4/efl_threads.m4 b/legacy/eet/m4/efl_threads.m4 new file mode 100644 index 0000000000..8866e3720a --- /dev/null +++ b/legacy/eet/m4/efl_threads.m4 @@ -0,0 +1,189 @@ +dnl Copyright (C) 2010 Vincent Torri +dnl That code is public domain and can be freely used or copied. + +dnl Macro that check if POSIX or Win32 threads library is available or not. + +dnl Usage: EFL_CHECK_THREADS(want_pthread_spin[, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Call AC_SUBST(EFL_PTHREAD_CFLAGS) +dnl Call AC_SUBST(EFL_PTHREAD_LIBS) +dnl Define EFL_HAVE_POSIX_THREADS or EFL_HAVE_WIN32_THREADS, and EFL_HAVE_THREADS +dnl Define EFL_HAVE_POSIX_THREADS_SPINLOCK + +AC_DEFUN([EFL_CHECK_THREADS], +[ + +dnl configure option + +AC_ARG_ENABLE([posix-threads], + [AC_HELP_STRING([--disable-posix-threads], [enable POSIX threads code @<:@default=auto@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_posix_threads="yes" + else + _efl_enable_posix_threads="no" + fi + ], + [_efl_enable_posix_threads="auto"]) + +AC_MSG_CHECKING([whether to build POSIX threads code]) +AC_MSG_RESULT([${_efl_enable_posix_threads}]) + +AC_ARG_ENABLE([win32-threads], + [AC_HELP_STRING([--disable-win32-threads], [enable Win32 threads code @<:@default=no@:>@])], + [ + if test "x${enableval}" = "xyes" ; then + _efl_enable_win32_threads="yes" + else + _efl_enable_win32_threads="no" + fi + ], + [_efl_enable_win32_threads="no"]) + +AC_MSG_CHECKING([whether to build Windows threads code]) +AC_MSG_RESULT([${_efl_enable_win32_threads}]) + +dnl +dnl * no + no +dnl * yes + no : win32: error, other : pthread +dnl * yes + yes : win32 : wthread, other : pthread +dnl * no + yes : win32 : wthread, other : error + +if test "x${_efl_enable_posix_threads}" = "xyes" && test "x${_efl_enable_win32_threads}" = "xyes" ; then + case "$host_os" in + mingw*) + _efl_enable_posix_threads=no + ;; + *) + _efl_enable_win32_threads=no + ;; + esac +fi + +if test "x${_efl_enable_win32_threads}" = "xyes" ; then + case "$host_os" in + mingw*) + ;; + *) + AC_MSG_ERROR([Win32 threads support requested but non Windows system found.]) + ;; + esac +fi + +if test "x${_efl_enable_posix_threads}" = "xyes" ; then + case "$host_os" in + mingw*) + AC_MSG_ERROR([POSIX threads support requested but Windows system found.]) + ;; + *) + ;; + esac +fi + +dnl check if the compiler supports POSIX threads + +case "$host_os" in + mingw*) + ;; + solaris*) + _efl_thread_cflags="-mt" + _efl_thread_libs="-mt" + ;; + *) + _efl_thread_cflags="-pthread" + _efl_thread_libs="-pthread" + ;; +esac + +_efl_have_posix_threads="no" +_efl_have_win32_threads="no" + +if test "x${_efl_enable_posix_threads}" = "xyes" || test "x${_efl_enable_posix_threads}" = "xauto" ; then + + SAVE_CFLAGS=${CFLAGS} + CFLAGS="${CFLAGS} ${_efl_threads_cflags}" + SAVE_LIBS=${LIBS} + LIBS="${LIBS} ${_efl_threads_libs}" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#include + ]], + [[ +pthread_t id; +id = pthread_self(); + ]])], + [_efl_have_posix_threads="yes"], + [_efl_have_posix_threads="no"]) + CFLAGS=${SAVE_CFLAGS} + LIBS=${SAVE_LIBS} + +fi + +AC_MSG_CHECKING([whether system support POSIX threads]) +AC_MSG_RESULT([${_efl_have_posix_threads}]) +if test "$x{_efl_enable_posix_threads}" = "xyes" && test "x${_efl_have_posix_threads}" = "xno"; then + AC_MSG_ERROR([POSIX threads support requested but not found.]) +fi + +EFL_PTHREAD_CFLAGS="" +EFL_PTHREAD_LIBS="" +if test "x${_efl_have_posix_threads}" = "xyes" ; then + EFL_PTHREAD_CFLAGS=${_efl_thread_cflags} + EFL_PTHREAD_LIBS=${_efl_thread_libs} +fi + +AC_SUBST(EFL_PTHREAD_CFLAGS) +AC_SUBST(EFL_PTHREAD_LIBS) + +if test "x${_efl_have_posix_threads}" = "xyes" ; then + AC_DEFINE([EFL_HAVE_POSIX_THREADS], [1], [Define to mention that POSIX threads are supported]) +fi + +dnl check if the compiler supports pthreads spinlock + +_efl_have_posix_threads_spinlock="no" + +if test "x${_efl_have_posix_threads}" = "xyes" && test "x$1" = "xyes" ; then + + SAVE_CFLAGS=${CFLAGS} + CFLAGS="${CFLAGS} ${EFL_PTHREAD_CFLAGS}" + SAVE_LIBS=${LIBS} + LIBS="${LIBS} ${EFL_PTHREAD_LIBS}" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([[ +#include + ]], + [[ +pthread_spinlock_t lock; +int res; +res = pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE); + ]])], + [_efl_have_posix_threads_spinlock="yes"], + [_efl_have_posix_threads_spinlock="no"]) + CFLAGS=${SAVE_CFLAGS} + LIBS=${SAVE_LIBS} + +fi + +AC_MSG_CHECKING([whether to build POSIX threads spinlock code]) +AC_MSG_RESULT([${_efl_have_posix_threads_spinlock}]) +if test "x${_efl_enable_posix_threads}" = "xyes" && test "x${_efl_have_posix_threads_spinlock}" = "xno" && test "x$1" = "xyes" ; then + AC_MSG_WARN([POSIX threads support requested but spinlocks are not supported]) +fi + +if test "x${_efl_have_posix_threads_spinlock}" = "xyes" ; then + AC_DEFINE([EFL_HAVE_POSIX_THREADS_SPINLOCK], [1], [Define to mention that POSIX threads spinlocks are supported]) +fi + +if test "x${_efl_enable_win32_threads}" = "xyes" ; then + _efl_have_win32_threads="yes" + AC_DEFINE([EFL_HAVE_WIN32_THREADS], [1], [Define to mention that Win32 threads are supported]) +fi + +if test "x${_efl_have_posix_threads}" = "xyes" || test "x${_efl_have_win32_threads}" = "xyes" ; then + AC_DEFINE([EFL_HAVE_THREADS], [1], [Define to mention that POSIX or Win32 threads are supported]) +fi + +AS_IF([test "x$_efl_have_posix_threads" = "xyes" || test "x$_efl_have_win32_threads" = "xyes"], [$2], [$3]) +AS_IF([test "x$_efl_have_posix_threads_spinlock" = "xyes"], [$4], [$5]) + +]) diff --git a/legacy/eet/src/lib/eet_lib.c b/legacy/eet/src/lib/eet_lib.c index 651e15e147..601aa22ead 100644 --- a/legacy/eet/src/lib/eet_lib.c +++ b/legacy/eet/src/lib/eet_lib.c @@ -60,7 +60,7 @@ void *alloca (size_t); # include #endif -#ifdef EFL_HAVE_PTHREAD +#ifdef EFL_HAVE_POSIX_THREADS # include #endif @@ -109,8 +109,12 @@ struct _Eet_File time_t mtime; -#ifdef EFL_HAVE_PTHREAD +#ifdef EFL_HAVE_THREADS +# ifdef EFL_HAVE_POSIX_THREADS pthread_mutex_t file_lock; +# else + HANDLE file_lock; +# endif #endif unsigned char writes_pending : 1; @@ -227,28 +231,45 @@ static int read_data_from_disk(Eet_File *ef, Eet_File_Node *efn, void *buf, int static Eet_Error eet_internal_close(Eet_File *ef, Eina_Bool locked); -#ifdef EFL_HAVE_PTHREAD +#ifdef EFL_HAVE_THREADS + +# ifdef EFL_HAVE_POSIX_THREADS + static pthread_mutex_t eet_cache_lock = PTHREAD_MUTEX_INITIALIZER; -#define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock); -#define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock); +# define LOCK_CACHE pthread_mutex_lock(&eet_cache_lock) +# define UNLOCK_CACHE pthread_mutex_unlock(&eet_cache_lock) -#define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL); -#define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock); -#define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock); -#define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock); +# define INIT_FILE(File) pthread_mutex_init(&File->file_lock, NULL) +# define LOCK_FILE(File) pthread_mutex_lock(&File->file_lock) +# define UNLOCK_FILE(File) pthread_mutex_unlock(&File->file_lock) +# define DESTROY_FILE(File) pthread_mutex_destroy(&File->file_lock) + +# else /* EFL_HAVE_WIN32_THREADS */ + +static HANDLE eet_cache_lock = NULL; + +# define LOCK_CACHE WaitForSingleObject(eet_cache_lock, INFINITE) +# define UNLOCK_CACHE ReleaseMutex(eet_cache_lock) + +# define INIT_FILE(File) File->file_lock = CreateMutex(NULL, FALSE, NULL) +# define LOCK_FILE(File) WaitForSingleObject(File->file_lock, INFINITE) +# define UNLOCK_FILE(File) ReleaseMutex(File->file_lock) +# define DESTROY_FILE(File) CloseHandle(File->file_lock) + +# endif /* EFL_HAVE_WIN32_THREADS */ #else -#define LOCK_CACHE ; -#define UNLOCK_CACHE ; +# define LOCK_CACHE do {} while (0) +# define UNLOCK_CACHE do {} while (0) -#define INIT_FILE(File) ; -#define LOCK_FILE(File) ; -#define UNLOCK_FILE(File) ; -#define DESTROY_FILE(File) ; +# define INIT_FILE(File) do {} while (0) +# define LOCK_FILE(File) do {} while (0) +# define UNLOCK_FILE(File) do {} while (0) +# define DESTROY_FILE(File) do {} while (0) -#endif +#endif /* EFL_HAVE_THREADS */ /* cache. i don't expect this to ever be large, so arrays will do */ static int eet_writers_num = 0; diff --git a/legacy/eet/src/tests/eet_suite.c b/legacy/eet/src/tests/eet_suite.c index 576e1531d7..4da3b43c7e 100644 --- a/legacy/eet/src/tests/eet_suite.c +++ b/legacy/eet/src/tests/eet_suite.c @@ -1,3 +1,8 @@ + +#ifdef HAVE_CONFIG_H +# include +#endif + #include #include #include @@ -6,14 +11,13 @@ #include #include #include -#include + +#ifdef EFL_HAVE_POSIX_THREADS +# include +#endif #include -#ifdef HAVE_CONFIG_H -# include -#endif - #include #include "eet_suite.h" @@ -1428,7 +1432,12 @@ START_TEST(eet_cipher_decipher_simple) } END_TEST +#ifdef EFL_HAVE_THREADS + static Eina_Bool open_worker_stop; + +# ifdef EFL_HAVE_POSIX_THREADS + static void* open_close_worker(void* path) { @@ -1450,6 +1459,31 @@ open_close_worker(void* path) pthread_exit(NULL); } +# else + +static unsigned int __stdcall +open_close_worker(void *path) +{ + while (!open_worker_stop) + { + Eet_File *ef = eet_open((char const *)path, EET_FILE_MODE_READ); + if (ef == NULL) + { + _endthreadex(-1); + } + else + { + Eet_Error err_code = eet_close(ef); + if (err_code != EET_ERROR_NONE) + _endthreadex(-2); + } + } + + _endthreadex(0); +} + +# endif + START_TEST(eet_cache_concurrency) { char *file = strdup("/tmp/eet_suite_testXXXXXX"); @@ -1457,6 +1491,13 @@ START_TEST(eet_cache_concurrency) Eet_File *ef; void *thread_ret; unsigned int n; +# ifdef EFL_HAVE_POSIX_THREADS + pthread_t thread; +# else + uintptr_t thread; + unsigned int thread_id; + DWORD ret; +# endif eet_init(); @@ -1468,9 +1509,11 @@ START_TEST(eet_cache_concurrency) /* start a thread that repeatedly opens and closes a file */ open_worker_stop = 0; - pthread_t thread; +# ifdef EFL_HAVE_POSIX_THREADS pthread_create(&thread, NULL, open_close_worker, file); - +# else + thread = _beginthreadex(NULL, 0, open_close_worker, file, 0, &thread_id); +# endif /* clear the cache repeatedly in this thread */ for (n = 0; n < 50000; ++n) { @@ -1479,14 +1522,23 @@ START_TEST(eet_cache_concurrency) /* join the other thread, and fail if it returned an error message */ open_worker_stop = 1; +# ifdef EFL_HAVE_POSIX_THREADS fail_if(pthread_join(thread, &thread_ret) != 0); fail_unless(thread_ret == NULL, (char const*)thread_ret); +# else + ret = WaitForSingleObject((HANDLE)thread, INFINITE); + fail_if(ret != WAIT_OBJECT_0); + fail_if(GetExitCoeThread((HANDLE)thread, &ret) == FALSE); + fail_if(ret != 0) +# endif fail_if(unlink(file) != 0); eet_shutdown(); } END_TEST +#endif /* EFL_HAVE_THREADS */ + typedef struct _Eet_Connection_Data Eet_Connection_Data; struct _Eet_Connection_Data { @@ -2236,9 +2288,11 @@ eet_suite(void) suite_add_tcase(s, tc); #endif +#ifdef EFL_HAVE_THREADS tc = tcase_create("Eet Cache"); tcase_add_test(tc, eet_cache_concurrency); suite_add_tcase(s, tc); +#endif tc = tcase_create("Eet Connection"); tcase_add_test(tc, eet_connection_check);