From 425a9a5fbde23ba17a29472978b1e5492013a8dc Mon Sep 17 00:00:00 2001 From: caiosignor Date: Thu, 12 Mar 2020 11:00:45 -0300 Subject: [PATCH] Separate eina_thred.c into eina_thread_posix.c and eina_thread_win32.c; Changed the meson.build to call theses files according to SO. --- src/lib/eina/eina_thread.c | 178 ++++++++++++------------------- src/lib/eina/eina_thread.h | 13 +++ src/lib/eina/eina_thread_posix.c | 150 ++++++++++++++++++++++++++ src/lib/eina/eina_thread_win32.c | 174 ++++++++++++++++++++++++++++++ src/lib/eina/meson.build | 4 +- 5 files changed, 406 insertions(+), 113 deletions(-) create mode 100644 src/lib/eina/eina_thread_posix.c create mode 100644 src/lib/eina/eina_thread_win32.c diff --git a/src/lib/eina/eina_thread.c b/src/lib/eina/eina_thread.c index c1a1ef0d22..5871449929 100644 --- a/src/lib/eina/eina_thread.c +++ b/src/lib/eina/eina_thread.c @@ -33,7 +33,14 @@ #include "eina_debug_private.h" -#include +/* +#ifndef _WIN32 + +# include "eina_thread_posix.h" +#else +# include "eina_thread_win32.h" +#endif +*/ #include #ifndef _WIN32 # include @@ -47,113 +54,7 @@ #endif #endif -static inline void * -_eina_thread_join(Eina_Thread t) -{ - void *ret = NULL; - int err = pthread_join((pthread_t)t, &ret); - - if (err == 0) return ret; - return NULL; -} - -static inline Eina_Bool -_eina_thread_create(Eina_Thread *t, int affinity, void *(*func)(void *data), void *data) -{ - int err; - pthread_attr_t attr; -#ifndef _WIN32 - sigset_t oldset, newset; -#endif - - pthread_attr_init(&attr); - if (affinity >= 0) - { -#ifdef EINA_HAVE_PTHREAD_AFFINITY - cpu_set_t cpu; - - CPU_ZERO(&cpu); - CPU_SET(affinity, &cpu); - pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu); -#endif - } - - /* setup initial locks */ -#ifndef _WIN32 - sigemptyset(&newset); - sigaddset(&newset, SIGPIPE); - sigaddset(&newset, SIGALRM); - sigaddset(&newset, SIGCHLD); - sigaddset(&newset, SIGUSR1); - sigaddset(&newset, SIGUSR2); - sigaddset(&newset, SIGHUP); - sigaddset(&newset, SIGQUIT); - sigaddset(&newset, SIGINT); - sigaddset(&newset, SIGTERM); -# ifdef SIGPWR - sigaddset(&newset, SIGPWR); -# endif - pthread_sigmask(SIG_BLOCK, &newset, &oldset); -#endif - err = pthread_create((pthread_t *)t, &attr, func, data); -#ifndef _WIN32 - pthread_sigmask(SIG_SETMASK, &oldset, NULL); -#endif - pthread_attr_destroy(&attr); - - if (err == 0) return EINA_TRUE; - - return EINA_FALSE; -} - -static inline Eina_Bool -_eina_thread_equal(Eina_Thread t1, Eina_Thread t2) -{ - return pthread_equal((pthread_t)t1, (pthread_t)t2); -} - -static inline Eina_Thread -_eina_thread_self(void) -{ - return (Eina_Thread)pthread_self(); -} - - -typedef struct _Eina_Thread_Call Eina_Thread_Call; -struct _Eina_Thread_Call -{ - Eina_Thread_Cb func; - const void *data; - - Eina_Thread_Priority prio; - int affinity; -}; - -static void * -_eina_internal_call(void *context) -{ - Eina_Thread_Call *c = context; - void *r; - pthread_t self; - - // Default this thread to not cancellable as per Eina documentation - eina_thread_cancellable_set(EINA_FALSE, NULL); - - EINA_THREAD_CLEANUP_PUSH(free, c); - - if (c->prio == EINA_THREAD_BACKGROUND || - c->prio == EINA_THREAD_IDLE) - eina_sched_prio_drop(); - - self = pthread_self(); - _eina_debug_thread_add(&self); - EINA_THREAD_CLEANUP_PUSH(_eina_debug_thread_del, &self); - r = c->func((void*) c->data, eina_thread_self()); - EINA_THREAD_CLEANUP_POP(EINA_TRUE); - EINA_THREAD_CLEANUP_POP(EINA_TRUE); - - return r; -} +static void *_eina_internal_call(void *context); EAPI Eina_Thread eina_thread_self(void) @@ -212,8 +113,9 @@ eina_thread_name_set(Eina_Thread t, const char *name) } else buf[0] = 0; #ifndef __linux__ - pthread_set_name_np((pthread_t)t, buf); - return EINA_TRUE; + //pthread_set_name_np((pthread_t)t, buf); + //return EINA_TRUE; + return _eina_thread_set_name_win32(t, buf); #else if (pthread_setname_np((pthread_t)t, buf) == 0) return EINA_TRUE; #endif @@ -228,7 +130,11 @@ EAPI Eina_Bool eina_thread_cancel(Eina_Thread t) { if (!t) return EINA_FALSE; + #ifndef _WIN32 return pthread_cancel((pthread_t)t) == 0; + #else + return _eina_thread_cancel(t); + #endif } EAPI Eina_Bool @@ -237,21 +143,32 @@ eina_thread_cancellable_set(Eina_Bool cancellable, Eina_Bool *was_cancellable) int state = cancellable ? PTHREAD_CANCEL_ENABLE : PTHREAD_CANCEL_DISABLE; int old = 0; int r; - + #ifndef _WIN32 /* enforce deferred in case users changed to asynchronous themselves */ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old); r = pthread_setcancelstate(state, &old); if (was_cancellable && r == 0) *was_cancellable = (old == PTHREAD_CANCEL_ENABLE); - return r == 0; + #else + if(!state){ + *was_cancellable = EINA_TRUE; + return EINA_FALSE; + }else{ + *was_cancellable = EINA_TRUE; + return EINA_TRUE; + } + #endif } EAPI void eina_thread_cancel_checkpoint(void) { + #ifndef _WIN32 pthread_testcancel(); + #endif + } EAPI void * @@ -281,3 +198,40 @@ eina_thread_shutdown(void) { return EINA_TRUE; } + +static void *_eina_internal_call(void *context) +{ + Eina_Thread_Call *c = context; + void *r; + #ifdef _WIN32 + HANDLE self; + #else + pthread_t self; + #endif + + // Default this thread to not cancellable as per Eina documentation + eina_thread_cancellable_set(EINA_FALSE, NULL); + + EINA_THREAD_CLEANUP_PUSH(free, c); + + if (c->prio == EINA_THREAD_BACKGROUND || c->prio == EINA_THREAD_IDLE) + eina_sched_prio_drop(); + + + #ifdef _WIN32 + self = GetCurrentThread(); + #else + self = pthread_self(); + #endif + + //self = GetCurrentThreadId(); + //self = GetCurrentThread(); + + _eina_debug_thread_add(&self); + EINA_THREAD_CLEANUP_PUSH(_eina_debug_thread_del, &self); + r = c->func((void*) c->data, eina_thread_self()); + EINA_THREAD_CLEANUP_POP(EINA_TRUE); + EINA_THREAD_CLEANUP_POP(EINA_TRUE); + + return r; +} \ No newline at end of file diff --git a/src/lib/eina/eina_thread.h b/src/lib/eina/eina_thread.h index 15e522fc4c..856b623770 100644 --- a/src/lib/eina/eina_thread.h +++ b/src/lib/eina/eina_thread.h @@ -336,8 +336,21 @@ typedef void *(*Eina_Thread_Cancellable_Run_Cb)(void *data); * * @since 1.19 */ + EAPI void *eina_thread_cancellable_run(Eina_Thread_Cancellable_Run_Cb cb, Eina_Free_Cb cleanup_cb, void *data); + +typedef struct _Eina_Thread_Call Eina_Thread_Call; +struct _Eina_Thread_Call +{ + Eina_Thread_Cb func; + const void *data; + + Eina_Thread_Priority prio; + int affinity; +}; + + /** * @} */ diff --git a/src/lib/eina/eina_thread_posix.c b/src/lib/eina/eina_thread_posix.c new file mode 100644 index 0000000000..bbfe020bce --- /dev/null +++ b/src/lib/eina/eina_thread_posix.c @@ -0,0 +1,150 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "eina_config.h" +#include "eina_lock.h" /* it will include pthread.h with proper flags */ +#include "eina_thread.h" +#include "eina_sched.h" +#include "eina_cpu.h" + +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" + +#include "eina_debug_private.h" + +#include +#include +#ifndef _WIN32 +# include +#endif +# include + +#if defined(EINA_HAVE_PTHREAD_AFFINITY) || defined(EINA_HAVE_PTHREAD_SETNAME) +#ifndef __linux__ +#include +#define cpu_set_t cpuset_t +#endif +#endif + + +static inline void * +_eina_thread_join(Eina_Thread t) +{ + void *ret = NULL; + int err = pthread_join((pthread_t)t, &ret); + + if (err == 0) return ret; + return NULL; +} + +static inline Eina_Bool +_eina_thread_create(Eina_Thread *t, int affinity, void *(*func)(void *data), void *data) +{ + int err; + pthread_attr_t attr; +#ifndef _WIN32 + sigset_t oldset, newset; +#endif + + pthread_attr_init(&attr); + if (affinity >= 0) + { +#ifdef EINA_HAVE_PTHREAD_AFFINITY + cpu_set_t cpu; + + CPU_ZERO(&cpu); + CPU_SET(affinity, &cpu); + pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu); +#endif + } + + /* setup initial locks */ +#ifndef _WIN32 + sigemptyset(&newset); + sigaddset(&newset, SIGPIPE); + sigaddset(&newset, SIGALRM); + sigaddset(&newset, SIGCHLD); + sigaddset(&newset, SIGUSR1); + sigaddset(&newset, SIGUSR2); + sigaddset(&newset, SIGHUP); + sigaddset(&newset, SIGQUIT); + sigaddset(&newset, SIGINT); + sigaddset(&newset, SIGTERM); +# ifdef SIGPWR + sigaddset(&newset, SIGPWR); +# endif + pthread_sigmask(SIG_BLOCK, &newset, &oldset); +#endif + err = pthread_create((pthread_t *)t, &attr, func, data); +#ifndef _WIN32 + pthread_sigmask(SIG_SETMASK, &oldset, NULL); +#endif + pthread_attr_destroy(&attr); + + if (err == 0) return EINA_TRUE; + + return EINA_FALSE; +} + +static inline Eina_Bool +_eina_thread_equal(Eina_Thread t1, Eina_Thread t2) +{ + return pthread_equal((pthread_t)t1, (pthread_t)t2); +} + +static inline Eina_Thread +_eina_thread_self(void) +{ + return (Eina_Thread)pthread_self(); +} + + + +/* +static void * +_eina_internal_call(void *context) +{ + Eina_Thread_Call *c = context; + void *r; + pthread_t self; + + // Default this thread to not cancellable as per Eina documentation + eina_thread_cancellable_set(EINA_FALSE, NULL); + + EINA_THREAD_CLEANUP_PUSH(free, c); + + if (c->prio == EINA_THREAD_BACKGROUND || + c->prio == EINA_THREAD_IDLE) + eina_sched_prio_drop(); + + self = pthread_self(); + _eina_debug_thread_add(&self); + EINA_THREAD_CLEANUP_PUSH(_eina_debug_thread_del, &self); + r = c->func((void*) c->data, eina_thread_self()); + EINA_THREAD_CLEANUP_POP(EINA_TRUE); + EINA_THREAD_CLEANUP_POP(EINA_TRUE); + + return r; +} +*/ \ No newline at end of file diff --git a/src/lib/eina/eina_thread_win32.c b/src/lib/eina/eina_thread_win32.c new file mode 100644 index 0000000000..4b2c9b695f --- /dev/null +++ b/src/lib/eina/eina_thread_win32.c @@ -0,0 +1,174 @@ +/* EINA - EFL data type library + * Copyright (C) 2012 Cedric Bail + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; + * if not, see . + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "eina_config.h" +#include "eina_lock.h" /* it will include pthread.h with proper flags */ + +#include "eina_sched.h" +#include "eina_cpu.h" +#include "eina_thread.h" +/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */ +#include "eina_safety_checks.h" + +#include "eina_debug_private.h" + +# include + + + +#include +#ifndef _WIN32 +# include +#endif +# include + +#if defined(EINA_HAVE_PTHREAD_AFFINITY) || defined(EINA_HAVE_PTHREAD_SETNAME) +#ifndef __linux__ +#define cpu_set_t cpuset_t +#endif +#endif + +typedef struct _Eina_win32_thread_attr{ + void *data; + void *(*func)(void *data); + +}Eina_win32_thread_attr; + + +inline void * +_eina_thread_join(Eina_Thread t) +{ + //void *ret = NULL; + int timeout_millis = 10000; + int ret = WaitForSingleObject(t,timeout_millis);//int ret = pthread_join((pthread_t)t, &ret); + + if (ret != 0) return ret;//if (ret == 0) return ret; + return NULL; +} + + + + + +DWORD WINAPI _eina_thread_func(void *params) +{ + // // Code + //Eina_Thread_Call *c = params; + //void *r; + //r = c->func((void*) c->data, eina_thread_self()); + //return (DWORD) r; + //return (DWORD) _eina_internal_call(params); + + return (DWORD) ((Eina_win32_thread_attr *)params)->func( (void*) ((Eina_win32_thread_attr *)params)->data); +} + + +void _eina_thread_set_priority(Eina_Thread_Priority prio, Eina_Thread *t){ + //HANDLE hThread; + int nPriority; + + switch(prio){ + case EINA_THREAD_URGENT: nPriority =THREAD_PRIORITY_HIGHEST; + case EINA_THREAD_NORMAL: nPriority = THREAD_PRIORITY_NORMAL; + case EINA_THREAD_BACKGROUND: nPriority = THREAD_PRIORITY_BELOW_NORMAL; + case EINA_THREAD_IDLE: nPriority = THREAD_PRIORITY_IDLE; + } + + SetThreadPriority((HANDLE)*t,nPriority); +} + +inline Eina_Bool +_eina_thread_create(Eina_Thread *t, int affinity, void *(*func)(void *data), void *data) +{ + Eina_Bool ret; + + LPDWORD threadID; + + Eina_win32_thread_attr *thread_attr = (Eina_win32_thread_attr*) malloc(sizeof(Eina_win32_thread_attr)); + Eina_Thread_Call *c = (Eina_Thread_Call*)(data); + + thread_attr->func = func; + thread_attr->data = data; + + *t =(HANDLE) CreateThread(NULL, 0, &_eina_thread_func,thread_attr,0,threadID); + + free(thread_attr); + + + + _eina_thread_set_priority(c->prio,t); //SetThreadPriority(*t, c->prio); + + ret = (*t != NULL) ? EINA_TRUE : EINA_FALSE; + + if(affinity >= 0 && ret){ + #ifdef EINA_HAVE_PTHREAD_AFFINITY + cpu_set_t cpu; + CPU_ZERO(&cpu); + CPU_SET(affinity, &cpu); + SetThreadAffinityMask(*t,(DWORD_PTR*)&cpu); + #else + SetThreadAffinityMask(*t,(DWORD_PTR*)&affinity); + #endif + } + + + return ret; +} + + + + +inline Eina_Bool +_eina_thread_equal(Eina_Thread t1, Eina_Thread t2) +{ + DWORD t1_thread_id = GetThreadId((HANDLE)t1); + DWORD t2_thread_id = GetThreadId((HANDLE)t2); + + return (t1_thread_id == t2_thread_id) ? EINA_TRUE : EINA_FALSE; + //return pthread_equal((pthread_t)t1, (pthread_t)t2); +} + +inline Eina_Thread +_eina_thread_self(void) +{ + //return (Eina_Thread)GetCurrentThreadId(); + return (Eina_Thread)GetCurrentThread(); + //return (Eina_Thread)pthread_self(); +} + +HRESULT _eina_thread_set_name_win32(Eina_Thread thread, char *buf){ + return SetThreadDescription((HANDLE)thread, (PCWSTR)buf); +} + +Eina_Bool _eina_thread_cancel(Eina_Thread thread){ + LPDWORD lpExitCode; + Eina_Bool success = GetExitCodeThread((HANDLE)thread, lpExitCode); + + ExitThread(*lpExitCode); + return success; + //return SetThreadDescription((HANDLE)thread, (PCWSTR)buf); +} + + + diff --git a/src/lib/eina/meson.build b/src/lib/eina/meson.build index b53eac8744..386d0423b1 100644 --- a/src/lib/eina/meson.build +++ b/src/lib/eina/meson.build @@ -199,8 +199,10 @@ sources = [ if sys_windows == true sources += 'eina_file_win32.c' + sources += 'eina_thread_win32.c' else sources += 'eina_file.c' + sources += 'eina_thread_posix.c' endif eina_config = configuration_data() @@ -410,4 +412,4 @@ pkgconfig.generate(eina_lib, version : version_major + '.' + version_minor + '.' + version_micro, libraries : eina_pub_deps, ) -endif +endif \ No newline at end of file