Allow user to override pthread mutex and cond

This commit is contained in:
Justine Tunney 2024-12-23 21:57:52 -08:00
parent 4705705548
commit 55b7aa1632
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
54 changed files with 216 additions and 102 deletions

View file

@ -34,6 +34,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/itimer.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread2.h"
#include "libc/thread/tls.h"
#ifdef __x86_64__
@ -76,7 +77,7 @@ static textwindows dontinstrument uint32_t __itimer_worker(void *arg) {
__sig_generate(SIGALRM, SI_TIMER);
__itimer_lock();
struct timespec deadline = timeval_totimespec(waituntil);
pthread_cond_timedwait(&__itimer.cond, &__itimer.lock, &deadline);
_pthread_cond_timedwait(&__itimer.cond, &__itimer.lock, &deadline);
__itimer_unlock();
}
return 0;
@ -108,7 +109,7 @@ textwindows int sys_setitimer_nt(int which, const struct itimerval *neu,
if (!timeval_iszero(config.it_value))
config.it_value = timeval_add(config.it_value, timeval_real());
__itimer.it = config;
pthread_cond_signal(&__itimer.cond);
_pthread_cond_signal(&__itimer.cond);
}
__itimer_unlock();
ALLOW_SIGNALS;

View file

@ -98,6 +98,11 @@ extern _Atomic(unsigned) _pthread_count;
extern struct PosixThread _pthread_static;
extern _Atomic(pthread_key_dtor) _pthread_key_dtor[PTHREAD_KEYS_MAX];
int _pthread_cond_signal(pthread_cond_t *) libcesque paramsnonnull();
int _pthread_mutex_lock(pthread_mutex_t *) libcesque paramsnonnull();
int _pthread_mutex_trylock(pthread_mutex_t *) libcesque paramsnonnull();
int _pthread_mutex_unlock(pthread_mutex_t *) libcesque paramsnonnull();
int _pthread_mutex_wipe_np(pthread_mutex_t *) libcesque paramsnonnull();
int _pthread_reschedule(struct PosixThread *) libcesque;
int _pthread_setschedparam_freebsd(int, int, const struct sched_param *);
int _pthread_tid(struct PosixThread *) libcesque;
@ -111,6 +116,13 @@ void _pthread_onfork_prepare(void) libcesque;
void _pthread_unlock(void) libcesque;
void _pthread_zombify(struct PosixThread *) libcesque;
int _pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *) libcesque
paramsnonnull();
int _pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *,
const struct timespec *) libcesque
paramsnonnull((1, 2));
forceinline pureconst struct PosixThread *_pthread_self(void) {
return (struct PosixThread *)__get_tls()->tib_pthread;
}

View file

@ -63,17 +63,17 @@ static void _pthread_onfork(int i, const char *op) {
}
void _pthread_onfork_prepare(void) {
pthread_mutex_lock(&_atforks.lock);
_pthread_mutex_lock(&_atforks.lock);
_pthread_onfork(0, "prepare");
}
void _pthread_onfork_parent(void) {
_pthread_onfork(1, "parent");
pthread_mutex_unlock(&_atforks.lock);
_pthread_mutex_unlock(&_atforks.lock);
}
void _pthread_onfork_child(void) {
pthread_mutex_wipe_np(&_atforks.lock);
_pthread_mutex_wipe_np(&_atforks.lock);
_pthread_onfork(2, "child");
}
@ -171,12 +171,12 @@ int pthread_atfork(atfork_f prepare, atfork_f parent, atfork_f child) {
a->f[0] = prepare;
a->f[1] = parent;
a->f[2] = child;
pthread_mutex_lock(&_atforks.lock);
_pthread_mutex_lock(&_atforks.lock);
a->p[0] = 0;
a->p[1] = _atforks.list;
if (_atforks.list)
_atforks.list->p[0] = a;
_atforks.list = a;
pthread_mutex_unlock(&_atforks.lock);
_pthread_mutex_unlock(&_atforks.lock);
return 0;
}

