mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
Implement POSIX threads API
This commit is contained in:
parent
af24f21556
commit
9be364d40a
95 changed files with 6029 additions and 317 deletions
0
libc/bits/atomic.h
Executable file
0
libc/bits/atomic.h
Executable file
|
@ -16,6 +16,7 @@ const char *DescribeCapability(char[20], int);
|
|||
const char *DescribeClockName(char[32], int);
|
||||
const char *DescribeDirfd(char[12], int);
|
||||
const char *DescribeFrame(char[32], int);
|
||||
const char *DescribeFutexOp(int);
|
||||
const char *DescribeFutexResult(char[12], int);
|
||||
const char *DescribeHow(char[12], int);
|
||||
const char *DescribeMapFlags(char[64], int);
|
||||
|
|
|
@ -17,21 +17,15 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nt/enum/consolemodeflags.h"
|
||||
#include "libc/sysv/consts/futex.h"
|
||||
|
||||
const char *DescribeNtFutexOp(int x) {
|
||||
const struct DescribeFlags kFutexOp[] = {
|
||||
{FUTEX_WAIT_PRIVATE, "WAIT_PRIVATE"}, //
|
||||
{FUTEX_WAKE_PRIVATE, "WAKE_PRIVATE"}, //
|
||||
{FUTEX_REQUEUE_PRIVATE, "REQUEUE_PRIVATE"}, //
|
||||
{FUTEX_PRIVATE_FLAG, "PRIVATE_FLAG"}, //
|
||||
{FUTEX_REQUEUE, "REQUEUE"}, //
|
||||
{FUTEX_WAIT, "WAIT"}, //
|
||||
{FUTEX_WAKE, "WAKE"}, //
|
||||
};
|
||||
_Alignas(char) static char futexop[32];
|
||||
return DescribeFlags(futexop, sizeof(futexop), kFutexOp, ARRAYLEN(kFutexOp),
|
||||
"FUTEX_", x);
|
||||
const char *DescribeFutexOp(int x) {
|
||||
if (x == FUTEX_WAIT) return "FUTEX_WAIT";
|
||||
if (x == FUTEX_WAKE) return "FUTEX_WAKE";
|
||||
if (x == FUTEX_REQUEUE) return "FUTEX_REQUEUE";
|
||||
// order matters (the private bit might be zero)
|
||||
if (x == FUTEX_WAIT_PRIVATE) return "FUTEX_WAIT_PRIVATE";
|
||||
if (x == FUTEX_WAKE_PRIVATE) return "FUTEX_WAKE_PRIVATE";
|
||||
if (x == FUTEX_REQUEUE_PRIVATE) return "FUTEX_REQUEUE_PRIVATE";
|
||||
return "FUTEX_???";
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int _futex_wait(void *, int, struct timespec *) hidden;
|
||||
int _futex_wake(void *, int) hidden;
|
||||
int _futex_wait_public(void *, int, struct timespec *) hidden;
|
||||
int _futex_wait_private(void *, int, struct timespec *) hidden;
|
||||
int _futex_wake_public(void *, int) hidden;
|
||||
int _futex_wake_private(void *, int) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -20,15 +20,33 @@
|
|||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timespec.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/sysv/consts/futex.h"
|
||||
|
||||
int _futex(void *, int, int, struct timespec *) hidden;
|
||||
int _futex_wait(void *addr, int expect, struct timespec *timeout) {
|
||||
int ax = _futex(addr, FUTEX_WAIT, expect, timeout);
|
||||
|
||||
static dontinline int _futex_wait_impl(void *addr, int expect,
|
||||
struct timespec *timeout, int private) {
|
||||
int op, ax;
|
||||
op = FUTEX_WAIT | private;
|
||||
ax = _futex(addr, op, expect, timeout);
|
||||
if (SupportsLinux() && private && ax == -ENOSYS) {
|
||||
// RHEL5 doesn't support FUTEX_PRIVATE_FLAG
|
||||
op = FUTEX_WAIT;
|
||||
ax = _futex(addr, op, expect, timeout);
|
||||
}
|
||||
if (IsOpenbsd() && ax > 0) ax = -ax; // yes openbsd does this w/o cf
|
||||
STRACE("futex(%t, FUTEX_WAIT, %d, %s) → %s", addr, expect,
|
||||
STRACE("futex(%t, %s, %d, %s) → %s", addr, DescribeFutexOp(op), expect,
|
||||
DescribeTimespec(0, timeout), DescribeFutexResult(ax));
|
||||
return ax;
|
||||
}
|
||||
|
||||
int _futex_wait_public(void *addr, int expect, struct timespec *timeout) {
|
||||
return _futex_wait_impl(addr, expect, timeout, 0);
|
||||
}
|
||||
|
||||
int _futex_wait_private(void *addr, int expect, struct timespec *timeout) {
|
||||
return _futex_wait_impl(addr, expect, timeout, FUTEX_PRIVATE_FLAG);
|
||||
}
|
||||
|
|
|
@ -17,14 +17,32 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/sysv/consts/futex.h"
|
||||
|
||||
int _futex(void *, int, int) hidden;
|
||||
int _futex_wake(void *addr, int count) {
|
||||
int ax = _futex(addr, FUTEX_WAKE, count);
|
||||
STRACE("futex(%t, FUTEX_WAKE, %d) → %s", addr, count,
|
||||
|
||||
static dontinline int _futex_wake_impl(void *addr, int count, int private) {
|
||||
int op, ax;
|
||||
op = FUTEX_WAKE | private;
|
||||
ax = _futex(addr, op, count);
|
||||
if (SupportsLinux() && private && ax == -ENOSYS) {
|
||||
// RHEL5 doesn't support FUTEX_PRIVATE_FLAG
|
||||
op = FUTEX_WAKE;
|
||||
ax = _futex(addr, op, count);
|
||||
}
|
||||
STRACE("futex(%t, %s, %d) → %s", addr, DescribeFutexOp(op), count,
|
||||
DescribeFutexResult(ax));
|
||||
return ax;
|
||||
}
|
||||
|
||||
int _futex_wake_public(void *addr, int count) {
|
||||
return _futex_wake_impl(addr, count, 0);
|
||||
}
|
||||
|
||||
int _futex_wake_private(void *addr, int count) {
|
||||
return _futex_wake_impl(addr, count, FUTEX_PRIVATE_FLAG);
|
||||
}
|
||||
|
|
0
libc/intrin/intrin.h
Executable file
0
libc/intrin/intrin.h
Executable file
|
@ -73,6 +73,7 @@ o/$(MODE)/libc/intrin/kprintf.greg.o: private \
|
|||
-fno-sanitize=all \
|
||||
-fno-stack-protector
|
||||
|
||||
# TODO(jart): Do we really need these?
|
||||
# synchronization primitives are intended to be magic free
|
||||
o/$(MODE)/libc/intrin/futex_wait.o \
|
||||
o/$(MODE)/libc/intrin/futex_wake.o \
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define COSMOPOLITAN_LIBC_INTRIN_ONCE_H_
|
||||
#include "libc/intrin/spinlock.h"
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
#define _once(x) \
|
||||
({ \
|
||||
typeof(x) oncerc; \
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_
|
||||
#define COSMOPOLITAN_LIBC_RUNTIME_PTHREAD_H_
|
||||
|
||||
#define PTHREAD_ONCE_INIT 0
|
||||
|
||||
#define PTHREAD_KEYS_MAX 64
|
||||
|
||||
#define PTHREAD_ONCE_INIT 0
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD 31337
|
||||
|
||||
#define PTHREAD_MUTEX_DEFAULT PTHREAD_MUTEX_NORMAL
|
||||
#define PTHREAD_MUTEX_NORMAL 0
|
||||
|
@ -12,18 +14,29 @@
|
|||
#define PTHREAD_MUTEX_STALLED 0
|
||||
#define PTHREAD_MUTEX_ROBUST 1
|
||||
|
||||
#define PTHREAD_PROCESS_DEFAULT PTHREAD_PROCESS_PRIVATE
|
||||
#define PTHREAD_PROCESS_PRIVATE 0
|
||||
#define PTHREAD_PROCESS_SHARED 1
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/* clang-format off */
|
||||
#define PTHREAD_MUTEX_INITIALIZER {PTHREAD_MUTEX_DEFAULT}
|
||||
#define PTHREAD_RWLOCK_INITIALIZER {{{0}}}
|
||||
#define PTHREAD_COND_INITIALIZER {{{0}}}
|
||||
#define PTHREAD_COND_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
|
||||
#define PTHREAD_BARRIER_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
|
||||
#define PTHREAD_RWLOCK_INITIALIZER {PTHREAD_PROCESS_DEFAULT}
|
||||
/* clang-format on */
|
||||
|
||||
typedef unsigned long *pthread_t;
|
||||
typedef int pthread_once_t;
|
||||
typedef void *pthread_t;
|
||||
typedef int pthread_id_np_t;
|
||||
typedef int pthread_condattr_t;
|
||||
typedef int pthread_mutexattr_t;
|
||||
typedef int pthread_rwlockattr_t;
|
||||
typedef int pthread_barrierattr_t;
|
||||
typedef unsigned pthread_key_t;
|
||||
typedef _Atomic(char) pthread_once_t;
|
||||
typedef _Atomic(char) pthread_spinlock_t;
|
||||
typedef void (*pthread_key_dtor)(void *);
|
||||
|
||||
typedef struct {
|
||||
|
@ -35,65 +48,88 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
int attr;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
typedef struct {
|
||||
int attr;
|
||||
} pthread_condattr_t;
|
||||
|
||||
typedef struct {
|
||||
int attr[2];
|
||||
} pthread_rwlockattr_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
int __i[9];
|
||||
volatile int __vi[9];
|
||||
unsigned __s[9];
|
||||
} __u;
|
||||
} pthread_attr_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
int __i[12];
|
||||
volatile int __vi[12];
|
||||
void *__p[12];
|
||||
} __u;
|
||||
_Atomic(int) waits;
|
||||
_Atomic(unsigned) seq;
|
||||
} pthread_cond_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
int __i[8];
|
||||
volatile int __vi[8];
|
||||
void *__p[8];
|
||||
} __u;
|
||||
int attr;
|
||||
int count;
|
||||
_Atomic(int) waits;
|
||||
_Atomic(int) popped;
|
||||
} pthread_barrier_t;
|
||||
|
||||
typedef struct {
|
||||
int attr;
|
||||
_Atomic(int) lock;
|
||||
_Atomic(int) waits;
|
||||
} pthread_rwlock_t;
|
||||
|
||||
typedef struct {
|
||||
int scope;
|
||||
int schedpolicy;
|
||||
int detachstate;
|
||||
int inheritsched;
|
||||
size_t guardsize;
|
||||
size_t stacksize;
|
||||
} pthread_attr_t;
|
||||
|
||||
int pthread_yield(void);
|
||||
void pthread_exit(void *) wontreturn;
|
||||
pthread_t pthread_self(void) pureconst;
|
||||
pthread_id_np_t pthread_getthreadid_np(void);
|
||||
int64_t pthread_getunique_np(pthread_t);
|
||||
int pthread_attr_init(pthread_attr_t *);
|
||||
int pthread_attr_destroy(pthread_attr_t *);
|
||||
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
|
||||
int pthread_attr_setdetachstate(pthread_attr_t *, int);
|
||||
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
|
||||
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
|
||||
int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
|
||||
int pthread_attr_setinheritsched(pthread_attr_t *, int);
|
||||
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
|
||||
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
|
||||
int pthread_attr_getscope(const pthread_attr_t *, int *);
|
||||
int pthread_attr_setscope(pthread_attr_t *, int);
|
||||
int pthread_attr_getstack(const pthread_attr_t *, void **, size_t *);
|
||||
int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
|
||||
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
|
||||
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
|
||||
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *),
|
||||
void *);
|
||||
int pthread_yield(void);
|
||||
int pthread_detach(pthread_t);
|
||||
int pthread_cancel(pthread_t);
|
||||
int pthread_join(pthread_t, void **);
|
||||
int pthread_equal(pthread_t, pthread_t);
|
||||
int pthread_once(pthread_once_t *, void (*)(void));
|
||||
int pthread_spin_init(pthread_spinlock_t *, int);
|
||||
int pthread_spin_destroy(pthread_spinlock_t *);
|
||||
int pthread_spin_lock(pthread_spinlock_t *);
|
||||
int pthread_spin_unlock(pthread_spinlock_t *);
|
||||
int pthread_spin_trylock(pthread_spinlock_t *);
|
||||
int pthread_mutexattr_init(pthread_mutexattr_t *);
|
||||
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
|
||||
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
|
||||
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
|
||||
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
|
||||
int pthread_mutex_lock(pthread_mutex_t *);
|
||||
int pthread_mutex_unlock(pthread_mutex_t *);
|
||||
int pthread_mutex_trylock(pthread_mutex_t *);
|
||||
int pthread_mutex_destroy(pthread_mutex_t *);
|
||||
int pthread_mutex_consistent(pthread_mutex_t *);
|
||||
int pthread_mutexattr_init(pthread_mutexattr_t *);
|
||||
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
|
||||
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
|
||||
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
|
||||
int pthread_condattr_init(pthread_condattr_t *);
|
||||
int pthread_condattr_destroy(pthread_condattr_t *);
|
||||
int pthread_condattr_setpshared(pthread_condattr_t *, int);
|
||||
int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
|
||||
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
|
||||
int pthread_cond_destroy(pthread_cond_t *);
|
||||
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
|
||||
int pthread_cond_broadcast(pthread_cond_t *);
|
||||
int pthread_cancel(pthread_t);
|
||||
int pthread_cond_signal(pthread_cond_t *);
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
|
||||
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
|
||||
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
|
||||
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
|
||||
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *);
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *);
|
||||
|
@ -105,20 +141,70 @@ int pthread_key_create(pthread_key_t *, pthread_key_dtor);
|
|||
int pthread_key_delete(pthread_key_t);
|
||||
int pthread_setspecific(pthread_key_t, void *);
|
||||
void *pthread_getspecific(pthread_key_t);
|
||||
int pthread_barrierattr_init(pthread_barrierattr_t *);
|
||||
int pthread_barrierattr_destroy(pthread_barrierattr_t *);
|
||||
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *);
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
|
||||
int pthread_barrier_wait(pthread_barrier_t *);
|
||||
int pthread_barrier_destroy(pthread_barrier_t *);
|
||||
int pthread_barrier_init(pthread_barrier_t *, const pthread_barrierattr_t *,
|
||||
unsigned);
|
||||
|
||||
#define pthread_mutexattr_init(pAttr) ((pAttr)->attr = PTHREAD_MUTEX_DEFAULT, 0)
|
||||
#define pthread_mutexattr_destroy(pAttr) ((pAttr)->attr = 0)
|
||||
#define pthread_mutexattr_gettype(pAttr, pType) (*(pType) = (pAttr)->attr, 0)
|
||||
#define pthread_mutexattr_settype(pAttr, type) ((pAttr)->attr = type, 0)
|
||||
#define pthread_spin_init(pSpin, multiprocess) (*(pSpin) = 0)
|
||||
#define pthread_spin_destroy(pSpin) (*(pSpin) = 0)
|
||||
|
||||
#if (__GNUC__ + 0) * 100 + (__GNUC_MINOR__ + 0) >= 407
|
||||
extern const errno_t EBUSY;
|
||||
#define pthread_spin_unlock(pSpin) \
|
||||
(__atomic_store_n(pSpin, 0, __ATOMIC_RELAXED), 0)
|
||||
#define pthread_spin_trylock(pSpin) \
|
||||
(__atomic_test_and_set(pSpin, __ATOMIC_SEQ_CST) ? EBUSY : 0)
|
||||
#ifdef TINY
|
||||
#define pthread_spin_lock(pSpin) __pthread_spin_lock_tiny(pSpin)
|
||||
#else
|
||||
#define pthread_spin_lock(pSpin) __pthread_spin_lock_cooperative(pSpin)
|
||||
#endif
|
||||
#define __pthread_spin_lock_tiny(pSpin) \
|
||||
({ \
|
||||
while (__atomic_test_and_set(pSpin, __ATOMIC_SEQ_CST)) { \
|
||||
__builtin_ia32_pause(); \
|
||||
} \
|
||||
0; \
|
||||
})
|
||||
#define __pthread_spin_lock_cooperative(pSpin) \
|
||||
({ \
|
||||
char __x; \
|
||||
volatile int __i; \
|
||||
unsigned __tries = 0; \
|
||||
pthread_spinlock_t *__lock = pSpin; \
|
||||
for (;;) { \
|
||||
__atomic_load(__lock, &__x, __ATOMIC_RELAXED); \
|
||||
if (!__x && !__atomic_test_and_set(__lock, __ATOMIC_SEQ_CST)) { \
|
||||
break; \
|
||||
} else if (__tries < 7) { \
|
||||
for (__i = 0; __i != 1 << __tries; __i++) { \
|
||||
} \
|
||||
__tries++; \
|
||||
} else { \
|
||||
pthread_yield(); \
|
||||
} \
|
||||
} \
|
||||
0; \
|
||||
})
|
||||
#endif /* GCC 4.7+ */
|
||||
|
||||
#define pthread_mutexattr_init(pAttr) (*(pAttr) = PTHREAD_MUTEX_DEFAULT, 0)
|
||||
#define pthread_mutexattr_destroy(pAttr) (*(pAttr) = 0)
|
||||
#define pthread_mutexattr_gettype(pAttr, pType) (*(pType) = *(pAttr), 0)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define pthread_mutex_init(mutex, pAttr) \
|
||||
({ \
|
||||
pthread_mutexattr_t *_pAttr = (pAttr); \
|
||||
*(mutex) = (pthread_mutex_t){ \
|
||||
(_pAttr) ? (_pAttr)->attr : PTHREAD_MUTEX_DEFAULT, \
|
||||
}; \
|
||||
0; \
|
||||
#define pthread_mutex_init(mutex, pAttr) \
|
||||
({ \
|
||||
pthread_mutexattr_t *_pAttr = (pAttr); \
|
||||
*(mutex) = (pthread_mutex_t){ \
|
||||
_pAttr ? *_pAttr : PTHREAD_MUTEX_DEFAULT, \
|
||||
}; \
|
||||
0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
@ -138,6 +224,42 @@ void *pthread_getspecific(pthread_key_t);
|
|||
: pthread_mutex_unlock(mutex))
|
||||
#endif
|
||||
|
||||
#define pthread_condattr_init(pAttr) (*(pAttr) = PTHREAD_PROCESS_DEFAULT, 0)
|
||||
#define pthread_condattr_destroy(pAttr) (*(pAttr) = 0)
|
||||
#define pthread_condattr_getpshared(pAttr, pPshared) (*(pPshared) = *(pAttr), 0)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define pthread_cond_init(cond, pAttr) \
|
||||
({ \
|
||||
pthread_condattr_t *_pAttr = (pAttr); \
|
||||
*(cond) = (pthread_cond_t){ \
|
||||
_pAttr ? *_pAttr : PTHREAD_PROCESS_DEFAULT, \
|
||||
}; \
|
||||
0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define pthread_barrierattr_init(pAttr) (*(pAttr) = PTHREAD_PROCESS_DEFAULT, 0)
|
||||
#define pthread_barrierattr_destroy(pAttr) (*(pAttr) = 0)
|
||||
#define pthread_barrierattr_getpshared(pAttr, pPshared) \
|
||||
(*(pPshared) = *(pAttr), 0)
|
||||
|
||||
#define pthread_rwlockattr_init(pAttr) (*(pAttr) = PTHREAD_PROCESS_DEFAULT, 0)
|
||||
#define pthread_rwlockattr_destroy(pAttr) (*(pAttr) = 0)
|
||||
#define pthread_rwlockattr_getpshared(pAttr, pPshared) \
|
||||
(*(pPshared) = *(pAttr), 0)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define pthread_rwlock_init(rwlock, pAttr) \
|
||||
({ \
|
||||
pthread_rwlockattr_t *_pAttr = (pAttr); \
|
||||
*(rwlock) = (pthread_rwlock_t){ \
|
||||
_pAttr ? *_pAttr : PTHREAD_PROCESS_DEFAULT, \
|
||||
}; \
|
||||
0; \
|
||||
})
|
||||
#endif
|
||||
|
||||
int _pthread_mutex_wake(pthread_mutex_t *) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
16
libc/intrin/pthread2.h
Normal file
16
libc/intrin/pthread2.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_INTRIN_PTHREAD2_H_
|
||||
#define COSMOPOLITAN_LIBC_INTRIN_PTHREAD2_H_
|
||||
#include "libc/calls/struct/sched_param.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
|
||||
int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
|
||||
int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *,
|
||||
const struct timespec *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_INTRIN_PTHREAD2_H_ */
|
28
libc/intrin/pthread_attr_destroy.c
Normal file
28
libc/intrin/pthread_attr_destroy.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Destroys pthread attributes.
|
||||
*/
|
||||
int pthread_attr_destroy(pthread_attr_t *attr) {
|
||||
bzero(attr, sizeof(*attr));
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_getdetachstate.c
Normal file
24
libc/intrin/pthread_attr_getdetachstate.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_getdetachstate(const pthread_attr_t *a, int *x) {
|
||||
*x = a->detachstate;
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_getguardsize.c
Normal file
24
libc/intrin/pthread_attr_getguardsize.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_getguardsize(const pthread_attr_t *a, size_t *x) {
|
||||
*x = a->guardsize;
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_getscope.c
Normal file
24
libc/intrin/pthread_attr_getscope.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_getscope(const pthread_attr_t *a, int *x) {
|
||||
*x = a->scope;
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_getstacksize.c
Normal file
24
libc/intrin/pthread_attr_getstacksize.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_getstacksize(const pthread_attr_t *a, size_t *x) {
|
||||
*x = a->stacksize;
|
||||
return 0;
|
||||
}
|
28
libc/intrin/pthread_attr_init.c
Normal file
28
libc/intrin/pthread_attr_init.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Initializes pthread attributes.
|
||||
*/
|
||||
int pthread_attr_init(pthread_attr_t *attr) {
|
||||
bzero(attr, sizeof(*attr));
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_setdetachstate.c
Normal file
24
libc/intrin/pthread_attr_setdetachstate.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_setdetachstate(pthread_attr_t *a, int x) {
|
||||
a->detachstate = x;
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_setguardsize.c
Normal file
24
libc/intrin/pthread_attr_setguardsize.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_setguardsize(pthread_attr_t *a, size_t x) {
|
||||
a->guardsize = x;
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_setscope.c
Normal file
24
libc/intrin/pthread_attr_setscope.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_setscope(pthread_attr_t *a, int x) {
|
||||
a->scope = x;
|
||||
return 0;
|
||||
}
|
24
libc/intrin/pthread_attr_setstacksize.c
Normal file
24
libc/intrin/pthread_attr_setstacksize.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
int pthread_attr_setstacksize(pthread_attr_t *a, size_t x) {
|
||||
a->stacksize = x;
|
||||
return 0;
|
||||
}
|
36
libc/intrin/pthread_barrier_destroy.c
Normal file
36
libc/intrin/pthread_barrier_destroy.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys barrier.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
* @raise EINVAL if threads are still inside the barrier
|
||||
*/
|
||||
int pthread_barrier_destroy(pthread_barrier_t *barrier) {
|
||||
if (barrier->waits || barrier->popped) {
|
||||
assert(!"deadlock");
|
||||
return EINVAL;
|
||||
}
|
||||
*barrier = (pthread_barrier_t)PTHREAD_BARRIER_INITIALIZER;
|
||||
return 0;
|
||||
}
|
45
libc/intrin/pthread_barrier_init.c
Normal file
45
libc/intrin/pthread_barrier_init.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Initializes barrier.
|
||||
*
|
||||
* @param attr may be null
|
||||
* @param count is how many threads need to call pthread_barrier_wait()
|
||||
* before the barrier is released, which must be greater than zero
|
||||
* @return 0 on success, or error number on failure
|
||||
* @raise EINVAL if `count` isn't greater than zero or overflows
|
||||
*/
|
||||
int pthread_barrier_init(pthread_barrier_t *barrier,
|
||||
const pthread_barrierattr_t *attr, unsigned count) {
|
||||
if (count && count < INT_MAX / 2) {
|
||||
*barrier = (pthread_barrier_t){
|
||||
attr ? *attr : PTHREAD_PROCESS_DEFAULT,
|
||||
count,
|
||||
};
|
||||
return 0;
|
||||
} else {
|
||||
assert(!"bad count");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
74
libc/intrin/pthread_barrier_wait.c
Normal file
74
libc/intrin/pthread_barrier_wait.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
* Waits for all threads to arrive at barrier.
|
||||
*
|
||||
* When the barrier is broken, the state becomes reset to what it was
|
||||
* when pthread_barrier_init() was called, so that the barrior may be
|
||||
* used again in the same way. The last thread to arrive shall be the
|
||||
* last to leave and it returns a magic value.
|
||||
*
|
||||
* @return 0 on success, `PTHREAD_BARRIER_SERIAL_THREAD` to one lucky
|
||||
* thread which was the last arrival, or an errno on error
|
||||
*/
|
||||
int pthread_barrier_wait(pthread_barrier_t *barrier) {
|
||||
if (atomic_fetch_add(&barrier->waits, 1) + 1 == barrier->count) {
|
||||
if (atomic_fetch_add(&barrier->waits, 1) + 1 < barrier->count * 2) {
|
||||
atomic_store(&barrier->popped, 1);
|
||||
do {
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
if (barrier->attr == PTHREAD_PROCESS_SHARED) {
|
||||
_futex_wake_public(&barrier->popped, INT_MAX);
|
||||
} else {
|
||||
_futex_wake_private(&barrier->popped, INT_MAX);
|
||||
}
|
||||
} else {
|
||||
pthread_yield();
|
||||
}
|
||||
} while (atomic_load_explicit(&barrier->waits, memory_order_relaxed) <
|
||||
barrier->count * 2);
|
||||
atomic_store_explicit(&barrier->popped, 0, memory_order_relaxed);
|
||||
}
|
||||
atomic_store_explicit(&barrier->waits, 0, memory_order_relaxed);
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
}
|
||||
do {
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
if (barrier->attr == PTHREAD_PROCESS_SHARED) {
|
||||
_futex_wait_public(&barrier->popped, 0, 0);
|
||||
} else {
|
||||
_futex_wait_private(&barrier->popped, 0, 0);
|
||||
}
|
||||
} else {
|
||||
pthread_yield();
|
||||
}
|
||||
} while (atomic_load_explicit(&barrier->waits, memory_order_relaxed) <
|
||||
barrier->count);
|
||||
atomic_fetch_add(&barrier->waits, 1);
|
||||
return 0;
|
||||
}
|
28
libc/intrin/pthread_barrierattr_destroy.c
Normal file
28
libc/intrin/pthread_barrierattr_destroy.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys barrier attributes.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_barrierattr_destroy)(pthread_barrierattr_t *attr) {
|
||||
return pthread_barrierattr_destroy(attr);
|
||||
}
|
32
libc/intrin/pthread_barrierattr_getpshared.c
Normal file
32
libc/intrin/pthread_barrierattr_getpshared.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Gets barrier process sharing.
|
||||
*
|
||||
* @param pshared is set to one of the following
|
||||
* - `PTHREAD_PROCESS_SHARED`
|
||||
* - `PTHREAD_PROCESS_PRIVATE`
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_barrierattr_getpshared)(const pthread_barrierattr_t *attr,
|
||||
int *pshared) {
|
||||
return pthread_barrierattr_getpshared(attr, pshared);
|
||||
}
|
28
libc/intrin/pthread_barrierattr_init.c
Normal file
28
libc/intrin/pthread_barrierattr_init.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Initializes barrier attributes.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_barrierattr_init)(pthread_barrierattr_t *attr) {
|
||||
return pthread_barrierattr_init(attr);
|
||||
}
|
40
libc/intrin/pthread_barrierattr_setpshared.c
Normal file
40
libc/intrin/pthread_barrierattr_setpshared.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Sets barrier process sharing.
|
||||
*
|
||||
* @param pshared can be one of
|
||||
* - `PTHREAD_PROCESS_SHARED`
|
||||
* - `PTHREAD_PROCESS_PRIVATE`
|
||||
* @return 0 on success, or error on failure
|
||||
* @raises EINVAL if `pshared` is invalid
|
||||
*/
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) {
|
||||
switch (pshared) {
|
||||
case PTHREAD_PROCESS_SHARED:
|
||||
case PTHREAD_PROCESS_PRIVATE:
|
||||
*attr = pshared;
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
100
libc/intrin/pthread_cond_broadcast.c
Normal file
100
libc/intrin/pthread_cond_broadcast.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
static dontinline int pthread_cond_signal_impl(pthread_cond_t *cond, int n) {
|
||||
if (atomic_load_explicit(&cond->waits, memory_order_relaxed)) {
|
||||
atomic_fetch_add(&cond->seq, 1);
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
if (cond->attr == PTHREAD_PROCESS_SHARED) {
|
||||
_futex_wake_public(&cond->seq, n);
|
||||
} else {
|
||||
_futex_wake_private(&cond->seq, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes at least one thread waiting on condition, e.g.
|
||||
*
|
||||
* pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
* pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
*
|
||||
* // thread pool waiters
|
||||
* pthread_mutex_lock(&lock);
|
||||
* pthread_cond_wait(&cond, &lock);
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* // waker upper
|
||||
* pthread_mutex_lock(&lock);
|
||||
* pthread_cond_signal(&cond);
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* This function has no effect if there aren't any threads currently
|
||||
* waiting on the condition.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @see pthread_cond_broadcast
|
||||
* @see pthread_cond_wait
|
||||
*/
|
||||
int pthread_cond_signal(pthread_cond_t *cond) {
|
||||
return pthread_cond_signal_impl(cond, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wakes all threads waiting on condition, e.g.
|
||||
*
|
||||
* pthread_mutex_t lock;
|
||||
* pthread_mutexattr_t mattr;
|
||||
* pthread_mutexattr_init(&mattr);
|
||||
* pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_ERRORCHECK);
|
||||
* pthread_mutex_init(&lock, &mattr);
|
||||
*
|
||||
* pthread_cond_t cond;
|
||||
* pthread_condattr_t cattr;
|
||||
* pthread_condattr_init(&cattr);
|
||||
* pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
|
||||
* pthread_cond_init(&cond, &cattr);
|
||||
*
|
||||
* // waiting threads
|
||||
* CHECK_EQ(0, pthread_mutex_lock(&lock));
|
||||
* CHECK_EQ(0, pthread_cond_wait(&cond, &lock));
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* // notifying thread
|
||||
* CHECK_EQ(0, pthread_mutex_lock(&lock));
|
||||
* pthread_cond_broadcast(&cond);
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* This function has no effect if there aren't any threads currently
|
||||
* waiting on the condition.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @see pthread_cond_signal
|
||||
* @see pthread_cond_wait
|
||||
*/
|
||||
int pthread_cond_broadcast(pthread_cond_t *cond) {
|
||||
return pthread_cond_signal_impl(cond, INT_MAX);
|
||||
}
|
36
libc/intrin/pthread_cond_destroy.c
Normal file
36
libc/intrin/pthread_cond_destroy.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys condition.
|
||||
*
|
||||
* @return 0 on success, or error number on failure
|
||||
* @raise EINVAL if threads are still waiting on condition
|
||||
*/
|
||||
int pthread_cond_destroy(pthread_cond_t *cond) {
|
||||
if (cond->waits) {
|
||||
assert(!"deadlock");
|
||||
return EINVAL;
|
||||
}
|
||||
*cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
|
||||
return 0;
|
||||
}
|
29
libc/intrin/pthread_cond_init.c
Normal file
29
libc/intrin/pthread_cond_init.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Initializes condition.
|
||||
*
|
||||
* @param attr may be null
|
||||
* @return 0 on success, or error number on failure
|
||||
*/
|
||||
int(pthread_cond_init)(pthread_cond_t *cond, const pthread_condattr_t *attr) {
|
||||
return pthread_cond_init(cond, attr);
|
||||
}
|
28
libc/intrin/pthread_condattr_destroy.c
Normal file
28
libc/intrin/pthread_condattr_destroy.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys condition attributes.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_condattr_destroy)(pthread_condattr_t *attr) {
|
||||
return pthread_condattr_destroy(attr);
|
||||
}
|
31
libc/intrin/pthread_condattr_getpshared.c
Normal file
31
libc/intrin/pthread_condattr_getpshared.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Gets condition process sharing.
|
||||
*
|
||||
* @param pshared is set to one of the following
|
||||
* - `PTHREAD_PROCESS_SHARED`
|
||||
* - `PTHREAD_PROCESS_PRIVATE`
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_condattr_getpshared)(const pthread_condattr_t *attr, int *pshared) {
|
||||
return pthread_condattr_getpshared(attr, pshared);
|
||||
}
|
28
libc/intrin/pthread_condattr_init.c
Normal file
28
libc/intrin/pthread_condattr_init.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Initializes condition attributes.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_condattr_init)(pthread_condattr_t *attr) {
|
||||
return pthread_condattr_init(attr);
|
||||
}
|
40
libc/intrin/pthread_condattr_setpshared.c
Normal file
40
libc/intrin/pthread_condattr_setpshared.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Sets condition process sharing.
|
||||
*
|
||||
* @param pshared can be one of
|
||||
* - `PTHREAD_PROCESS_SHARED`
|
||||
* - `PTHREAD_PROCESS_PRIVATE`
|
||||
* @return 0 on success, or error on failure
|
||||
* @raises EINVAL if `pshared` is invalid
|
||||
*/
|
||||
int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared) {
|
||||
switch (pshared) {
|
||||
case PTHREAD_PROCESS_SHARED:
|
||||
case PTHREAD_PROCESS_PRIVATE:
|
||||
*attr = pshared;
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
|
@ -19,20 +19,18 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Destroys mutex.
|
||||
*
|
||||
* @return 0 on success, or error number on failure
|
||||
* @raise EINVAL if mutex is locked in our implementation
|
||||
*/
|
||||
int pthread_mutex_destroy(pthread_mutex_t *mutex) {
|
||||
int rc;
|
||||
if (!mutex->lock && !mutex->waits) {
|
||||
rc = 0;
|
||||
} else {
|
||||
assert(!"dead lock");
|
||||
rc = EDEADLK;
|
||||
if (mutex->lock || mutex->waits) {
|
||||
assert(!"deadlock");
|
||||
return EINVAL;
|
||||
}
|
||||
bzero(mutex, sizeof(*mutex));
|
||||
*mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -21,12 +21,11 @@
|
|||
|
||||
/**
|
||||
* Initializes mutex.
|
||||
* @param attr may be NULL
|
||||
*
|
||||
* @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) {
|
||||
bzero(mutex, sizeof(*mutex));
|
||||
mutex->attr = attr ? attr->attr : PTHREAD_MUTEX_DEFAULT;
|
||||
return 0;
|
||||
return pthread_mutex_init(mutex, attr);
|
||||
}
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/asmflag.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
|
@ -39,10 +39,10 @@ static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int expect,
|
|||
tries++;
|
||||
} else if (IsLinux() || IsOpenbsd()) {
|
||||
atomic_fetch_add(&mutex->waits, 1);
|
||||
_futex_wait(&mutex->lock, expect, &(struct timespec){1});
|
||||
_futex_wait_private(&mutex->lock, expect, &(struct timespec){1});
|
||||
atomic_fetch_sub(&mutex->waits, 1);
|
||||
} else {
|
||||
sched_yield();
|
||||
pthread_yield();
|
||||
}
|
||||
return tries;
|
||||
}
|
||||
|
@ -50,12 +50,48 @@ static int pthread_mutex_lock_spin(pthread_mutex_t *mutex, int expect,
|
|||
/**
|
||||
* Locks mutex.
|
||||
*
|
||||
* _spinlock() l: 181,570c 58,646ns
|
||||
* spin l: 181,570c 58,646ns
|
||||
* mutex normal l: 297,965c 96,241ns
|
||||
* mutex recursive l: 1,112,166c 359,223ns
|
||||
* mutex errorcheck l: 1,449,723c 468,252ns
|
||||
*
|
||||
* Here's an example of using a normal mutex:
|
||||
*
|
||||
* pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
* pthread_mutex_lock(&lock);
|
||||
* // do work...
|
||||
* pthread_mutex_unlock(&lock);
|
||||
* pthread_mutex_destroy(&lock);
|
||||
*
|
||||
* Cosmopolitan permits succinct notation for normal mutexes:
|
||||
*
|
||||
* pthread_mutex_t lock = {0};
|
||||
* pthread_mutex_lock(&lock);
|
||||
* // do work...
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* Here's an example of the proper way to do recursive mutexes:
|
||||
*
|
||||
* pthread_mutex_t lock;
|
||||
* pthread_mutexattr_t attr;
|
||||
* pthread_mutexattr_init(&attr);
|
||||
* pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
|
||||
* pthread_mutex_init(&lock, &attr);
|
||||
* pthread_mutexattr_destroy(&attr);
|
||||
* pthread_mutex_lock(&lock);
|
||||
* // do work...
|
||||
* pthread_mutex_unlock(&lock);
|
||||
* pthread_mutex_destroy(&lock);
|
||||
*
|
||||
* Alternatively, Cosmopolitan lets you do the folllowing instead:
|
||||
*
|
||||
* pthread_mutex_t lock = {PTHREAD_MUTEX_RECURSIVE};
|
||||
* pthread_mutex_lock(&lock);
|
||||
* // do work...
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* @return 0 on success, or error number on failure
|
||||
* @see pthread_spin_lock
|
||||
*/
|
||||
int(pthread_mutex_lock)(pthread_mutex_t *mutex) {
|
||||
int me, owner, tries;
|
||||
|
@ -81,7 +117,7 @@ int(pthread_mutex_lock)(pthread_mutex_t *mutex) {
|
|||
if (mutex->attr != PTHREAD_MUTEX_ERRORCHECK) {
|
||||
break;
|
||||
} else {
|
||||
assert(!"dead lock");
|
||||
assert(!"deadlock");
|
||||
return EDEADLK;
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +126,7 @@ int(pthread_mutex_lock)(pthread_mutex_t *mutex) {
|
|||
++mutex->reent;
|
||||
return 0;
|
||||
default:
|
||||
assert(!"inva lock");
|
||||
assert(!"badlock");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Releases mutex.
|
||||
*
|
||||
* @return 0 on success or error number on failure
|
||||
* @raises EPERM if in error check mode and not owned by caller
|
||||
*/
|
||||
|
@ -35,7 +35,7 @@ int(pthread_mutex_unlock)(pthread_mutex_t *mutex) {
|
|||
me = gettid();
|
||||
owner = atomic_load_explicit(&mutex->lock, memory_order_relaxed);
|
||||
if (owner != me) {
|
||||
assert(!"perm lock");
|
||||
assert(!"permlock");
|
||||
return EPERM;
|
||||
}
|
||||
// fallthrough
|
||||
|
@ -49,7 +49,7 @@ int(pthread_mutex_unlock)(pthread_mutex_t *mutex) {
|
|||
}
|
||||
return 0;
|
||||
default:
|
||||
assert(!"inva lock");
|
||||
assert(!"badlock");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,15 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
int _pthread_mutex_wake(pthread_mutex_t *mutex) {
|
||||
if ((IsLinux() || IsOpenbsd()) &&
|
||||
atomic_load_explicit(&mutex->waits, memory_order_relaxed)) {
|
||||
return _futex_wake(&mutex->lock, 1);
|
||||
return _futex_wake_private(&mutex->lock, 1);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,5 @@
|
|||
* @return 0 on success, or error number on failure
|
||||
*/
|
||||
int(pthread_mutexattr_destroy)(pthread_mutexattr_t *attr) {
|
||||
attr->attr = 0;
|
||||
return 0;
|
||||
return pthread_mutexattr_destroy(attr);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
|
@ -30,6 +29,5 @@
|
|||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_mutexattr_gettype)(const pthread_mutexattr_t *attr, int *type) {
|
||||
*type = attr->attr;
|
||||
return 0;
|
||||
return pthread_mutexattr_gettype(attr, type);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,5 @@
|
|||
* @return 0 on success, or error number on failure
|
||||
*/
|
||||
int(pthread_mutexattr_init)(pthread_mutexattr_t *attr) {
|
||||
attr->attr = PTHREAD_MUTEX_DEFAULT;
|
||||
return 0;
|
||||
return pthread_mutexattr_init(attr);
|
||||
}
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
* @return 0 on success, or error on failure
|
||||
* @raises EINVAL if `type` is invalid
|
||||
*/
|
||||
int(pthread_mutexattr_settype)(pthread_mutexattr_t *attr, int type) {
|
||||
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type) {
|
||||
switch (type) {
|
||||
case PTHREAD_MUTEX_NORMAL:
|
||||
case PTHREAD_MUTEX_RECURSIVE:
|
||||
case PTHREAD_MUTEX_ERRORCHECK:
|
||||
attr->attr = type;
|
||||
*attr = type;
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
|
|
|
@ -16,33 +16,55 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
#define INIT 0
|
||||
#define CALLING 1
|
||||
#define FINISHED 2
|
||||
|
||||
/**
|
||||
* Ensures initialization function is called exactly once, e.g.
|
||||
*
|
||||
* static void *g_factory;
|
||||
*
|
||||
* static void InitFactory(void) {
|
||||
* g_factory = expensive();
|
||||
* }
|
||||
*
|
||||
* void *GetFactory(void) {
|
||||
* static pthread_once_t once = PTHREAD_ONCE_INIT;
|
||||
* pthread_once(&once, InitFactory);
|
||||
* return g_factory;
|
||||
* }
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
int pthread_once(pthread_once_t *once, void init(void)) {
|
||||
int x;
|
||||
unsigned tries;
|
||||
switch ((x = atomic_load(once))) {
|
||||
case 0:
|
||||
if (atomic_compare_exchange_strong(once, &x, 1)) {
|
||||
char old;
|
||||
switch ((old = atomic_load_explicit(once, memory_order_relaxed))) {
|
||||
case INIT:
|
||||
if (atomic_compare_exchange_strong_explicit(once, &old, CALLING,
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
init();
|
||||
atomic_store(once, 2);
|
||||
atomic_store(once, FINISHED);
|
||||
break;
|
||||
}
|
||||
// fallthrough
|
||||
case 1:
|
||||
tries = 0;
|
||||
case CALLING:
|
||||
do {
|
||||
if (++tries & 7) {
|
||||
__builtin_ia32_pause();
|
||||
} else {
|
||||
sched_yield();
|
||||
}
|
||||
} while (atomic_load(once) == 1);
|
||||
pthread_yield();
|
||||
} while (atomic_load_explicit(once, memory_order_relaxed) == CALLING);
|
||||
break;
|
||||
case FINISHED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
assert(!"bad once");
|
||||
return EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
36
libc/intrin/pthread_rwlock_destroy.c
Normal file
36
libc/intrin/pthread_rwlock_destroy.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys read-write lock.
|
||||
*
|
||||
* @return 0 on success, or error number on failure
|
||||
* @raise EINVAL if any threads still hold the lock
|
||||
*/
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) {
|
||||
if (rwlock->lock) {
|
||||
assert(!"deadlock");
|
||||
return EINVAL;
|
||||
}
|
||||
*rwlock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER;
|
||||
return 0;
|
||||
}
|
30
libc/intrin/pthread_rwlock_init.c
Normal file
30
libc/intrin/pthread_rwlock_init.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Initializes read-write lock.
|
||||
*
|
||||
* @param attr may be null
|
||||
* @return 0 on success, or error number on failure
|
||||
*/
|
||||
int(pthread_rwlock_init)(pthread_rwlock_t *rwlock,
|
||||
const pthread_rwlockattr_t *attr) {
|
||||
return pthread_rwlock_init(rwlock, attr);
|
||||
}
|
61
libc/intrin/pthread_rwlock_rdlock.c
Normal file
61
libc/intrin/pthread_rwlock_rdlock.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
static int pthread_rwlock_rdlock_spin(pthread_rwlock_t *rwlock, int expect,
|
||||
int tries) {
|
||||
if (tries < 7) {
|
||||
volatile int i;
|
||||
for (i = 0; i != 1 << tries; i++) {
|
||||
}
|
||||
tries++;
|
||||
} else if (IsLinux() || IsOpenbsd()) {
|
||||
atomic_fetch_add(&rwlock->waits, 1);
|
||||
_futex_wait_private(&rwlock->lock, expect, &(struct timespec){1});
|
||||
atomic_fetch_sub(&rwlock->waits, 1);
|
||||
} else {
|
||||
pthread_yield();
|
||||
}
|
||||
return tries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires read lock on read-write lock.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) {
|
||||
int old, tries;
|
||||
for (tries = 0;;) {
|
||||
old = atomic_load_explicit(&rwlock->lock, memory_order_relaxed);
|
||||
if (old >= 0) {
|
||||
do {
|
||||
if (atomic_compare_exchange_weak_explicit(&rwlock->lock, &old, old + 1,
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
return 0;
|
||||
}
|
||||
} while (old >= 0);
|
||||
}
|
||||
tries = pthread_rwlock_rdlock_spin(rwlock, old, tries);
|
||||
}
|
||||
}
|
60
libc/intrin/pthread_rwlock_unlock.c
Normal file
60
libc/intrin/pthread_rwlock_unlock.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/intrin.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Unlocks read-write lock.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise EINVAL if lock is in a bad state
|
||||
*/
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) {
|
||||
int old, waits;
|
||||
for (;;) {
|
||||
old = atomic_load_explicit(&rwlock->lock, memory_order_relaxed);
|
||||
if (!old || old < -1) {
|
||||
assert(!"badlock");
|
||||
return EINVAL;
|
||||
} else if (old == -1 || old == 1) {
|
||||
waits = atomic_load_explicit(&rwlock->waits, memory_order_relaxed);
|
||||
if (atomic_compare_exchange_weak_explicit(&rwlock->lock, &old, 0,
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
if (waits && (IsLinux() || IsOpenbsd())) {
|
||||
if (rwlock->attr == PTHREAD_PROCESS_SHARED) {
|
||||
_futex_wake_public(&rwlock->lock, 1);
|
||||
} else {
|
||||
_futex_wake_private(&rwlock->lock, 1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} else if (atomic_compare_exchange_weak_explicit(
|
||||
&rwlock->lock, &old, old - 1, memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
60
libc/intrin/pthread_rwlock_wrlock.c
Normal file
60
libc/intrin/pthread_rwlock_wrlock.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
static int pthread_rwlock_wrlock_spin(pthread_rwlock_t *rwlock, int expect,
|
||||
int tries) {
|
||||
if (tries < 7) {
|
||||
volatile int i;
|
||||
for (i = 0; i != 1 << tries; i++) {
|
||||
}
|
||||
tries++;
|
||||
} else if (IsLinux() || IsOpenbsd()) {
|
||||
atomic_fetch_add(&rwlock->waits, 1);
|
||||
_futex_wait_private(&rwlock->lock, expect, &(struct timespec){1});
|
||||
atomic_fetch_sub(&rwlock->waits, 1);
|
||||
} else {
|
||||
pthread_yield();
|
||||
}
|
||||
return tries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires write lock on read-write lock.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) {
|
||||
int old, tries;
|
||||
for (tries = 0;;) {
|
||||
if (!(old = atomic_load_explicit(&rwlock->lock, memory_order_relaxed))) {
|
||||
do {
|
||||
if (atomic_compare_exchange_weak_explicit(&rwlock->lock, &old, -1,
|
||||
memory_order_acquire,
|
||||
memory_order_relaxed)) {
|
||||
return 0;
|
||||
}
|
||||
} while (!old);
|
||||
}
|
||||
tries = pthread_rwlock_wrlock_spin(rwlock, old, tries);
|
||||
}
|
||||
}
|
28
libc/intrin/pthread_rwlockattr_destroy.c
Normal file
28
libc/intrin/pthread_rwlockattr_destroy.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys read-write lock attributes.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_rwlockattr_destroy)(pthread_rwlockattr_t *attr) {
|
||||
return pthread_rwlockattr_destroy(attr);
|
||||
}
|
32
libc/intrin/pthread_rwlockattr_getpshared.c
Normal file
32
libc/intrin/pthread_rwlockattr_getpshared.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Gets read-write lock process sharing.
|
||||
*
|
||||
* @param pshared is set to one of the following
|
||||
* - `PTHREAD_PROCESS_SHARED`
|
||||
* - `PTHREAD_PROCESS_PRIVATE`
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_rwlockattr_getpshared)(const pthread_rwlockattr_t *attr,
|
||||
int *pshared) {
|
||||
return pthread_rwlockattr_getpshared(attr, pshared);
|
||||
}
|
28
libc/intrin/pthread_rwlockattr_init.c
Normal file
28
libc/intrin/pthread_rwlockattr_init.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Initializes read-write lock attributes.
|
||||
*
|
||||
* @return 0 on success, or error on failure
|
||||
*/
|
||||
int(pthread_rwlockattr_init)(pthread_rwlockattr_t *attr) {
|
||||
return pthread_rwlockattr_init(attr);
|
||||
}
|
40
libc/intrin/pthread_rwlockattr_setpshared.c
Normal file
40
libc/intrin/pthread_rwlockattr_setpshared.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Sets read-write lock process sharing.
|
||||
*
|
||||
* @param pshared can be one of
|
||||
* - `PTHREAD_PROCESS_SHARED`
|
||||
* - `PTHREAD_PROCESS_PRIVATE`
|
||||
* @return 0 on success, or error on failure
|
||||
* @raises EINVAL if `pshared` is invalid
|
||||
*/
|
||||
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared) {
|
||||
switch (pshared) {
|
||||
case PTHREAD_PROCESS_SHARED:
|
||||
case PTHREAD_PROCESS_PRIVATE:
|
||||
*attr = pshared;
|
||||
return 0;
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
28
libc/intrin/pthread_spin_destroy.c
Normal file
28
libc/intrin/pthread_spin_destroy.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Destroys spin lock.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
int(pthread_spin_destroy)(pthread_spinlock_t *spin) {
|
||||
return pthread_spin_destroy(spin);
|
||||
}
|
32
libc/intrin/pthread_spin_init.c
Normal file
32
libc/intrin/pthread_spin_init.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.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
|
||||
*/
|
||||
int(pthread_spin_init)(pthread_spinlock_t *spin, int pshared) {
|
||||
return pthread_spin_init(spin, pshared);
|
||||
}
|
60
libc/intrin/pthread_spin_lock.c
Normal file
60
libc/intrin/pthread_spin_lock.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Acquires spin lock.
|
||||
*
|
||||
* spin l: 181,570c 58,646ns
|
||||
* mutex normal l: 297,965c 96,241ns
|
||||
* mutex recursive l: 1,112,166c 359,223ns
|
||||
* mutex errorcheck l: 1,449,723c 468,252ns
|
||||
*
|
||||
* If the lock is already held, this function will wait for it to become
|
||||
* available. No genuine error conditions are currently defined. This is
|
||||
* similar to pthread_mutex_lock() except spin locks are much simpler so
|
||||
* this API is able to offer a performance advantage in situations where
|
||||
* scalable contention handling isn't necessary. Spinlocks are also very
|
||||
* small especially in MODE=tiny where a lock needs 16 bytes of code and
|
||||
* unlocking needs just 5 bytes. The lock object also only takes 1 byte.
|
||||
*
|
||||
* The posixly correct way to use this API is as follows:
|
||||
*
|
||||
* 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);
|
||||
*
|
||||
* Cosmopolitan permits succinct notation for spin locks:
|
||||
*
|
||||
* pthread_spinlock_t lock = 0;
|
||||
* pthread_spin_lock(&lock);
|
||||
* // do work...
|
||||
* pthread_spin_unlock(&lock);
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @see pthread_spin_trylock
|
||||
* @see pthread_spin_unlock
|
||||
* @see pthread_spin_init
|
||||
*/
|
||||
int(pthread_spin_lock)(pthread_spinlock_t *spin) {
|
||||
return pthread_spin_lock(spin);
|
||||
}
|
33
libc/intrin/pthread_spin_trylock.c
Normal file
33
libc/intrin/pthread_spin_trylock.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Acquires spin lock if available.
|
||||
*
|
||||
* Unlike pthread_spin_lock() this function won't block, and instead
|
||||
* returns an error immediately if the spinlock couldn't be acquired
|
||||
* furthermore this function doesn't define any error conditions now
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise EBUSY if lock is already held
|
||||
*/
|
||||
int(pthread_spin_trylock)(pthread_spinlock_t *spin) {
|
||||
return pthread_spin_trylock(spin);
|
||||
}
|
29
libc/intrin/pthread_spin_unlock.c
Normal file
29
libc/intrin/pthread_spin_unlock.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
|
||||
/**
|
||||
* Releases spin lock.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
* @see pthread_spin_lock
|
||||
*/
|
||||
int(pthread_spin_unlock)(pthread_spinlock_t *spin) {
|
||||
return pthread_spin_unlock(spin);
|
||||
}
|
32
libc/intrin/pthread_yield.c
Normal file
32
libc/intrin/pthread_yield.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/calls/calls.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Yields current thread's remaining timeslice to operating system.
|
||||
*
|
||||
* @return 0 on success, or error number on failure
|
||||
*/
|
||||
int pthread_yield(void) {
|
||||
sched_yield();
|
||||
STRACE("pthread_yield()");
|
||||
return 0;
|
||||
}
|
|
@ -22,7 +22,8 @@
|
|||
.privileged
|
||||
|
||||
// Asks kernel to let other threads be scheduled.
|
||||
// @return 0 on success, or non-zero on failure
|
||||
//
|
||||
// @return 0 on success, or -1 w/ errno
|
||||
// @norestart
|
||||
sched_yield:
|
||||
push %rbp
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/* TODO(jart): DELETE */
|
||||
|
||||
#ifdef TINY
|
||||
#define _spinlock(lock) _spinlock_tiny(lock)
|
||||
#else
|
||||
|
|
|
@ -16,11 +16,12 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/intrin/wait0.internal.h"
|
||||
#include "libc/linux/futex.h"
|
||||
|
||||
|
@ -34,16 +35,17 @@
|
|||
void _wait0(const int *ctid) {
|
||||
int x;
|
||||
for (;;) {
|
||||
if (!(x = atomic_load_explicit(ctid, memory_order_acquire))) {
|
||||
if (!(x = atomic_load_explicit(ctid, memory_order_relaxed))) {
|
||||
break;
|
||||
} else if (IsLinux() || IsOpenbsd()) {
|
||||
_futex_wait(ctid, x, &(struct timespec){2});
|
||||
_futex_wait_public(ctid, x, &(struct timespec){2});
|
||||
} else {
|
||||
sched_yield();
|
||||
pthread_yield();
|
||||
}
|
||||
}
|
||||
if (IsOpenbsd()) {
|
||||
// TODO(jart): whyyyy do we need it
|
||||
sched_yield();
|
||||
// TODO(jart): Why do we need it? It's not even perfect.
|
||||
// What's up with all these OpenBSD flakes??
|
||||
pthread_yield();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#ifndef LIBC_ISYSTEM_PTHREAD_H_
|
||||
#define LIBC_ISYSTEM_PTHREAD_H_
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/intrin/pthread2.h"
|
||||
#endif /* LIBC_ISYSTEM_PTHREAD_H_ */
|
||||
|
|
31
libc/thread/posixthread.internal.h
Normal file
31
libc/thread/posixthread.internal.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
enum PosixThreadStatus {
|
||||
kPosixThreadStarted,
|
||||
kPosixThreadDetached,
|
||||
kPosixThreadTerminated,
|
||||
kPosixThreadZombie,
|
||||
};
|
||||
|
||||
struct PosixThread {
|
||||
struct spawn spawn;
|
||||
void *(*start_routine)(void *);
|
||||
void *arg;
|
||||
void *rc;
|
||||
int tid;
|
||||
_Atomic(enum PosixThreadStatus) status;
|
||||
jmp_buf exiter;
|
||||
};
|
||||
|
||||
void pthread_zombies_add(struct PosixThread *);
|
||||
void pthread_zombies_decimate(void);
|
||||
void pthread_zombies_harvest(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_ */
|
98
libc/thread/pthread_cond_timedwait.c
Normal file
98
libc/thread/pthread_cond_timedwait.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/intrin/pthread2.h"
|
||||
|
||||
/**
|
||||
* Waits for condition with optional time limit, e.g.
|
||||
*
|
||||
* struct timespec ts; // one second timeout
|
||||
* ts = _timespec_add(_timespec_mono(), _timespec_frommillis(1000));
|
||||
* if (pthread_cond_timedwait(cond, mutex, &ts) == ETIMEDOUT) {
|
||||
* // handle timeout...
|
||||
* }
|
||||
*
|
||||
* @param mutex needs to be held by thread when calling this function
|
||||
* @param abstime may be null to wait indefinitely and should contain
|
||||
* some arbitrary interval added to a `CLOCK_MONOTONIC` timestamp
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise ETIMEDOUT if `abstime` was specified and the current time
|
||||
* exceeded its value
|
||||
* @raise EPERM if `mutex` is `PTHREAD_MUTEX_ERRORCHECK` and the lock
|
||||
* isn't owned by the current thread
|
||||
* @raise EINVAL if `0 ≤ abstime->tv_nsec < 1000000000` wasn't the case
|
||||
* @see pthread_cond_broadcast
|
||||
* @see pthread_cond_signal
|
||||
*/
|
||||
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
const struct timespec *abstime) {
|
||||
int rc, err, seq;
|
||||
struct timespec now, rel, *tsp;
|
||||
|
||||
if (abstime && !(0 <= abstime->tv_nsec && abstime->tv_nsec < 1000000000)) {
|
||||
assert(!"bad abstime");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if ((err = pthread_mutex_unlock(mutex))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
atomic_fetch_add(&cond->waits, 1);
|
||||
|
||||
rc = 0;
|
||||
seq = atomic_load_explicit(&cond->seq, memory_order_relaxed);
|
||||
do {
|
||||
if (!abstime) {
|
||||
tsp = 0;
|
||||
} else {
|
||||
now = _timespec_mono();
|
||||
if (_timespec_gte(now, *abstime)) {
|
||||
rc = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
rel = _timespec_sub(*abstime, now);
|
||||
tsp = &rel;
|
||||
}
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
if (cond->attr == PTHREAD_PROCESS_SHARED) {
|
||||
_futex_wait_public(&cond->seq, seq, tsp);
|
||||
} else {
|
||||
_futex_wait_private(&cond->seq, seq, tsp);
|
||||
}
|
||||
} else {
|
||||
sched_yield();
|
||||
}
|
||||
} while (seq == atomic_load_explicit(&cond->seq, memory_order_relaxed));
|
||||
|
||||
atomic_fetch_sub(&cond->waits, 1);
|
||||
|
||||
if ((err = pthread_mutex_lock(mutex))) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
47
libc/thread/pthread_cond_wait.c
Normal file
47
libc/thread/pthread_cond_wait.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread2.h"
|
||||
|
||||
/**
|
||||
* Waits for condition, e.g.
|
||||
*
|
||||
* pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
|
||||
* pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
*
|
||||
* // waiting threads
|
||||
* pthread_mutex_lock(&lock);
|
||||
* pthread_cond_wait(&cond, &lock);
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* // notifying thread
|
||||
* pthread_mutex_lock(&lock);
|
||||
* pthread_cond_broadcast(&cond);
|
||||
* pthread_mutex_unlock(&lock);
|
||||
*
|
||||
* @param mutex needs to be held by thread when calling this function
|
||||
* @return 0 on success, or errno on error
|
||||
* @raise EPERM if `mutex` is `PTHREAD_MUTEX_ERRORCHECK` and the lock
|
||||
* isn't owned by the current thread
|
||||
* @see pthread_cond_timedwait
|
||||
* @see pthread_cond_broadcast
|
||||
* @see pthread_cond_signal
|
||||
*/
|
||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) {
|
||||
return pthread_cond_timedwait(cond, mutex, 0);
|
||||
}
|
73
libc/thread/pthread_create.c
Normal file
73
libc/thread/pthread_create.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/intrin/pthread.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/gettls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
static int PosixThread(void *arg, int tid) {
|
||||
struct PosixThread *pt = arg;
|
||||
enum PosixThreadStatus status;
|
||||
pt->tid = tid;
|
||||
if (!setjmp(pt->exiter)) {
|
||||
((cthread_t)__get_tls())->pthread = pt;
|
||||
pt->rc = pt->start_routine(pt->arg);
|
||||
}
|
||||
if (atomic_load_explicit(&pt->status, memory_order_relaxed) ==
|
||||
kPosixThreadDetached) {
|
||||
atomic_store_explicit(&pt->status, kPosixThreadZombie,
|
||||
memory_order_relaxed);
|
||||
} else {
|
||||
atomic_store_explicit(&pt->status, kPosixThreadTerminated,
|
||||
memory_order_relaxed);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates thread.
|
||||
*
|
||||
* @return 0 on success, or errno on error
|
||||
*/
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
void *(*start_routine)(void *), void *arg) {
|
||||
int e, rc;
|
||||
struct PosixThread *pt;
|
||||
e = errno;
|
||||
pthread_zombies_decimate();
|
||||
if ((pt = calloc(1, sizeof(struct PosixThread)))) {
|
||||
pt->start_routine = start_routine;
|
||||
pt->arg = arg;
|
||||
if (!_spawn(PosixThread, pt, &pt->spawn)) {
|
||||
*thread = pt;
|
||||
rc = 0;
|
||||
} else {
|
||||
free(pt);
|
||||
rc = errno;
|
||||
}
|
||||
} else {
|
||||
rc = errno;
|
||||
}
|
||||
errno = e;
|
||||
return rc;
|
||||
}
|
51
libc/thread/pthread_detach.c
Normal file
51
libc/thread/pthread_detach.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
|
||||
/**
|
||||
* Asks POSIX thread to free itself automatically on termination.
|
||||
*
|
||||
* @return 0 on success, or errno with error
|
||||
*/
|
||||
int pthread_detach(pthread_t thread) {
|
||||
enum PosixThreadStatus status;
|
||||
struct PosixThread *pt = thread;
|
||||
for (;;) {
|
||||
status = atomic_load_explicit(&pt->status, memory_order_relaxed);
|
||||
if (status == kPosixThreadDetached || status == kPosixThreadZombie) {
|
||||
break;
|
||||
} else if (status == kPosixThreadTerminated) {
|
||||
_join(&pt->spawn);
|
||||
free(pt);
|
||||
break;
|
||||
} else if (status == kPosixThreadStarted &&
|
||||
atomic_compare_exchange_weak_explicit(
|
||||
&pt->status, &status, kPosixThreadDetached,
|
||||
memory_order_acquire, memory_order_relaxed)) {
|
||||
pthread_zombies_add(pt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
31
libc/thread/pthread_equal.c
Normal file
31
libc/thread/pthread_equal.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
|
||||
/**
|
||||
* Compares thread ids;
|
||||
*
|
||||
* @return nonzero if equal, otherwise zero
|
||||
*/
|
||||
int pthread_equal(pthread_t t1, pthread_t t2) {
|
||||
struct PosixThread *a = t1;
|
||||
struct PosixThread *b = t2;
|
||||
return a->tid == b->tid;
|
||||
}
|
33
libc/thread/pthread_exit.c
Normal file
33
libc/thread/pthread_exit.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
#include "libc/nexgen32e/gettls.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Terminates current POSIX thread.
|
||||
*/
|
||||
void pthread_exit(void *rc) {
|
||||
struct PosixThread *pt;
|
||||
pt = ((cthread_t)__get_tls())->pthread;
|
||||
pt->rc = rc;
|
||||
longjmp(pt->exiter, 1);
|
||||
}
|
27
libc/thread/pthread_getthreadid_np.c
Normal file
27
libc/thread/pthread_getthreadid_np.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/calls/calls.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
|
||||
/**
|
||||
* Returns thread id of current POSIX thread.
|
||||
*/
|
||||
pthread_id_np_t pthread_getthreadid_np(void) {
|
||||
return gettid();
|
||||
}
|
28
libc/thread/pthread_getunique_np.c
Normal file
28
libc/thread/pthread_getunique_np.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/posixthread.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Returns thread id of POSIX thread.
|
||||
*/
|
||||
int64_t pthread_getunique_np(pthread_t thread) {
|
||||
struct PosixThread *pt = thread;
|
||||
return pt->tid;
|
||||
}
|
45
libc/thread/pthread_join.c
Normal file
45
libc/thread/pthread_join.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/pthread.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
|
||||
/**
|
||||
* Waits for thread to terminate.
|
||||
*
|
||||
* @return 0 on success, or errno with error
|
||||
* @raise EDEADLK if thread is detached
|
||||
*/
|
||||
int pthread_join(pthread_t thread, void **value_ptr) {
|
||||
struct PosixThread *pt = thread;
|
||||
if (pt->status == kPosixThreadDetached) {
|
||||
assert(!"badjoin");
|
||||
return EDEADLK;
|
||||
}
|
||||
_join(&pt->spawn);
|
||||
if (value_ptr) {
|
||||
*value_ptr = pt->rc;
|
||||
}
|
||||
free(pt);
|
||||
return 0;
|
||||
}
|
28
libc/thread/pthread_self.c
Normal file
28
libc/thread/pthread_self.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/pthread.h"
|
||||
#include "libc/nexgen32e/gettls.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
/**
|
||||
* Returns current POSIX thread.
|
||||
*/
|
||||
pthread_t pthread_self(void) {
|
||||
return ((cthread_t)__get_tls())->pthread;
|
||||
}
|
|
@ -30,7 +30,7 @@ struct cthread_descriptor_t {
|
|||
struct FtraceTls ftrace; /* 0x08 */
|
||||
void *garbages; /* 0x10 */
|
||||
locale_t locale; /* 0x20 */
|
||||
int64_t __pad2; /* 0x28 */
|
||||
pthread_t pthread; /* 0x28 */
|
||||
struct cthread_descriptor_t *self2; /* 0x30 */
|
||||
int32_t tid; /* 0x38 */
|
||||
int32_t err; /* 0x3c */
|
||||
|
@ -64,8 +64,6 @@ int cthread_sem_wait(cthread_sem_t *, int, const struct timespec *);
|
|||
int cthread_sem_signal(cthread_sem_t *);
|
||||
int cthread_memory_wait32(int *, int, const struct timespec *);
|
||||
int cthread_memory_wake32(int *, int);
|
||||
void cthread_zombies_add(cthread_t);
|
||||
void cthread_zombies_reap(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -16,26 +16,26 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/futex.internal.h"
|
||||
#include "libc/thread/thread.h"
|
||||
|
||||
int cthread_memory_wait32(int* addr, int val, const struct timespec* timeout) {
|
||||
size_t size;
|
||||
if (IsLinux() /* || IsOpenbsd() */) {
|
||||
return _futex_wait(addr, val, timeout);
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
return _futex_wait_public(addr, val, timeout);
|
||||
} else {
|
||||
return sched_yield();
|
||||
}
|
||||
}
|
||||
|
||||
int cthread_memory_wake32(int* addr, int n) {
|
||||
if (IsLinux() /* || IsOpenbsd() */) {
|
||||
return _futex_wake(addr, n);
|
||||
if (IsLinux() || IsOpenbsd()) {
|
||||
return _futex_wake_public(addr, n);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
|
75
libc/thread/zombie.c
Normal file
75
libc/thread/zombie.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net 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/bits/atomic.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Memory collector for detached threads.
|
||||
*/
|
||||
|
||||
static struct Zombie {
|
||||
struct Zombie *next;
|
||||
struct PosixThread *pt;
|
||||
} * pthread_zombies;
|
||||
|
||||
void pthread_zombies_add(struct PosixThread *pt) {
|
||||
struct Zombie *z;
|
||||
if ((z = malloc(sizeof(struct Zombie)))) {
|
||||
z->pt = pt;
|
||||
z->next = atomic_load(&pthread_zombies);
|
||||
for (;;) {
|
||||
if (atomic_compare_exchange_weak(&pthread_zombies, &z->next, z)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pthread_zombies_destroy(struct Zombie *z) {
|
||||
_join(&z->pt->spawn);
|
||||
free(z->pt);
|
||||
free(z);
|
||||
}
|
||||
|
||||
void pthread_zombies_decimate(void) {
|
||||
struct Zombie *z;
|
||||
while ((z = atomic_load(&pthread_zombies)) &&
|
||||
atomic_load(&z->pt->status) == kPosixThreadZombie) {
|
||||
if (atomic_compare_exchange_strong(&pthread_zombies, &z, z->next)) {
|
||||
pthread_zombies_destroy(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pthread_zombies_harvest(void) {
|
||||
struct Zombie *z;
|
||||
while ((z = atomic_load(&pthread_zombies))) {
|
||||
if (atomic_compare_exchange_weak(&pthread_zombies, &z, z->next)) {
|
||||
pthread_zombies_destroy(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__constructor__)) static void init(void) {
|
||||
atexit(pthread_zombies_harvest);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue