diff --git a/include/ircd/ctx/posix.h b/include/ircd/ctx/posix.h new file mode 100644 index 000000000..5e3ed9565 --- /dev/null +++ b/include/ircd/ctx/posix.h @@ -0,0 +1,627 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +extern "C" int +ircd_pthread_create(pthread_t *const thread, + const pthread_attr_t *const attr, + void *(*const start_routine)(void *), + void *const arg) +noexcept; + +extern "C" int +ircd_pthread_join(pthread_t __th, + void **__thread_return); + +extern "C" int +ircd_pthread_tryjoin_np(pthread_t __th, + void **__thread_return); +extern "C" int +ircd_pthread_timedjoin_np(pthread_t __th, + void **__thread_return, + const struct timespec *__abstime); +extern "C" int +ircd_pthread_detach(pthread_t __th) +noexcept; + +extern "C" int +ircd_pthread_getcpuclockid(pthread_t __thread_id, + __clockid_t *__clock_id) +noexcept; + +extern "C" int +ircd_pthread_atfork(void (*__prepare)(void), + void (*__parent)(void), + void (*__child)(void)) +noexcept; + +extern "C" void +ircd_pthread_exit(void *const retval); + +extern "C" pthread_t +ircd_pthread_self(void) +noexcept; + +// +// Initialization +// + +extern "C" int +ircd_pthread_once(pthread_once_t *__once_control, + void (*__init_routine)(void)); + +// +// Cancellation +// + +extern "C" int +ircd_pthread_setcancelstate(int __state, + int *__oldstate); +extern "C" int +ircd_pthread_setcanceltype(int __type, + int *__oldtype); +extern "C" int +ircd_pthread_cancel(pthread_t __th); + +extern "C" void +ircd_pthread_testcancel(void); + +// +// Scheduling +// + +extern "C" int +ircd_pthread_setschedparam(pthread_t __target_thread, + int __policy, + const struct sched_param *__param) +noexcept; + +extern "C" int +ircd_pthread_getschedparam(pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) +noexcept; + +extern "C" int +ircd_pthread_setschedprio(pthread_t __target_thread, + int __prio) +noexcept; + +extern "C" int +ircd_pthread_getname_np(pthread_t __target_thread, + char *__buf, + size_t __buflen) +noexcept; + +extern "C" int +ircd_pthread_setname_np(pthread_t __target_thread, + const char *__name) +noexcept; + +extern "C" int +ircd_pthread_getconcurrency(void) +noexcept; + +extern "C" int +ircd_pthread_setconcurrency(int __level) +noexcept; + +extern "C" int +ircd_pthread_setaffinity_np(pthread_t __th, + size_t __cpusetsize, + const cpu_set_t *__cpuset) +noexcept; + +extern "C" int +ircd_pthread_getaffinity_np(pthread_t __th, + size_t __cpusetsize, + cpu_set_t *__cpuset) +noexcept; + +extern "C" int +ircd_pthread_yield(void) +noexcept; + +// +// Attributes +// + +extern "C" int +ircd_pthread_attr_init(pthread_attr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_attr_destroy(pthread_attr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_attr_getdetachstate(const pthread_attr_t *__attr, + int *__detachstate) +noexcept; + +extern "C" int +ircd_pthread_attr_setdetachstate(pthread_attr_t *__attr, + int __detachstate) +noexcept; + +extern "C" int +ircd_pthread_attr_getguardsize(const pthread_attr_t *__attr, + size_t *__guardsize) +noexcept; + +extern "C" int +ircd_pthread_attr_setguardsize(pthread_attr_t *__attr, + size_t __guardsize) +noexcept; + +extern "C" int +ircd_pthread_attr_getschedparam(const pthread_attr_t *__restrict __attr, + struct sched_param *__restrict __param) +noexcept; + +extern "C" int +ircd_pthread_attr_setschedparam(pthread_attr_t *__restrict __attr, + const struct sched_param *__restrict __param) +noexcept; + +extern "C" int +ircd_pthread_attr_getschedpolicy(const pthread_attr_t *__restrict __attr, + int *__restrict __policy) +noexcept; + +extern "C" int +ircd_pthread_attr_setschedpolicy(pthread_attr_t *__attr, + int __policy) +noexcept; + +extern "C" int +ircd_pthread_attr_getinheritsched(const pthread_attr_t *__restrict __attr, + int *__restrict __inherit) +noexcept; + +extern "C" int +ircd_pthread_attr_setinheritsched(pthread_attr_t *__attr, + int __inherit) +noexcept; + +extern "C" int +ircd_pthread_attr_getscope(const pthread_attr_t *__restrict __attr, + int *__restrict __scope) +noexcept; + +extern "C" int +ircd_pthread_attr_setscope(pthread_attr_t *__attr, + int __scope) +noexcept; + +extern "C" int +ircd_pthread_attr_getstackaddr(const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr) +noexcept; + +extern "C" int +ircd_pthread_attr_setstackaddr(pthread_attr_t *__attr, + void *__stackaddr) +noexcept; + +extern "C" int +ircd_pthread_attr_getstacksize(const pthread_attr_t *__restrict __attr, + size_t *__restrict __stacksize) +noexcept; + +extern "C" int +ircd_pthread_attr_setstacksize(pthread_attr_t *__attr, + size_t __stacksize) +noexcept; + +extern "C" int +ircd_pthread_attr_getstack(const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) +noexcept; + +extern "C" int +ircd_pthread_attr_setstack(pthread_attr_t *__attr, + void *__stackaddr, + size_t __stacksize) +noexcept; + +extern "C" int +ircd_pthread_attr_setaffinity_np(pthread_attr_t *__attr, + size_t __cpusetsize, + const cpu_set_t *__cpuset) +noexcept; + +extern "C" int +ircd_pthread_attr_getaffinity_np(const pthread_attr_t *__attr, + size_t __cpusetsize, + cpu_set_t *__cpuset) +noexcept; + +extern "C" int +ircd_pthread_getattr_default_np(pthread_attr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_setattr_default_np(const pthread_attr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_getattr_np(pthread_t __th, + pthread_attr_t *__attr) +noexcept; + +// +// Thread-Local +// + +extern "C" int +ircd_pthread_key_create(pthread_key_t *__key, + void (*__destr_function)(void *)) +noexcept; + +extern "C" int +ircd_pthread_key_delete(pthread_key_t __key) +noexcept; + +extern "C" void * +ircd_pthread_getspecific(pthread_key_t __key) +noexcept; + +extern "C" int +ircd_pthread_setspecific(pthread_key_t __key, + const void *__pointer) +noexcept; + +// +// Spinlock +// + +extern "C" int +ircd_pthread_spin_init(pthread_spinlock_t *__lock, + int __pshared) +noexcept; + +extern "C" int +ircd_pthread_spin_destroy(pthread_spinlock_t *__lock) +noexcept; + +extern "C" int +ircd_pthread_spin_lock(pthread_spinlock_t *__lock) +noexcept; + +extern "C" int +ircd_pthread_spin_trylock(pthread_spinlock_t *__lock) +noexcept; + +extern "C" int +ircd_pthread_spin_unlock(pthread_spinlock_t *__lock) +noexcept; + +// +// Mutex +// + +extern "C" int +ircd_pthread_mutex_init(pthread_mutex_t *__mutex, + const pthread_mutexattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_mutex_destroy(pthread_mutex_t *__mutex) +noexcept; + +extern "C" int +ircd_pthread_mutex_trylock(pthread_mutex_t *__mutex) +noexcept; + +extern "C" int +ircd_pthread_mutex_lock(pthread_mutex_t *__mutex) +noexcept; + +extern "C" int +ircd_pthread_mutex_timedlock(pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict __abstime) +noexcept; + +extern "C" int +ircd_pthread_mutex_clocklock(pthread_mutex_t *__restrict __mutex, + clockid_t __clockid, + const struct timespec *__restrict __abstime) +noexcept; + +extern "C" int +ircd_pthread_mutex_unlock(pthread_mutex_t *__mutex) +noexcept; + +extern "C" int +ircd_pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict __mutex, + int *__restrict __prioceiling) +noexcept; + +extern "C" int +ircd_pthread_mutex_setprioceiling(pthread_mutex_t *__restrict __mutex, + int __prioceiling, + int *__restrict __old_ceiling) +noexcept; + +extern "C" int +ircd_pthread_mutex_consistent(pthread_mutex_t *__mutex) +noexcept; + +extern "C" int +ircd_pthread_mutex_consistent_np(pthread_mutex_t *__mutex) +noexcept; + +// +// Mutex Attributes +// + +extern "C" int +ircd_pthread_mutexattr_init(pthread_mutexattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_destroy(pthread_mutexattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, + int __pshared) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __kind) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_settype(pthread_mutexattr_t *__attr, + int __kind) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __protocol) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_setprotocol(pthread_mutexattr_t *__attr, + int __protocol) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __prioceiling) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_setprioceiling(pthread_mutexattr_t *__attr, + int __prioceiling) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_getrobust(const pthread_mutexattr_t *__attr, + int *__robustness) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *__attr, + int *__robustness) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_setrobust(pthread_mutexattr_t *__attr, + int __robustness) +noexcept; + +extern "C" int +ircd_pthread_mutexattr_setrobust_np(pthread_mutexattr_t *__attr, + int __robustness) +noexcept; + +// +// Shared Mutex +// + +extern "C" int +ircd_pthread_rwlock_init(pthread_rwlock_t *__restrict __rwlock, + const pthread_rwlockattr_t *__restrict __attr) +noexcept; + +extern "C" int +ircd_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock) +noexcept; + +extern "C" int +ircd_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock) +noexcept; + +extern "C" int +ircd_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock) +noexcept; + +extern "C" int +ircd_pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict __abstime) +noexcept; + +extern "C" int +ircd_pthread_rwlock_clockrdlock(pthread_rwlock_t *__restrict __rwlock, + clockid_t __clockid, + const struct timespec *__restrict __abstime) +noexcept; + +extern "C" int +ircd_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock) +noexcept; + +extern "C" int +ircd_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock) +noexcept; + +extern "C" int +ircd_pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict __abstime) +noexcept; + +extern "C" int +ircd_pthread_rwlock_clockwrlock(pthread_rwlock_t *__restrict __rwlock, + clockid_t __clockid, + const struct timespec *__restrict __abstime) +noexcept; + +extern "C" int +ircd_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock) +noexcept; + +// +// Shared Mutex Attributes +// + +extern "C" int +ircd_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept; + +extern "C" int +ircd_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr, + int __pshared) +noexcept; + +extern "C" int +ircd_pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *__restrict __attr, + int *__restrict __pref) +noexcept; + +extern "C" int +ircd_pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *__attr, + int __pref) +noexcept; + +// +// Condition Variable +// + +extern "C" int +ircd_pthread_cond_init(pthread_cond_t *__restrict __cond, + const pthread_condattr_t *__restrict __cond_attr) +noexcept; + +extern "C" int +ircd_pthread_cond_destroy(pthread_cond_t *__cond) +noexcept; + +extern "C" int +ircd_pthread_cond_signal(pthread_cond_t *__cond) +noexcept; + +extern "C" int +ircd_pthread_cond_broadcast(pthread_cond_t *__cond) +noexcept; + +extern "C" int +ircd_pthread_cond_wait(pthread_cond_t *const __restrict __cond, + pthread_mutex_t *const __restrict __mutex); + +extern "C" int +ircd_pthread_cond_timedwait(pthread_cond_t *const __restrict __cond, + pthread_mutex_t *const __restrict __mutex, + const struct timespec *__restrict __abstime); + +extern "C" int +ircd_pthread_cond_clockwait(pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __clockid_t __clock_id, + const struct timespec *__restrict __abstime); + +// +// Condition Variable Attributes +// + +extern "C" int +ircd_pthread_condattr_init(pthread_condattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_condattr_destroy(pthread_condattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_condattr_getpshared(const pthread_condattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept; + +extern "C" int +ircd_pthread_condattr_setpshared(pthread_condattr_t *__attr, + int __pshared) +noexcept; + +extern "C" int +ircd_pthread_condattr_getclock(const pthread_condattr_t *__restrict __attr, + __clockid_t *__restrict __clock_id) +noexcept; + +extern "C" int +ircd_pthread_condattr_setclock(pthread_condattr_t *__attr, + __clockid_t __clock_id) +noexcept; + +// +// Barrier +// + +extern "C" int +ircd_pthread_barrier_init(pthread_barrier_t *__restrict __barrier, + const pthread_barrierattr_t *__restrict __attr, + unsigned int __count) +noexcept; + +extern "C" int +ircd_pthread_barrier_destroy(pthread_barrier_t *__barrier) +noexcept; + +extern "C" int +ircd_pthread_barrier_wait(pthread_barrier_t *__barrier) +noexcept; + +// +// Barrier Attributes +// + +extern "C" int +ircd_pthread_barrierattr_init(pthread_barrierattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_barrierattr_destroy(pthread_barrierattr_t *__attr) +noexcept; + +extern "C" int +ircd_pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept; + +extern "C" int +ircd_pthread_barrierattr_setpshared(pthread_barrierattr_t *__attr, + int __pshared) +noexcept; diff --git a/ircd/Makefile.am b/ircd/Makefile.am index e24c634e7..c92b31d98 100644 --- a/ircd/Makefile.am +++ b/ircd/Makefile.am @@ -145,6 +145,7 @@ libircd_la_SOURCES += ctx_x86_64.S libircd_la_SOURCES += ctx.cc libircd_la_SOURCES += ctx_eh.cc libircd_la_SOURCES += ctx_ole.cc +libircd_la_SOURCES += ctx_posix.cc if AIO libircd_la_SOURCES += fs_aio.cc endif diff --git a/ircd/ctx_posix.cc b/ircd/ctx_posix.cc new file mode 100644 index 000000000..8e8a21e2b --- /dev/null +++ b/ircd/ctx_posix.cc @@ -0,0 +1,1409 @@ +// The Construct +// +// Copyright (C) The Construct Developers, Authors & Contributors +// Copyright (C) 2016-2020 Jason Volk +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice is present in all copies. The +// full license for this software is available in the LICENSE file. + +/////////////////////////////////////////////////////////////////////////////// +// +// This unit exists to mitigate unwanted use of pthreads by third-party +// libraries. It is NOT intended to supplant real threads with ircd::ctx at +// this time, as we still want real parallel execution ability available to +// the project and to other users of the address space. +// +// This unit is a work in progress. Its eventual goals are non-interference +// with the rest of the address space, and may even implement the full +// interface to offer actual functionality of ircd::ctx rather than focused +// hacks and mitigations. +// +#include +#include + +//#define IRCD_PTHREAD_DEADLK_CHK + +namespace ircd::ctx::posix +{ + extern log::log log; + std::vector ctxs; +} + +using ircd::always_assert; + +decltype(ircd::ctx::posix::log) +ircd::ctx::posix::log +{ + "ctx.posix" +}; + +int +ircd_pthread_create(pthread_t *const thread, + const pthread_attr_t *const attr, + void *(*const start_routine)(void *), + void *const arg) +noexcept +{ + assert(thread); + assert(start_routine); + assert(arg); + + ircd::ctx::posix::ctxs.emplace_back(ircd::context + { + "pthread", + 1024 * 1024 * 1UL, + ircd::context::POST, + std::bind(start_routine, arg), + }); + + *thread = id(ircd::ctx::posix::ctxs.back()); + + ircd::log::debug + { + ircd::ctx::posix::log, "pthread_create id:%lu attr:%p func:%p arg:%p", + *thread, + attr, + start_routine, + arg + }; + + return 0; +} + +int +ircd_pthread_join(pthread_t __th, + void **__thread_return) +{ + ircd::log::debug + { + ircd::ctx::posix::log, "pthread_join id:%lu thread_return:%p", + __th, + __thread_return, + }; + + auto it(begin(ircd::ctx::posix::ctxs)); + while(it != end(ircd::ctx::posix::ctxs)) + { + if(id(*it) == __th) + { + it->join(); + it = ircd::ctx::posix::ctxs.erase(it); + break; + } + else ++it; + } + + if(__thread_return) + *__thread_return = PTHREAD_CANCELED; + + return 0; +} + +int +ircd_pthread_tryjoin_np(pthread_t __th, + void **__thread_return) +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_timedjoin_np(pthread_t __th, + void **__thread_return, + const struct timespec *__abstime) +{ + always_assert(false); + return EINVAL; +} + +void +ircd_pthread_exit(void *const retval) +{ + always_assert(false); + __builtin_unreachable(); +} + +int +ircd_pthread_detach(pthread_t __th) +noexcept +{ + always_assert(false); + return EINVAL; +} + +pthread_t +ircd_pthread_self(void) +noexcept +{ + always_assert(ircd::ctx::current); + return id(ircd::ctx::cur()); +} + +int +ircd_pthread_getcpuclockid(pthread_t __thread_id, + __clockid_t *__clock_id) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_atfork(void (*__prepare)(void), + void (*__parent)(void), + void (*__child)(void)) +noexcept +{ + always_assert(false); + return EINVAL; +} + +// +// Initialization +// + +int +ircd_pthread_once(pthread_once_t *__once_control, + void (*__init_routine)(void)) +{ + static_assert(sizeof(std::atomic) == sizeof(pthread_once_t)); + + auto *const _once_control + { + reinterpret_cast *>(__once_control) + }; + + const int once_control + { + std::atomic_exchange(_once_control, 1) + }; + + assert(once_control == 1 || once_control == 0); + if(likely(once_control == 0)) + __init_routine(); + + return 0; +} + +// +// Cancellation +// + +int +ircd_pthread_setcancelstate(int __state, + int *__oldstate) +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_setcanceltype(int __type, + int *__oldtype) +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_cancel(pthread_t __th) +{ + always_assert(false); + return EINVAL; +} + +void +ircd_pthread_testcancel(void) +{ + always_assert(false); +} + +// +// Scheduling +// + +int +ircd_pthread_setschedparam(pthread_t __target_thread, + int __policy, + const struct sched_param *__param) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_getschedparam(pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_setschedprio(pthread_t __target_thread, + int __prio) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_getname_np(pthread_t __target_thread, + char *__buf, + size_t __buflen) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_setname_np(pthread_t __target_thread, + const char *__name) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_getconcurrency(void) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_setconcurrency(int __level) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_setaffinity_np(pthread_t __th, + size_t __cpusetsize, + const cpu_set_t *__cpuset) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_getaffinity_np(pthread_t __th, + size_t __cpusetsize, + cpu_set_t *__cpuset) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_yield(void) +noexcept +{ + assert(ircd::ctx::current); + ircd::ctx::yield(); + return 0; +} + +// +// Attributes +// + +int +ircd_pthread_attr_init(pthread_attr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_destroy(pthread_attr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getdetachstate(const pthread_attr_t *__attr, + int *__detachstate) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setdetachstate(pthread_attr_t *__attr, + int __detachstate) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getguardsize(const pthread_attr_t *__attr, + size_t *__guardsize) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setguardsize(pthread_attr_t *__attr, + size_t __guardsize) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getschedparam(const pthread_attr_t *__restrict __attr, + struct sched_param *__restrict __param) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setschedparam(pthread_attr_t *__restrict __attr, + const struct sched_param *__restrict __param) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getschedpolicy(const pthread_attr_t *__restrict __attr, + int *__restrict __policy) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setschedpolicy(pthread_attr_t *__attr, + int __policy) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getinheritsched(const pthread_attr_t *__restrict __attr, + int *__restrict __inherit) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setinheritsched(pthread_attr_t *__attr, + int __inherit) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getscope(const pthread_attr_t *__restrict __attr, + int *__restrict __scope) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setscope(pthread_attr_t *__attr, + int __scope) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getstackaddr(const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setstackaddr(pthread_attr_t *__attr, + void *__stackaddr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getstacksize(const pthread_attr_t *__restrict __attr, + size_t *__restrict __stacksize) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setstacksize(pthread_attr_t *__attr, + size_t __stacksize) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getstack(const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setstack(pthread_attr_t *__attr, + void *__stackaddr, + size_t __stacksize) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_setaffinity_np(pthread_attr_t *__attr, + size_t __cpusetsize, + const cpu_set_t *__cpuset) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_attr_getaffinity_np(const pthread_attr_t *__attr, + size_t __cpusetsize, + cpu_set_t *__cpuset) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_getattr_default_np(pthread_attr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_setattr_default_np(const pthread_attr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_getattr_np(pthread_t __th, + pthread_attr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Thread-Local +// + +int +ircd_pthread_key_create(pthread_key_t *__key, + void (*__destr_function)(void *)) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_key_delete(pthread_key_t __key) +noexcept +{ + always_assert(false); + return EINVAL; +} + +void * +ircd_pthread_getspecific(pthread_key_t __key) +noexcept +{ + always_assert(false); + return nullptr; +} + +int +ircd_pthread_setspecific(pthread_key_t __key, + const void *__pointer) +noexcept +{ + always_assert(false); + return EINVAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Spinlock +// + +int +ircd_pthread_spin_init(pthread_spinlock_t *__lock, + int __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_spin_destroy(pthread_spinlock_t *__lock) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_spin_lock(pthread_spinlock_t *__lock) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_spin_trylock(pthread_spinlock_t *__lock) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_spin_unlock(pthread_spinlock_t *__lock) +noexcept +{ + always_assert(false); + return EINVAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Mutex +// + +int +ircd_pthread_mutex_init(pthread_mutex_t *__mutex, + const pthread_mutexattr_t *__attr) +noexcept +{ + static_assert(sizeof(ircd::ctx::mutex) <= sizeof(pthread_mutex_t)); + assert(__mutex); + //assert(__attr); + + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + new (mutex) ircd::ctx::mutex; + return 0; +} + +int +ircd_pthread_mutex_destroy(pthread_mutex_t *__mutex) +noexcept +{ + assert(__mutex); + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + if(unlikely(mutex->locked())) + return EBUSY; + + mutex->~mutex(); + return 0; +} + +int +ircd_pthread_mutex_trylock(pthread_mutex_t *__mutex) +noexcept +{ + assert(__mutex); + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + if(!mutex->try_lock()) + return EBUSY; + + return 0; +} + +int +ircd_pthread_mutex_lock(pthread_mutex_t *__mutex) +noexcept +{ + assert(__mutex); + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + #ifdef IRCD_PTHREAD_DEADLK_CHK + if(unlikely(mutex->m == ircd::ctx::current)) + return EDEADLK; + #endif + + mutex->lock(); + return 0; +} + +int +ircd_pthread_mutex_timedlock(pthread_mutex_t *__restrict __mutex, + const struct timespec *__restrict __abstime) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutex_clocklock(pthread_mutex_t *__restrict __mutex, + clockid_t __clockid, + const struct timespec *__restrict __abstime) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutex_unlock(pthread_mutex_t *__mutex) +noexcept +{ + assert(__mutex); + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + if(unlikely(mutex->m != ircd::ctx::current)) + return EPERM; + + mutex->unlock(); + return 0; +} + +int +ircd_pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict __mutex, + int *__restrict __prioceiling) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutex_setprioceiling(pthread_mutex_t *__restrict __mutex, + int __prioceiling, + int *__restrict __old_ceiling) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutex_consistent(pthread_mutex_t *__mutex) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutex_consistent_np(pthread_mutex_t *__mutex) +noexcept +{ + always_assert(false); + return EINVAL; +} + +// +// Mutex Attributes +// + +int +ircd_pthread_mutexattr_init(pthread_mutexattr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_destroy(pthread_mutexattr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, + int __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __kind) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_settype(pthread_mutexattr_t *__attr, + int __kind) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __protocol) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_setprotocol(pthread_mutexattr_t *__attr, + int __protocol) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict __attr, + int *__restrict __prioceiling) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_setprioceiling(pthread_mutexattr_t *__attr, + int __prioceiling) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_getrobust(const pthread_mutexattr_t *__attr, + int *__robustness) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *__attr, + int *__robustness) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_setrobust(pthread_mutexattr_t *__attr, + int __robustness) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_mutexattr_setrobust_np(pthread_mutexattr_t *__attr, + int __robustness) +noexcept +{ + always_assert(false); + return EINVAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Shared Mutex +// + +int +ircd_pthread_rwlock_init(pthread_rwlock_t *__restrict __rwlock, + const pthread_rwlockattr_t *__restrict __attr) +noexcept +{ + static_assert(sizeof(ircd::ctx::shared_mutex) <= sizeof(pthread_rwlock_t)); + assert(__rwlock); + //assert(__attr); + + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + new (shared_mutex) ircd::ctx::shared_mutex; + return 0; +} + +int +ircd_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock) +noexcept +{ + assert(__rwlock); + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + const bool busy + { + !shared_mutex->can_lock_upgrade() + || shared_mutex->shares() + || shared_mutex->waiting() + }; + + if(unlikely(busy)) + return EBUSY; + + shared_mutex->~shared_mutex(); + return 0; +} + +int +ircd_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock) +noexcept +{ + assert(__rwlock); + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + shared_mutex->lock_shared(); + return 0; +} + +int +ircd_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock) +noexcept +{ + assert(__rwlock); + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + if(!shared_mutex->try_lock_shared()) + return EBUSY; + + return 0; +} + +int +ircd_pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict __abstime) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlock_clockrdlock(pthread_rwlock_t *__restrict __rwlock, + clockid_t __clockid, + const struct timespec *__restrict __abstime) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock) +noexcept +{ + assert(__rwlock); + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + #ifdef IRCD_PTHREAD_DEADLK_CHK + if(unlikely(shared_mutex->u == ircd::ctx::current)) + return EDEADLK; + #endif + + shared_mutex->lock(); + return 0; +} + +int +ircd_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock) +noexcept +{ + assert(__rwlock); + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + if(!shared_mutex->try_lock()) + return EBUSY; + + return 0; +} + +int +ircd_pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict __rwlock, + const struct timespec *__restrict __abstime) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlock_clockwrlock(pthread_rwlock_t *__restrict __rwlock, + clockid_t __clockid, + const struct timespec *__restrict __abstime) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock) +noexcept +{ + assert(__rwlock); + auto *const shared_mutex + { + reinterpret_cast(__rwlock) + }; + + // pthread interface has no rdunlock() and wrunlock() so we have to branch + if(shared_mutex->unique()) + { + if(unlikely(shared_mutex->u != ircd::ctx::current)) + return EPERM; + + shared_mutex->unlock(); + return 0; + } + + if(unlikely(shared_mutex->unique() || !shared_mutex->shares())) + return EPERM; + + shared_mutex->unlock_shared(); + return 0; +} + +// +// Shared Mutex Attributes +// + +int +ircd_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr, + int __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *__restrict __attr, + int *__restrict __pref) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *__attr, + int __pref) +noexcept +{ + always_assert(false); + return EINVAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Condition Variable +// + +int +ircd_pthread_cond_init(pthread_cond_t *__restrict __cond, + const pthread_condattr_t *__restrict __cond_attr) +noexcept +{ + static_assert(sizeof(ircd::ctx::condition_variable) <= sizeof(pthread_cond_t)); + assert(__cond); + //assert(__cond_attr); + + auto *const condition_variable + { + reinterpret_cast(__cond) + }; + + new (condition_variable) ircd::ctx::condition_variable; + return 0; +} + +int +ircd_pthread_cond_destroy(pthread_cond_t *__cond) +noexcept +{ + assert(__cond); + auto *const condition_variable + { + reinterpret_cast(__cond) + }; + + const bool busy + { + !condition_variable->empty() + }; + + if(unlikely(busy)) + return EBUSY; + + condition_variable->~condition_variable(); + return 0; +} + +int +ircd_pthread_cond_signal(pthread_cond_t *__cond) +noexcept +{ + auto *const condition_variable + { + reinterpret_cast(__cond) + }; + + condition_variable->notify(); + return 0; +} + +int +ircd_pthread_cond_broadcast(pthread_cond_t *__cond) +noexcept +{ + auto *const condition_variable + { + reinterpret_cast(__cond) + }; + + condition_variable->notify_all(); + return 0; +} + +int +ircd_pthread_cond_wait(pthread_cond_t *const __restrict __cond, + pthread_mutex_t *const __restrict __mutex) +{ + assert(__cond); + assert(__mutex); + + auto *const condition_variable + { + reinterpret_cast(__cond) + }; + + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + condition_variable->wait(*mutex); + return 0; +} + +int +ircd_pthread_cond_timedwait(pthread_cond_t *const __restrict __cond, + pthread_mutex_t *const __restrict __mutex, + const struct timespec *__restrict __abstime) +{ + using namespace std::chrono; + + assert(__cond); + assert(__mutex); + assert(__abstime); + + auto *const condition_variable + { + reinterpret_cast(__cond) + }; + + auto *const mutex + { + reinterpret_cast(__mutex) + }; + + const nanoseconds epoch + { + seconds(__abstime->tv_sec) + + nanoseconds(__abstime->tv_nsec) + }; + + const time_point time_point + { + epoch + }; + + const std::cv_status cv_status + { + condition_variable->wait_until(*mutex, time_point) + }; + + if(cv_status == std::cv_status::timeout) + return ETIMEDOUT; + + return 0; +} + +int +ircd_pthread_cond_clockwait(pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __clockid_t __clock_id, + const struct timespec *__restrict __abstime) +{ + always_assert(false); + return EINVAL; +} + +// +// Condition Variable Attributes +// + +int +ircd_pthread_condattr_init(pthread_condattr_t *__attr) +noexcept +{ + assert(__attr); + memset(__attr, 0x0, sizeof(pthread_condattr_t)); + return 0; +} + +int +ircd_pthread_condattr_destroy(pthread_condattr_t *__attr) +noexcept +{ + return 0; +} + +int +ircd_pthread_condattr_getpshared(const pthread_condattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_condattr_setpshared(pthread_condattr_t *__attr, + int __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_condattr_getclock(const pthread_condattr_t *__restrict __attr, + __clockid_t *__restrict __clock_id) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_condattr_setclock(pthread_condattr_t *__attr, + __clockid_t __clock_id) +noexcept +{ + always_assert(false); + return EINVAL; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Barrier +// + +int +ircd_pthread_barrier_init(pthread_barrier_t *__restrict __barrier, + const pthread_barrierattr_t *__restrict __attr, + unsigned int __count) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_barrier_destroy(pthread_barrier_t *__barrier) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_barrier_wait(pthread_barrier_t *__barrier) +noexcept +{ + always_assert(false); + return EINVAL; +} + +// +// Barrier Attributes +// + +int +ircd_pthread_barrierattr_init(pthread_barrierattr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_barrierattr_destroy(pthread_barrierattr_t *__attr) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict __attr, + int *__restrict __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +} + +int +ircd_pthread_barrierattr_setpshared(pthread_barrierattr_t *__attr, + int __pshared) +noexcept +{ + always_assert(false); + return EINVAL; +}