rizin/librz/util/thread_lock.c
Giovanni a988941bf2
Refactor thread code and add RzThreadQueue (#2683)
* Kill the thread only if is alive.
* Remove rz_th_lock_guard.
* Use rz_sys_usleep since pthread_yield/sched_yield are not portable.
* Kill threads only on error.
* Avoid killing already-dead threads.
* RzThreadFunction now returns void* and added test_thread_queue.
* Removed pthread_exit
2022-06-19 21:07:13 +08:00

99 lines
2.4 KiB
C

// SPDX-FileCopyrightText: 2009-2017 pancake <pancake@nopcode.org>
// SPDX-FileCopyrightText: 2022 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include "thread.h"
/**
* \brief Allocates and initialize a RzThreadLock structure.
*
* \param recursive Set it to true for recursive locking (on windows, all the locks are always recursive).
*
* \return On success returns a valid pointer, otherwise NULL
*/
RZ_API RZ_OWN RzThreadLock *rz_th_lock_new(bool recursive) {
RzThreadLock *thl = RZ_NEW0(RzThreadLock);
if (!thl) {
return NULL;
}
#if HAVE_PTHREAD
if (recursive) {
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if !defined(__GLIBC__) || __USE_UNIX98__
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
#else
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
#endif
pthread_mutex_init(&thl->lock, &attr);
} else {
pthread_mutex_init(&thl->lock, NULL);
}
#elif __WINDOWS__
// Windows critical sections always accept recursive
// access and it cannot be configured in any other way.
InitializeCriticalSection(&thl->lock);
#endif
return thl;
}
/**
* \brief Acquires a RzThreadLock structure
*
* \param thl The RzThreadLock to acquire
*/
RZ_API void rz_th_lock_enter(RZ_NONNULL RzThreadLock *thl) {
rz_return_if_fail(thl);
#if HAVE_PTHREAD
pthread_mutex_lock(&thl->lock);
#elif __WINDOWS__
EnterCriticalSection(&thl->lock);
#endif
}
/**
* \brief Tries to acquire a RzThreadLock structure
*
* \param thl The RzThreadLock to try to acquire
*
* \return On success returns true, otherwise false
*/
RZ_API bool rz_th_lock_tryenter(RZ_NONNULL RzThreadLock *thl) {
rz_return_val_if_fail(thl, false);
#if HAVE_PTHREAD
return !pthread_mutex_trylock(&thl->lock);
#elif __WINDOWS__
return TryEnterCriticalSection(&thl->lock);
#endif
}
/**
* \brief Releases a RzThreadLock structure
*
* \param thl The RzThreadLock to release
*/
RZ_API void rz_th_lock_leave(RZ_NONNULL RzThreadLock *thl) {
rz_return_if_fail(thl);
#if HAVE_PTHREAD
pthread_mutex_unlock(&thl->lock);
#elif __WINDOWS__
LeaveCriticalSection(&thl->lock);
#endif
}
/**
* \brief Frees a RzThreadLock structure
*
* \param thl The RzThreadLock to free
*/
RZ_API void rz_th_lock_free(RZ_NULLABLE RzThreadLock *thl) {
if (!thl) {
return;
}
#if HAVE_PTHREAD
pthread_mutex_destroy(&thl->lock);
#elif __WINDOWS__
DeleteCriticalSection(&thl->lock);
#endif
free(thl);
}