View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/sysv/consts/clock.h"
#include "libc/thread/thread.h"
/**
* Initializes condition variable.
*
* @param attr may be null
* @return 0 on success, or error number on failure
*/
errno_t pthread_cond_init(pthread_cond_t *cond,
const pthread_condattr_t *attr) {
*cond = (pthread_cond_t){0};
if (attr) {
cond->_pshared = attr->_pshared;
cond->_clock = attr->_clock;
}
return 0;
}

View file

@ -43,7 +43,7 @@ __static_yoink("nsync_mu_trylock");
* @see pthread_cond_broadcast
* @see pthread_cond_wait
*/
errno_t pthread_cond_signal(pthread_cond_t *cond) {
errno_t _pthread_cond_signal(pthread_cond_t *cond) {
#if PTHREAD_USE_NSYNC
// do nothing if pthread_cond_timedwait() hasn't been called yet
@ -65,3 +65,5 @@ errno_t pthread_cond_signal(pthread_cond_t *cond) {
cosmo_futex_wake((atomic_int *)&cond->_sequence, 1, cond->_pshared);
return 0;
}
__weak_reference(_pthread_cond_signal, pthread_cond_signal);

View file

@ -49,7 +49,7 @@ static bool can_use_nsync(uint64_t muword) {
static void pthread_cond_leave(void *arg) {
struct PthreadWait *wait = (struct PthreadWait *)arg;
if (pthread_mutex_lock(wait->mutex))
if (_pthread_mutex_lock(wait->mutex))
__builtin_trap();
atomic_fetch_sub_explicit(&wait->cond->_waiters, 1, memory_order_acq_rel);
}
@ -68,7 +68,7 @@ static errno_t pthread_cond_timedwait_impl(pthread_cond_t *cond,
// start waiting on condition variable
atomic_fetch_add_explicit(&cond->_waiters, 1, memory_order_acq_rel);
if (pthread_mutex_unlock(mutex))
if (_pthread_mutex_unlock(mutex))
__builtin_trap();
// wait for sequence change, timeout, or cancelation
@ -110,8 +110,8 @@ static errno_t pthread_cond_timedwait_impl(pthread_cond_t *cond,
* @see pthread_cond_signal()
* @cancelationpoint
*/
errno_t pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime) {
errno_t _pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime) {
// validate arguments
struct PosixThread *pt;
@ -165,3 +165,5 @@ errno_t pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
END_CANCELATION_POINT;
return err;
}
__weak_reference(_pthread_cond_timedwait, pthread_cond_timedwait);

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/thread.h"
#include "libc/thread/thread2.h"
@ -39,6 +40,8 @@
* @see pthread_cond_signal
* @cancelationpoint
*/
errno_t pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
errno_t _pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
return pthread_cond_timedwait(cond, mutex, 0);
}
__weak_reference(_pthread_cond_wait, pthread_cond_wait);

View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2024 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/cosmo.h"
#include "libc/dce.h"
#include "libc/intrin/atomic.h"
#include "libc/thread/lock.h"
#include "libc/thread/thread.h"
/**
* Recovers mutex whose owner died.
*
* @return 0 on success, or errno on error
*/
int pthread_mutex_consistent(pthread_mutex_t *mutex) {
// The POSIX concept of robust mutexes is a bit cray. So let's change
// things up a bit. Rather than implementing all those goofy behaviors
// we shall simply use this function to weasel around the ownership
// check in pthread_mutex_unlock().
uint64_t word = atomic_load_explicit(&mutex->_word, memory_order_relaxed);
if (IsModeDbg() || MUTEX_TYPE(word) == PTHREAD_MUTEX_ERRORCHECK)
__deadlock_track(mutex, 0);
return 0;
}

View file

@ -0,0 +1,33 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
#include "libc/thread/thread.h"
/**
* Destroys mutex.
*
* Destroying a mutex that's currently locked or being waited upon, will
* result in undefined behavior.
*
* @return 0 on success, or error number on failure
*/
errno_t pthread_mutex_destroy(pthread_mutex_t *mutex) {
memset(mutex, -1, sizeof(*mutex));
return 0;
}

View file

@ -0,0 +1,40 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
/**
* Initializes mutex, e.g.
*
* pthread_mutex_t lock;
* pthread_mutexattr_t attr;
* pthread_mutexattr_init(&attr);
* pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
* pthread_mutex_init(&lock, &attr);
* pthread_mutexattr_destroy(&attr);
* // ...
* pthread_mutex_destroy(&lock);
*
* @param attr may be null
* @return 0 on success, or error number on failure
*/
int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr) {
*mutex = (pthread_mutex_t){._word = attr ? attr->_word : 0};
return 0;
}

View file

@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/str/str.h"
#include "libc/thread/thread.h"
/**
* Destroys mutex attr.
* @return 0 on success, or error number on failure
*/
errno_t pthread_mutexattr_destroy(pthread_mutexattr_t *attr) {
memset(attr, -1, sizeof(*attr));
return 0;
}

View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/lock.h"
#include "libc/thread/thread.h"
/**
* Gets mutex process sharing.
*
* @param pshared is set to one of the following
* - `PTHREAD_PROCESS_PRIVATE` (default)
* - `PTHREAD_PROCESS_SHARED`
* @return 0 on success, or error on failure
*/
errno_t pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr,
int *pshared) {
*pshared = MUTEX_PSHARED(attr->_word);
return 0;
}

View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/lock.h"
#include "libc/thread/thread.h"
/**
* Gets mutex type.
*
* @param type will be set to one of these on success
* - `PTHREAD_MUTEX_DEFAULT`
* - `PTHREAD_MUTEX_NORMAL`
* - `PTHREAD_MUTEX_RECURSIVE`
* - `PTHREAD_MUTEX_ERRORCHECK`
* @return 0 on success, or error on failure
*/
errno_t pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type) {
*type = MUTEX_TYPE(attr->_word);
return 0;
}

