eina: remove Windows specific thread implementation and rely on posix compliant library instead.
This commit is contained in:
parent
c0683bc2dd
commit
2cb0c1cadc
|
@ -25,17 +25,7 @@ gl_LOCK
|
|||
|
||||
AC_DEFINE([EFL_HAVE_THREADS], [1], [Define to mention that POSIX or Win32 threads are supported])
|
||||
|
||||
case "$host_os" in
|
||||
mingw*)
|
||||
_efl_have_win32_threads="yes"
|
||||
efl_have_setaffinity="yes"
|
||||
AC_DEFINE([EFL_HAVE_WIN32_THREADS], [1], [Define to mention that Win32 threads are supported])
|
||||
;;
|
||||
*)
|
||||
_efl_have_posix_threads="${gl_use_threads}"
|
||||
AC_DEFINE([EFL_HAVE_POSIX_THREADS], [1], [Define to mention that POSIX threads are supported])
|
||||
;;
|
||||
esac
|
||||
_efl_have_posix_threads="${gl_use_threads}"
|
||||
|
||||
dnl System specific CFLAGS
|
||||
if test "x${_efl_have_posix_threads}" = "xyes"; then
|
||||
|
|
|
@ -35,9 +35,7 @@
|
|||
# elif defined (__linux__) || defined(__GLIBC__)
|
||||
# include <sched.h>
|
||||
# endif
|
||||
# ifdef EFL_HAVE_POSIX_THREADS
|
||||
# include <pthread.h>
|
||||
# endif
|
||||
# include <pthread.h>
|
||||
|
||||
# define TH_MAX 8
|
||||
#endif
|
||||
|
|
|
@ -1,610 +0,0 @@
|
|||
/* EINA - EFL data type library
|
||||
* Copyright (C) 2011 Vincent Torri
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef EINA_INLINE_LOCK_WIN32_X_
|
||||
#define EINA_INLINE_LOCK_WIN32_X_
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
|
||||
/** @privatesection @{ */
|
||||
typedef CRITICAL_SECTION Eina_Lock;
|
||||
typedef struct _Eina_Condition Eina_Condition;
|
||||
typedef struct _Eina_RWLock Eina_RWLock;
|
||||
typedef DWORD Eina_TLS;
|
||||
typedef HANDLE Eina_Semaphore;
|
||||
typedef Eina_Lock Eina_Spinlock;
|
||||
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
struct _Eina_Condition
|
||||
{
|
||||
CRITICAL_SECTION *mutex; /**< The locking mechanism for this condition variable */
|
||||
CONDITION_VARIABLE condition; /**< The condition variable */
|
||||
};
|
||||
|
||||
struct _Eina_RWLock
|
||||
{
|
||||
SRWLOCK mutex; /**< The locking mechanism */
|
||||
|
||||
Eina_Bool is_read_mode : 1; /**< Indicates if the lock is a read lock */
|
||||
};
|
||||
#else
|
||||
struct _Eina_Condition
|
||||
{
|
||||
int waiters_count; /**< The count of threads that are waiting on this condition */
|
||||
CRITICAL_SECTION waiters_count_lock; /**< The locking mechanism for the waiters_count member */
|
||||
CRITICAL_SECTION *mutex; /**< The locking mechanism for the condition */
|
||||
HANDLE semaphore; /**< Semaphore used to coordinate waiters */
|
||||
HANDLE waiters_done; /**< Event to trigger when all the waiters are done */
|
||||
Eina_Bool was_broadcast; /**< Indicates whether this condition has signalled its waiters */
|
||||
};
|
||||
|
||||
struct _Eina_RWLock
|
||||
{
|
||||
LONG readers_count; /**< The number of readers waiting for locks */
|
||||
LONG writers_count; /**< The number of writers waiting for locks */
|
||||
int readers; /**< The number of readers that have locks */
|
||||
int writers; /**< The number of writers that have locks */
|
||||
|
||||
Eina_Lock mutex; /**< The locking mechanism */
|
||||
Eina_Condition cond_read; /**< The condition for readers */
|
||||
Eina_Condition cond_write; /**< The condition for writers */
|
||||
};
|
||||
#endif
|
||||
/** @} privatesection */
|
||||
|
||||
EAPI extern Eina_Bool _eina_threads_activated;
|
||||
EAPI extern Eina_Bool _eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb);
|
||||
EAPI extern Eina_Bool _eina_thread_tls_cb_unregister(Eina_TLS key);
|
||||
EAPI extern Eina_Bool _eina_thread_tls_key_add(Eina_TLS key);
|
||||
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_lock_new(Eina_Lock *mutex)
|
||||
{
|
||||
InitializeCriticalSection(mutex);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_lock_free(Eina_Lock *mutex)
|
||||
{
|
||||
DeleteCriticalSection(mutex);
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_lock_take(Eina_Lock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
EnterCriticalSection(mutex);
|
||||
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_lock_take_try(Eina_Lock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
return TryEnterCriticalSection(mutex) == 0 ? EINA_LOCK_FAIL : EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_lock_release(Eina_Lock *mutex)
|
||||
{
|
||||
#ifdef EINA_HAVE_ON_OFF_THREADS
|
||||
if (!_eina_threads_activated) return EINA_LOCK_SUCCEED;
|
||||
#endif
|
||||
|
||||
LeaveCriticalSection(mutex);
|
||||
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_lock_debug(const Eina_Lock *mutex)
|
||||
{
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_new(Eina_Condition *cond, Eina_Lock *mutex)
|
||||
{
|
||||
cond->mutex = mutex;
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
InitializeConditionVariable(&cond->condition);
|
||||
#else
|
||||
cond->waiters_count = 0;
|
||||
cond->was_broadcast = EINA_FALSE;
|
||||
cond->semaphore = CreateSemaphore(NULL, // no security
|
||||
0, // initially 0
|
||||
0x7fffffff, // max count
|
||||
NULL); // unnamed
|
||||
if (!cond->semaphore)
|
||||
return EINA_FALSE;
|
||||
|
||||
InitializeCriticalSection(&cond->waiters_count_lock);
|
||||
|
||||
cond->waiters_done = CreateEvent(NULL, // no security
|
||||
FALSE, // auto-reset
|
||||
FALSE, // non-signaled initially
|
||||
NULL); // unnamed
|
||||
if (!cond->waiters_done)
|
||||
{
|
||||
CloseHandle(cond->semaphore);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_condition_free(Eina_Condition *cond)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
/* Nothing to do */
|
||||
(void)cond;
|
||||
#else
|
||||
CloseHandle(cond->waiters_done);
|
||||
DeleteCriticalSection(&cond->waiters_count_lock);
|
||||
CloseHandle(cond->semaphore);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_condition_internal_timedwait(Eina_Condition *cond, DWORD t)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
SleepConditionVariableCS(&cond->condition, cond->mutex, t);
|
||||
#else
|
||||
DWORD ret;
|
||||
Eina_Bool last_waiter;
|
||||
|
||||
/* Avoid race conditions. */
|
||||
EnterCriticalSection(&cond->waiters_count_lock);
|
||||
cond->waiters_count++;
|
||||
LeaveCriticalSection(&cond->waiters_count_lock);
|
||||
|
||||
/*
|
||||
* This call atomically releases the mutex and waits on the
|
||||
* semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
|
||||
* are called by another thread.
|
||||
*/
|
||||
ret = SignalObjectAndWait(cond->mutex, cond->semaphore, t, FALSE);
|
||||
if (ret == WAIT_FAILED)
|
||||
return EINA_FALSE;
|
||||
|
||||
/* Reacquire lock to avoid race conditions. */
|
||||
EnterCriticalSection(&cond->waiters_count_lock);
|
||||
|
||||
/* We're no longer waiting... */
|
||||
cond->waiters_count--;
|
||||
|
||||
/* Check to see if we're the last waiter after <pthread_cond_broadcast>. */
|
||||
last_waiter = (cond->was_broadcast) && (cond->waiters_count == 0);
|
||||
|
||||
LeaveCriticalSection(&cond->waiters_count_lock);
|
||||
|
||||
/*
|
||||
* If we're the last waiter thread during this particular broadcast
|
||||
* then let all the other threads proceed.
|
||||
*/
|
||||
if (last_waiter)
|
||||
{
|
||||
/*
|
||||
* This call atomically signals the <waiters_done_> event and waits until
|
||||
* it can acquire the <external_mutex>. This is required to ensure fairness.
|
||||
*/
|
||||
ret = SignalObjectAndWait(cond->waiters_done, cond->mutex, t, FALSE);
|
||||
if (ret == WAIT_FAILED)
|
||||
return EINA_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Always regain the external mutex since that's the guarantee we
|
||||
* give to our callers.
|
||||
*/
|
||||
ret = WaitForSingleObject(cond->mutex, t);
|
||||
if (ret == WAIT_FAILED)
|
||||
return EINA_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_timedwait(Eina_Condition *cond, double val)
|
||||
{
|
||||
return _eina_condition_internal_timedwait(cond, (DWORD)(val * 1000));
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_wait(Eina_Condition *cond)
|
||||
{
|
||||
return _eina_condition_internal_timedwait(cond, INFINITE);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_broadcast(Eina_Condition *cond)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
WakeAllConditionVariable(&cond->condition);
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
Eina_Bool have_waiters;
|
||||
|
||||
/*
|
||||
* This is needed to ensure that <waiters_count_> and <was_broadcast_> are
|
||||
* consistent relative to each other.
|
||||
*/
|
||||
EnterCriticalSection(&cond->waiters_count_lock);
|
||||
have_waiters = EINA_FALSE;
|
||||
|
||||
if (cond->waiters_count > 0)
|
||||
{
|
||||
/*
|
||||
* We are broadcasting, even if there is just one waiter...
|
||||
* Record that we are broadcasting, which helps optimize
|
||||
* <pthread_cond_wait> for the non-broadcast case.
|
||||
*/
|
||||
cond->was_broadcast = EINA_TRUE;
|
||||
have_waiters = EINA_TRUE;
|
||||
}
|
||||
|
||||
if (have_waiters)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
/* Wake up all the waiters atomically. */
|
||||
ret = ReleaseSemaphore(cond->semaphore, cond->waiters_count, 0);
|
||||
LeaveCriticalSection(&cond->waiters_count_lock);
|
||||
if (!ret) return EINA_FALSE;
|
||||
|
||||
/*
|
||||
* Wait for all the awakened threads to acquire the counting
|
||||
* semaphore.
|
||||
*/
|
||||
ret = WaitForSingleObject(cond->waiters_done, INFINITE);
|
||||
if (ret == WAIT_FAILED)
|
||||
return EINA_FALSE;
|
||||
/*
|
||||
* This assignment is okay, even without the <waiters_count_lock_> held
|
||||
* because no other waiter threads can wake up to access it.
|
||||
*/
|
||||
cond->was_broadcast = EINA_FALSE;
|
||||
}
|
||||
else
|
||||
LeaveCriticalSection(&cond->waiters_count_lock);
|
||||
|
||||
return EINA_TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_condition_signal(Eina_Condition *cond)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
WakeConditionVariable(&cond->condition);
|
||||
#else
|
||||
Eina_Bool have_waiters;
|
||||
|
||||
EnterCriticalSection(&cond->waiters_count_lock);
|
||||
have_waiters = (cond->waiters_count > 0);
|
||||
LeaveCriticalSection(&cond->waiters_count_lock);
|
||||
|
||||
/* If there aren't any waiters, then this is a no-op. */
|
||||
if (have_waiters)
|
||||
{
|
||||
if (!ReleaseSemaphore(cond->semaphore, 1, 0))
|
||||
return EINA_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_rwlock_new(Eina_RWLock *mutex)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
InitializeSRWLock(&mutex->mutex);
|
||||
return EINA_TRUE;
|
||||
#else
|
||||
if (!eina_lock_new(&(mutex->mutex))) return EINA_FALSE;
|
||||
if (!eina_condition_new(&(mutex->cond_read), &(mutex->mutex)))
|
||||
goto on_error1;
|
||||
if (!eina_condition_new(&(mutex->cond_write), &(mutex->mutex)))
|
||||
goto on_error2;
|
||||
|
||||
mutex->readers_count = 0;
|
||||
mutex->writers_count = 0;
|
||||
mutex->readers = 0;
|
||||
mutex->writers = 0;
|
||||
|
||||
return EINA_TRUE;
|
||||
|
||||
on_error2:
|
||||
eina_condition_free(&(mutex->cond_read));
|
||||
on_error1:
|
||||
eina_lock_free(&(mutex->mutex));
|
||||
return EINA_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_rwlock_free(Eina_RWLock *mutex)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
(void)mutex;
|
||||
#else
|
||||
eina_condition_free(&(mutex->cond_read));
|
||||
eina_condition_free(&(mutex->cond_write));
|
||||
eina_lock_free(&(mutex->mutex));
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_rwlock_take_read(Eina_RWLock *mutex)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
AcquireSRWLockShared(&mutex->mutex);
|
||||
mutex->is_read_mode = EINA_TRUE;
|
||||
#else
|
||||
DWORD res = 0;
|
||||
|
||||
if (eina_lock_take(&(mutex->mutex)) == EINA_LOCK_FAIL)
|
||||
return EINA_LOCK_FAIL;
|
||||
|
||||
if (mutex->writers)
|
||||
{
|
||||
mutex->readers_count++;
|
||||
while (mutex->writers)
|
||||
{
|
||||
EnterCriticalSection(&mutex->cond_write.waiters_count_lock);
|
||||
mutex->cond_read.waiters_count++;
|
||||
LeaveCriticalSection(&mutex->cond_write.waiters_count_lock);
|
||||
res = WaitForSingleObject(mutex->cond_write.semaphore, INFINITE);
|
||||
if (res != WAIT_OBJECT_0) break;
|
||||
}
|
||||
mutex->readers_count--;
|
||||
}
|
||||
if (res == 0)
|
||||
mutex->readers++;
|
||||
eina_lock_release(&(mutex->mutex));
|
||||
#endif
|
||||
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_rwlock_take_write(Eina_RWLock *mutex)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
AcquireSRWLockExclusive(&mutex->mutex);
|
||||
mutex->is_read_mode = EINA_FALSE;
|
||||
#else
|
||||
DWORD res = 0;
|
||||
|
||||
if (eina_lock_take(&(mutex->mutex)) == EINA_LOCK_FAIL)
|
||||
return EINA_LOCK_FAIL;
|
||||
|
||||
if (mutex->writers || mutex->readers > 0)
|
||||
{
|
||||
mutex->writers_count++;
|
||||
while (mutex->writers || mutex->readers > 0)
|
||||
{
|
||||
EnterCriticalSection(&mutex->cond_write.waiters_count_lock);
|
||||
mutex->cond_read.waiters_count++;
|
||||
LeaveCriticalSection(&mutex->cond_write.waiters_count_lock);
|
||||
res = WaitForSingleObject(mutex->cond_write.semaphore, INFINITE);
|
||||
if (res != WAIT_OBJECT_0) break;
|
||||
}
|
||||
mutex->writers_count--;
|
||||
}
|
||||
if (res == 0) mutex->writers = 1;
|
||||
eina_lock_release(&(mutex->mutex));
|
||||
#endif
|
||||
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_rwlock_release(Eina_RWLock *mutex)
|
||||
{
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
if (mutex->is_read_mode)
|
||||
ReleaseSRWLockShared(&mutex->mutex);
|
||||
else
|
||||
ReleaseSRWLockExclusive(&mutex->mutex);
|
||||
#else
|
||||
if (eina_lock_take(&(mutex->mutex)) == EINA_LOCK_FAIL)
|
||||
return EINA_LOCK_FAIL;
|
||||
|
||||
if (mutex->writers)
|
||||
{
|
||||
mutex->writers = 0;
|
||||
if (mutex->readers_count == 1)
|
||||
{
|
||||
EnterCriticalSection(&mutex->cond_read.waiters_count_lock);
|
||||
if (mutex->cond_read.waiters_count > 0)
|
||||
ReleaseSemaphore(mutex->cond_read.semaphore, 1, 0);
|
||||
LeaveCriticalSection(&mutex->cond_read.waiters_count_lock);
|
||||
}
|
||||
else if (mutex->readers_count > 0)
|
||||
eina_condition_broadcast(&(mutex->cond_read));
|
||||
else if (mutex->writers_count > 0)
|
||||
{
|
||||
EnterCriticalSection (&mutex->cond_write.waiters_count_lock);
|
||||
if (mutex->cond_write.waiters_count > 0)
|
||||
ReleaseSemaphore(mutex->cond_write.semaphore, 1, 0);
|
||||
LeaveCriticalSection (&mutex->cond_write.waiters_count_lock);
|
||||
}
|
||||
}
|
||||
else if (mutex->readers > 0)
|
||||
{
|
||||
mutex->readers--;
|
||||
if (mutex->readers == 0 && mutex->writers_count > 0)
|
||||
{
|
||||
EnterCriticalSection (&mutex->cond_write.waiters_count_lock);
|
||||
if (mutex->cond_write.waiters_count > 0)
|
||||
ReleaseSemaphore(mutex->cond_write.semaphore, 1, 0);
|
||||
LeaveCriticalSection (&mutex->cond_write.waiters_count_lock);
|
||||
}
|
||||
}
|
||||
eina_lock_release(&(mutex->mutex));
|
||||
#endif
|
||||
|
||||
return EINA_LOCK_SUCCEED;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_cb_new(Eina_TLS *key, Eina_TLS_Delete_Cb delete_cb)
|
||||
{
|
||||
if ((*key = TlsAlloc()) == TLS_OUT_OF_INDEXES)
|
||||
return EINA_FALSE;
|
||||
if (delete_cb)
|
||||
{
|
||||
if (!_eina_thread_tls_cb_register(*key, delete_cb))
|
||||
{
|
||||
TlsFree(*key);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
}
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_new(Eina_TLS *key)
|
||||
{
|
||||
return eina_tls_cb_new(key, NULL);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_tls_free(Eina_TLS key)
|
||||
{
|
||||
_eina_thread_tls_cb_unregister(key);
|
||||
TlsFree(key);
|
||||
}
|
||||
|
||||
static inline void *
|
||||
eina_tls_get(Eina_TLS key)
|
||||
{
|
||||
return (void*)TlsGetValue(key);
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_tls_set(Eina_TLS key, const void *data)
|
||||
{
|
||||
if (TlsSetValue(key, (LPVOID)data) == 0)
|
||||
return EINA_FALSE;
|
||||
_eina_thread_tls_key_add(key);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_new(Eina_Semaphore *sem, int count_init)
|
||||
{
|
||||
if (!sem || (count_init <= 0))
|
||||
return EINA_FALSE;
|
||||
|
||||
*sem = CreateSemaphore(NULL, count_init, 32767, NULL);
|
||||
if (!*sem)
|
||||
return EINA_FALSE;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_free(Eina_Semaphore *sem)
|
||||
{
|
||||
if (!sem)
|
||||
return EINA_FALSE;
|
||||
|
||||
CloseHandle(*sem);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_lock(Eina_Semaphore *sem)
|
||||
{
|
||||
DWORD res;
|
||||
|
||||
if (!sem)
|
||||
return EINA_FALSE;
|
||||
|
||||
res = WaitForSingleObject(*sem, 0L);
|
||||
if (res == WAIT_OBJECT_0)
|
||||
return EINA_TRUE;
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
eina_semaphore_release(Eina_Semaphore *sem, int count_release)
|
||||
{
|
||||
if (!sem)
|
||||
return EINA_FALSE;
|
||||
|
||||
return ReleaseSemaphore(*sem, count_release, NULL) ? EINA_TRUE : EINA_FALSE;
|
||||
}
|
||||
|
||||
// FIXME: Implement proper spinlock = http://www.codeproject.com/Articles/184046/Spin-Lock-in-C
|
||||
static inline Eina_Bool
|
||||
eina_spinlock_new(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return eina_lock_new(spinlock);
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_spinlock_take(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return eina_lock_take(spinlock);
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_spinlock_take_try(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return eina_lock_take_try(spinlock);
|
||||
}
|
||||
|
||||
static inline Eina_Lock_Result
|
||||
eina_spinlock_release(Eina_Spinlock *spinlock)
|
||||
{
|
||||
return eina_lock_release(spinlock);
|
||||
}
|
||||
|
||||
static inline void
|
||||
eina_spinlock_free(Eina_Spinlock *spinlock)
|
||||
{
|
||||
eina_lock_free(spinlock);
|
||||
}
|
||||
|
||||
#include "eina_inline_lock_barrier.x"
|
||||
|
||||
#endif
|
|
@ -97,11 +97,7 @@ typedef enum
|
|||
*/
|
||||
typedef void (*Eina_TLS_Delete_Cb)(void *ptr);
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "eina_inline_lock_win32.x"
|
||||
#else
|
||||
# include "eina_inline_lock_posix.x"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A type definition for warning that a function was called from
|
||||
|
|
|
@ -103,11 +103,7 @@ EAPI Eina_Error EINA_ERROR_NOT_MAIN_LOOP = 0;
|
|||
EAPI unsigned int eina_seed = 0;
|
||||
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
# ifdef _WIN32
|
||||
EAPI DWORD _eina_main_loop;
|
||||
# else
|
||||
EAPI pthread_t _eina_main_loop;
|
||||
# endif
|
||||
static pid_t _eina_pid;
|
||||
#endif
|
||||
|
||||
|
@ -117,10 +113,8 @@ static int _mt_enabled = 0;
|
|||
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
EAPI int _eina_threads_debug = 0;
|
||||
# if !defined(_WIN32)
|
||||
EAPI pthread_mutex_t _eina_tracking_lock;
|
||||
EAPI Eina_Inlist *_eina_tracking = NULL;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* place module init/shutdown functions here to avoid other modules
|
||||
|
@ -280,11 +274,7 @@ eina_init(void)
|
|||
}
|
||||
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
# ifdef _WIN32
|
||||
_eina_main_loop = GetCurrentThreadId();
|
||||
# else
|
||||
_eina_main_loop = pthread_self();
|
||||
# endif
|
||||
_eina_pid = getpid();
|
||||
#endif
|
||||
|
||||
|
@ -426,24 +416,10 @@ eina_main_loop_is(void)
|
|||
{
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
pid_t pid;
|
||||
|
||||
# ifdef _WIN32
|
||||
if (_eina_main_loop == GetCurrentThreadId())
|
||||
if (pthread_equal(_eina_main_loop, pthread_self()))
|
||||
return EINA_TRUE;
|
||||
# else
|
||||
if (pthread_equal(_eina_main_loop, pthread_self()))
|
||||
return EINA_TRUE;
|
||||
# endif
|
||||
|
||||
pid = getpid();
|
||||
# ifdef _WIN32
|
||||
if (pid != _eina_pid)
|
||||
{
|
||||
_eina_pid = pid;
|
||||
_eina_main_loop = GetCurrentThreadId();
|
||||
return EINA_TRUE;
|
||||
}
|
||||
#else
|
||||
if (pid != _eina_pid)
|
||||
{
|
||||
/* This is in case of a fork, but don't like the solution */
|
||||
|
@ -451,7 +427,6 @@ eina_main_loop_is(void)
|
|||
_eina_main_loop = pthread_self();
|
||||
return EINA_TRUE;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return EINA_FALSE;
|
||||
|
@ -463,11 +438,7 @@ eina_main_loop_define(void)
|
|||
{
|
||||
#ifdef EFL_HAVE_THREADS
|
||||
_eina_pid = getpid();
|
||||
# ifdef _WIN32
|
||||
_eina_main_loop = GetCurrentThreadId();
|
||||
# else
|
||||
_eina_main_loop = pthread_self();
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -20,14 +20,12 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef EFL_HAVE_POSIX_THREADS
|
||||
# include <pthread.h>
|
||||
# ifdef __linux__
|
||||
# include <sched.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
# include <errno.h>
|
||||
# endif
|
||||
#include <pthread.h>
|
||||
#ifdef __linux__
|
||||
# include <sched.h>
|
||||
# include <sys/time.h>
|
||||
# include <sys/resource.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef EFL_HAVE_WIN32_THREADS
|
||||
|
@ -47,7 +45,6 @@
|
|||
EAPI void
|
||||
eina_sched_prio_drop(void)
|
||||
{
|
||||
#ifdef EFL_HAVE_POSIX_THREADS
|
||||
struct sched_param param;
|
||||
int pol, ret;
|
||||
pthread_t pthread_id;
|
||||
|
@ -92,11 +89,4 @@ eina_sched_prio_drop(void)
|
|||
}
|
||||
}
|
||||
# endif
|
||||
#elif defined EFL_HAVE_WIN32_THREADS
|
||||
if (!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
|
||||
EINA_LOG_ERR("Can not set thread priority");
|
||||
#else
|
||||
EINA_LOG_ERR("Eina does not have support for threads enabled"
|
||||
"or it doesn't support setting scheduler priorities");
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -25,238 +25,10 @@
|
|||
#include "eina_config.h"
|
||||
#include "eina_thread.h"
|
||||
#include "eina_sched.h"
|
||||
#ifdef _WIN32
|
||||
# include "eina_list.h"
|
||||
# include "eina_lock.h"
|
||||
#endif
|
||||
|
||||
/* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
|
||||
#include "eina_safety_checks.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <windows.h>
|
||||
# undef WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <process.h>
|
||||
|
||||
typedef struct _Eina_TLS_Cbs_Win32 Eina_TLS_Cbs_Win32;
|
||||
struct _Eina_TLS_Cbs_Win32
|
||||
{
|
||||
Eina_TLS key;
|
||||
Eina_TLS_Delete_Cb cb;
|
||||
};
|
||||
typedef struct _Eina_Thread_Win32 Eina_Thread_Win32;
|
||||
struct _Eina_Thread_Win32
|
||||
{
|
||||
HANDLE thread;
|
||||
void *(*func)(void *data);
|
||||
void *data;
|
||||
void *ret;
|
||||
Eina_List *tls_keys;
|
||||
|
||||
Eina_Thread index;
|
||||
};
|
||||
|
||||
/* FIXME: For the moment Eina_Thread is considered not
|
||||
thread safe, wondering if it's worth it */
|
||||
static unsigned long int _current_index = 1; /* start from one as the main loop == 0 */
|
||||
static Eina_List *_thread_pool = NULL;
|
||||
static Eina_List *_thread_running = NULL;
|
||||
static Eina_List *_tls_keys_cbs = NULL;
|
||||
|
||||
static inline Eina_TLS_Cbs_Win32 *
|
||||
_eina_thread_tls_cb_find(Eina_TLS key)
|
||||
{
|
||||
Eina_TLS_Cbs_Win32 *cb;
|
||||
Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(_tls_keys_cbs, l, cb)
|
||||
if (cb->key == key)
|
||||
return cb;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_eina_thread_tls_keys_clean(Eina_Thread_Win32 *tw)
|
||||
{
|
||||
void *data;
|
||||
Eina_TLS_Cbs_Win32 *cb;
|
||||
|
||||
EINA_LIST_FREE(tw->tls_keys, data)
|
||||
{
|
||||
Eina_TLS key = (Eina_TLS)(uintptr_t)data;
|
||||
cb = _eina_thread_tls_cb_find(key);
|
||||
if (cb)
|
||||
cb->cb(eina_tls_get(key));
|
||||
}
|
||||
tw->tls_keys = NULL;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_thread_tls_cb_register(Eina_TLS key, Eina_TLS_Delete_Cb cb)
|
||||
{
|
||||
Eina_TLS_Cbs_Win32 *tls_cb;
|
||||
|
||||
if (!cb) return EINA_FALSE;
|
||||
|
||||
tls_cb = malloc(sizeof(Eina_TLS_Cbs_Win32));
|
||||
if (!tls_cb) return EINA_FALSE;
|
||||
|
||||
tls_cb->key = key;
|
||||
tls_cb->cb = cb;
|
||||
_tls_keys_cbs = eina_list_append(_tls_keys_cbs, tls_cb);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_thread_tls_cb_unregister(Eina_TLS key)
|
||||
{
|
||||
Eina_TLS_Cbs_Win32 *cb = _eina_thread_tls_cb_find(key);
|
||||
if (!cb) return EINA_FALSE;
|
||||
|
||||
_tls_keys_cbs = eina_list_remove(_tls_keys_cbs, cb);
|
||||
free(cb);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
_eina_thread_tls_key_add(Eina_TLS key)
|
||||
{
|
||||
HANDLE t;
|
||||
Eina_Thread_Win32 *tw;
|
||||
Eina_List *l;
|
||||
|
||||
t = GetCurrentThread();
|
||||
EINA_LIST_FOREACH(_thread_running, l, tw)
|
||||
if (tw->thread == t)
|
||||
{
|
||||
void *data = (void *)(uintptr_t)key;
|
||||
if (!eina_list_data_find(tw->tls_keys, data))
|
||||
tw->tls_keys = eina_list_append(tw->tls_keys, data);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Thread_Win32 *
|
||||
_eina_thread_win32_find(Eina_Thread index)
|
||||
{
|
||||
Eina_Thread_Win32 *tw;
|
||||
Eina_List *l;
|
||||
|
||||
EINA_LIST_FOREACH(_thread_running, l, tw)
|
||||
if (tw->index == index)
|
||||
return tw;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline Eina_Thread
|
||||
_eina_thread_self(void)
|
||||
{
|
||||
HANDLE t;
|
||||
Eina_Thread_Win32 *tw;
|
||||
Eina_List *l;
|
||||
|
||||
t = GetCurrentThread();
|
||||
EINA_LIST_FOREACH(_thread_running, l, tw)
|
||||
if (tw->thread == t)
|
||||
return tw->index;
|
||||
|
||||
/* We assume main loop == 0 on Windows */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_thread_equal(Eina_Thread t1, Eina_Thread t2)
|
||||
{
|
||||
if (t1 == t2) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static unsigned int WINAPI
|
||||
_eina_thread_win32_cb(LPVOID lpParam)
|
||||
{
|
||||
Eina_Thread_Win32 *tw = lpParam;
|
||||
|
||||
tw->ret = tw->func(tw->data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_eina_thread_create(Eina_Thread *t,
|
||||
int affinity,
|
||||
void *(*func)(void *data),
|
||||
const void *data)
|
||||
{
|
||||
Eina_Thread_Win32 *tw;
|
||||
|
||||
tw = eina_list_data_get(_thread_pool);
|
||||
_thread_pool = eina_list_remove_list(_thread_pool, _thread_pool);
|
||||
|
||||
if (!tw)
|
||||
{
|
||||
tw = malloc(sizeof (Eina_Thread_Win32));
|
||||
if (!tw) goto on_error;
|
||||
|
||||
do {
|
||||
tw->index = _current_index++;
|
||||
} while (tw->index == 0); /* prevent having a "false" main loop */
|
||||
}
|
||||
|
||||
tw->func = func;
|
||||
tw->data = (void *)data;
|
||||
tw->tls_keys = NULL;
|
||||
|
||||
tw->thread = (HANDLE)_beginthreadex(NULL, 0, _eina_thread_win32_cb, tw, 0, NULL);
|
||||
if (!tw->thread) goto on_error;
|
||||
|
||||
/* affinity is an hint, if we fail, we continue without */
|
||||
if (affinity >= 0)
|
||||
SetThreadAffinityMask(tw->thread, 1 << affinity);
|
||||
|
||||
_thread_running = eina_list_append(_thread_running, tw);
|
||||
|
||||
*t = tw->index;
|
||||
return EINA_TRUE;
|
||||
|
||||
on_error:
|
||||
_thread_pool = eina_list_append(_thread_pool, tw);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
_eina_thread_join(Eina_Thread t)
|
||||
{
|
||||
Eina_Thread_Win32 *tw;
|
||||
void *ret;
|
||||
|
||||
tw = _eina_thread_win32_find(t);
|
||||
if (!tw) return NULL;
|
||||
|
||||
WaitForSingleObject(tw->thread, INFINITE);
|
||||
CloseHandle(tw->thread);
|
||||
|
||||
ret = tw->ret;
|
||||
|
||||
tw->ret = NULL;
|
||||
tw->thread = NULL;
|
||||
tw->func = NULL;
|
||||
tw->data = NULL;
|
||||
_eina_thread_tls_keys_clean(tw);
|
||||
|
||||
_thread_running = eina_list_remove(_thread_running, tw);
|
||||
_thread_pool = eina_list_append(_thread_pool, _thread_pool);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#elif defined(EFL_HAVE_POSIX_THREADS)
|
||||
# include <pthread.h>
|
||||
# include <errno.h>
|
||||
|
||||
|
@ -312,9 +84,6 @@ _eina_thread_self(void)
|
|||
return (Eina_Thread)pthread_self();
|
||||
}
|
||||
|
||||
#else
|
||||
# error "Not supported any more"
|
||||
#endif
|
||||
|
||||
typedef struct _Eina_Thread_Call Eina_Thread_Call;
|
||||
struct _Eina_Thread_Call
|
||||
|
|
Loading…
Reference in New Issue