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.

This commit is contained in:
caiosignor 2020-03-12 11:00:45 -03:00 committed by João Paulo Taylor Ienczak Zanette
parent ed0287d23b
commit 425a9a5fbd
5 changed files with 406 additions and 113 deletions

View File

@ -33,7 +33,14 @@
#include "eina_debug_private.h"
#include <pthread.h>
/*
#ifndef _WIN32
# include "eina_thread_posix.h"
#else
# include "eina_thread_win32.h"
#endif
*/
#include <errno.h>
#ifndef _WIN32
# include <signal.h>
@ -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;
}

View File

@ -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;
};
/**
* @}
*/

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#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 <pthread.h>
#include <errno.h>
#ifndef _WIN32
# include <signal.h>
#endif
# include <string.h>
#if defined(EINA_HAVE_PTHREAD_AFFINITY) || defined(EINA_HAVE_PTHREAD_SETNAME)
#ifndef __linux__
#include <pthread_np.h>
#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;
}
*/

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#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 <Windows.h>
#include <errno.h>
#ifndef _WIN32
# include <signal.h>
#endif
# include <string.h>
#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);
}

View File

@ -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