View file

@ -0,0 +1,28 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
/**
* Initializes mutex attr.
* @return 0 on success, or error number on failure
*/
errno_t pthread_mutexattr_init(pthread_mutexattr_t *attr) {
*attr = (pthread_mutexattr_t){0};
return 0;
}

View file

@ -0,0 +1,41 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/thread/lock.h"
#include "libc/thread/thread.h"
/**
* Sets mutex process sharing.
*
* @param pshared can be one of
* - `PTHREAD_PROCESS_PRIVATE` (default)
* - `PTHREAD_PROCESS_SHARED`
* @return 0 on success, or error on failure
* @raises EINVAL if `pshared` is invalid
*/
errno_t pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared) {
switch (pshared) {
case PTHREAD_PROCESS_SHARED:
case PTHREAD_PROCESS_PRIVATE:
attr->_word = MUTEX_SET_PSHARED(attr->_word, pshared);
return 0;
default:
return EINVAL;
}
}

View file

@ -0,0 +1,45 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/thread/lock.h"
#include "libc/thread/thread.h"
/**
* Sets mutex type.
*
* @param type can be one of
* - `PTHREAD_MUTEX_DEFAULT`
* - `PTHREAD_MUTEX_NORMAL`
* - `PTHREAD_MUTEX_RECURSIVE`
* - `PTHREAD_MUTEX_ERRORCHECK`
* @return 0 on success, or error on failure
* @raises EINVAL if `type` is invalid
*/
errno_t pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) {
switch (type) {
case PTHREAD_MUTEX_DEFAULT:
case PTHREAD_MUTEX_NORMAL:
case PTHREAD_MUTEX_RECURSIVE:
case PTHREAD_MUTEX_ERRORCHECK:
attr->_word = MUTEX_SET_TYPE(attr->_word, type);
return 0;
default:
return EINVAL;
}
}

View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/atomic.h"
#include "libc/thread/thread.h"
/**
* Destroys spin lock.
*
* @return 0 on success, or errno on error
*/
errno_t pthread_spin_destroy(pthread_spinlock_t *spin) {
atomic_store_explicit(&spin->_lock, -1, memory_order_relaxed);
return 0;
}

View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/atomic.h"
#include "libc/thread/thread.h"
/**
* Initializes spin lock.
*
* @param pshared is ignored, since this implementation always permits
* multiple processes to operate on the same spin locks
* @return 0 on success, or errno on error
* @see pthread_spin_destroy
* @see pthread_spin_lock
*/
errno_t pthread_spin_init(pthread_spinlock_t *spin, int pshared) {
atomic_store_explicit(&spin->_lock, 0, memory_order_relaxed);
return 0;
}

