From a4dd0ad63c00f4dee3b86dfd3075d1d61b2b3180 Mon Sep 17 00:00:00 2001 From: sanine Date: Sat, 27 Aug 2022 23:52:56 -0500 Subject: add plibsys --- 3rdparty/plibsys/src/puthread-atheos.c | 317 +++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 3rdparty/plibsys/src/puthread-atheos.c (limited to '3rdparty/plibsys/src/puthread-atheos.c') diff --git a/3rdparty/plibsys/src/puthread-atheos.c b/3rdparty/plibsys/src/puthread-atheos.c new file mode 100644 index 0000000..8d33ec5 --- /dev/null +++ b/3rdparty/plibsys/src/puthread-atheos.c @@ -0,0 +1,317 @@ +/* + * The MIT License + * + * Copyright (C) 2016-2019 Alexander Saprykin + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * 'Software'), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "pmem.h" +#include "patomic.h" +#include "puthread.h" +#include "puthread-private.h" + +#include +#include +#include +#include + +#include +#include + +typedef thread_id puthread_hdl; + +struct PUThread_ { + PUThreadBase base; + puthread_hdl hdl; +}; + +struct PUThreadKey_ { + pint key; + PDestroyFunc free_func; +}; + +static pint pp_uthread_get_atheos_priority (PUThreadPriority prio); +static pint pp_uthread_get_tls_key (PUThreadKey *key); + +static pint +pp_uthread_get_atheos_priority (PUThreadPriority prio) +{ + switch (prio) { + case P_UTHREAD_PRIORITY_INHERIT: + { + thread_info thr_info; + + memset (&thr_info, 0, sizeof (thr_info)); + + if (P_UNLIKELY (get_thread_info (get_thread_id (NULL), &thr_info) != 0)) { + P_WARNING ("PUThread::pp_uthread_get_atheos_priority: failed to get thread info"); + return NORMAL_PRIORITY; + } else + return thr_info.ti_priority; + } + + case P_UTHREAD_PRIORITY_IDLE: + return IDLE_PRIORITY; + case P_UTHREAD_PRIORITY_LOWEST: + return LOW_PRIORITY / 2; + case P_UTHREAD_PRIORITY_LOW: + return LOW_PRIORITY; + case P_UTHREAD_PRIORITY_NORMAL: + return NORMAL_PRIORITY; + case P_UTHREAD_PRIORITY_HIGH: + return DISPLAY_PRIORITY; + case P_UTHREAD_PRIORITY_HIGHEST: + return URGENT_DISPLAY_PRIORITY; + case P_UTHREAD_PRIORITY_TIMECRITICAL: + return REALTIME_PRIORITY; + } +} + +static pint +pp_uthread_get_tls_key (PUThreadKey *key) +{ + pint thread_key; + + thread_key = p_atomic_int_get ((const volatile pint *) &key->key); + + if (P_LIKELY (thread_key >= 0)) + return thread_key; + + if (P_UNLIKELY ((thread_key = alloc_tld (key->free_func)) < 0)) { + P_ERROR ("PUThread::pp_uthread_get_tls_key: alloc_tld() failed"); + return -1; + } + + if (P_UNLIKELY (p_atomic_int_compare_and_exchange ((volatile pint *) &key->key, + -1, + thread_key) == FALSE)) { + if (P_UNLIKELY (free_tld (thread_key) != 0)) { + P_ERROR ("PUThread::pp_uthread_get_tls_key: free_tld() failed"); + return -1; + } + + thread_key = key->key; + } + + return thread_key; +} + +void +p_uthread_init_internal (void) +{ +} + +void +p_uthread_shutdown_internal (void) +{ +} + +void +p_uthread_win32_thread_detach (void) +{ +} + +PUThread * +p_uthread_create_internal (PUThreadFunc func, + pboolean joinable, + PUThreadPriority prio, + psize stack_size) +{ + PUThread *ret; + + if (P_UNLIKELY ((ret = p_malloc0 (sizeof (PUThread))) == NULL)) { + P_ERROR ("PUThread::p_uthread_create_internal: failed to allocate memory"); + return NULL; + } + + if (P_UNLIKELY ((ret->hdl = spawn_thread ("", + func, + pp_uthread_get_atheos_priority (prio), + stack_size, + ret)) < 0)) { + P_ERROR ("PUThread::p_uthread_create_internal: spawn_thread() failed"); + p_free (ret); + return NULL; + } + + if (P_UNLIKELY (resume_thread (ret->hdl) != 0)) { + P_ERROR ("PUThread::p_uthread_create_internal: resume_thread() failed"); + p_free (ret); + return NULL; + } + + ret->base.joinable = joinable; + ret->base.prio = prio; + + return ret; +} + +void +p_uthread_exit_internal (void) +{ + exit_thread (0); +} + +void +p_uthread_wait_internal (PUThread *thread) +{ + wait_for_thread (thread->hdl); +} + +void +p_uthread_set_name_internal (PUThread *thread) +{ + pchar *thr_name = NULL; + psize namelen = 0; + pint res = 0; + pboolean is_alloc = FALSE; + + thr_name = thread->base.name; + namelen = strlen (thr_name); + + if (namelen > OS_NAME_LENGTH - 1) { + if (P_UNLIKELY ((thr_name = p_malloc0 (namelen + 1)) == NULL)) { + P_ERROR ("PUThread::p_uthread_set_name_internal: failed to allocate memory"); + return; + } + + memcpy (thr_name, thread->base.name, OS_NAME_LENGTH - 1); + + is_alloc = TRUE; + } + + if (rename_thread (thread->hdl, thr_name) != 0) + P_WARNING ("PUThread::p_uthread_set_name_internal: failed to set thread system name"); + + if (is_alloc == TRUE) + p_free (thr_name); +} + +void +p_uthread_free_internal (PUThread *thread) +{ + p_free (thread); +} + +P_LIB_API void +p_uthread_yield (void) +{ + sched_yield (); +} + +P_LIB_API pboolean +p_uthread_set_priority (PUThread *thread, + PUThreadPriority prio) +{ + if (P_UNLIKELY (thread == NULL)) + return FALSE; + + set_thread_priority (thread->hdl, pp_uthread_get_atheos_priority (prio)); + + thread->base.prio = prio; + + return TRUE; +} + +P_LIB_API P_HANDLE +p_uthread_current_id (void) +{ + return (P_HANDLE) ((psize) get_thread_id (NULL)); +} + +P_LIB_API PUThreadKey * +p_uthread_local_new (PDestroyFunc free_func) +{ + PUThreadKey *ret; + + if (P_UNLIKELY ((ret = p_malloc0 (sizeof (PUThreadKey))) == NULL)) { + P_ERROR ("PUThread::p_uthread_local_new: failed to allocate memory"); + return NULL; + } + + ret->key = -1; + ret->free_func = free_func; + + return ret; +} + +P_LIB_API void +p_uthread_local_free (PUThreadKey *key) +{ + if (P_UNLIKELY (key == NULL)) + return; + + p_free (key); +} + +P_LIB_API ppointer +p_uthread_get_local (PUThreadKey *key) +{ + pint tls_key; + + if (P_UNLIKELY (key == NULL)) + return NULL; + + tls_key = pp_uthread_get_tls_key (key); + + if (P_LIKELY (tls_key >= 0)) + return get_tld (tls_key); + + return NULL; +} + +P_LIB_API void +p_uthread_set_local (PUThreadKey *key, + ppointer value) +{ + pint tls_key; + + if (P_UNLIKELY (key == NULL)) + return; + + tls_key = pp_uthread_get_tls_key (key); + + if (tls_key >= 0) + set_tld (tls_key, value); +} + +P_LIB_API void +p_uthread_replace_local (PUThreadKey *key, + ppointer value) +{ + pint tls_key; + ppointer old_value; + + if (P_UNLIKELY (key == NULL)) + return; + + tls_key = pp_uthread_get_tls_key (key); + + if (P_UNLIKELY (tls_key < 0)) + return; + + old_value = get_tld (tls_key); + + if (old_value != NULL && key->free_func != NULL) + key->free_func (old_value); + + set_tld (tls_key, value); +} -- cgit v1.2.1