View file

@ -0,0 +1,63 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/atomic.h"
#include "libc/intrin/strace.h"
#include "libc/thread/thread.h"
/**
* Acquires spin lock, e.g.
*
* pthread_spinlock_t lock;
* pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
* pthread_spin_lock(&lock);
* // do work...
* pthread_spin_unlock(&lock);
* pthread_spin_destroy(&lock);
*
* This function has undefined behavior when `spin` wasn't intialized or
* was destroyed, and if the lock is already held by the calling thread.
*
* You can debug locks the acquisition of locks by building your program
* with `cosmocc -mdbg` and passing the `--strace` flag to your program.
* This will cause a line to be logged each time a mutex or spin lock is
* locked or unlocked. When locking, this is printed after the lock gets
* acquired. The entry to the lock operation will be logged too but only
* if the lock couldn't be immediately acquired. Lock logging works best
* when `mutex` refers to a static variable, in which case its name will
* be printed in the log.
*
* @return 0 on success, or errno on error
* @see pthread_spin_trylock
* @see pthread_spin_unlock
* @see pthread_spin_init
*/
errno_t pthread_spin_lock(pthread_spinlock_t *spin) {
if (atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire)) {
LOCKTRACE("acquiring pthread_spin_lock(%t)...", spin);
for (;;) {
for (;;)
if (!atomic_load_explicit(&spin->_lock, memory_order_relaxed))
break;
if (!atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire))
break;
}
}
LOCKTRACE("pthread_spin_lock(%t)", spin);
return 0;
}

View file

@ -0,0 +1,38 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/thread/thread.h"
/**
* Acquires spin lock if available.
*
* This function has undefined behavior when `spin` wasn't intialized,
* was destroyed, or if the lock's already held by the calling thread.
*
* @return 0 on success, or errno on error
* @raise EBUSY if lock is already held
*/
errno_t pthread_spin_trylock(pthread_spinlock_t *spin) {
if (!atomic_exchange_explicit(&spin->_lock, 1, memory_order_acquire)) {
return 0;
} else {
return EBUSY;
}
}

View file

@ -0,0 +1,36 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
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 appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/intrin/atomic.h"
#include "libc/intrin/strace.h"
#include "libc/thread/thread.h"
/**
* Releases spin lock.
*
* Calling this function when the lock isn't held by the calling thread
* has undefined behavior.
*
* @return 0 on success, or errno on error
* @see pthread_spin_lock
*/
errno_t pthread_spin_unlock(pthread_spinlock_t *spin) {
LOCKTRACE("pthread_spin_unlock(%t)", spin);
atomic_store_explicit(&spin->_lock, 0, memory_order_release);
return 0;
}

View file

@ -37,6 +37,7 @@
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#include "libc/thread/posixthread.internal.h"
#include "libc/thread/semaphore.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
@ -56,19 +57,18 @@ static struct Semaphores {
};
static void sem_open_lock(void) {
pthread_mutex_lock(&g_semaphores.lock);
_pthread_mutex_lock(&g_semaphores.lock);
}
static void sem_open_unlock(void) {
pthread_mutex_unlock(&g_semaphores.lock);
_pthread_mutex_unlock(&g_semaphores.lock);
}
static void sem_open_wipe(void) {
pthread_mutex_init(&g_semaphores.lock, 0);
_pthread_mutex_wipe_np(&g_semaphores.lock);
}
static void sem_open_setup(void) {
sem_open_wipe();
pthread_atfork(sem_open_lock, sem_open_unlock, sem_open_wipe);
}

View file

@ -48,6 +48,7 @@ COSMOPOLITAN_C_START_
#define PTHREAD_MUTEX_INITIALIZER {0, PTHREAD_MUTEX_DEFAULT}
#define PTHREAD_NORMAL_MUTEX_INITIALIZER_NP {0, PTHREAD_MUTEX_NORMAL}
#define PTHREAD_SHARED_MUTEX_INITIALIZER_NP {0, PTHREAD_PROCESS_SHARED}
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {0, PTHREAD_MUTEX_RECURSIVE}
#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP {0, PTHREAD_MUTEX_ERRORCHECK}