mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-21 09:02:17 +00:00
Reduce pthread memory usage
This commit is contained in:
parent
ec2db4e40e
commit
93e22c581f
6 changed files with 75 additions and 58 deletions
|
@ -94,7 +94,7 @@ struct PosixThread {
|
|||
typedef void (*atfork_f)(void);
|
||||
|
||||
extern struct Dll *_pthread_list;
|
||||
extern _Atomic(unsigned) _pthread_count;
|
||||
extern atomic_uint _pthread_count;
|
||||
extern struct PosixThread _pthread_static;
|
||||
extern _Atomic(pthread_key_dtor) _pthread_key_dtor[PTHREAD_KEYS_MAX];
|
||||
|
||||
|
@ -109,6 +109,7 @@ int _pthread_tid(struct PosixThread *) libcesque;
|
|||
intptr_t _pthread_syshand(struct PosixThread *) libcesque;
|
||||
long _pthread_cancel_ack(void) libcesque;
|
||||
void _pthread_decimate(void) libcesque;
|
||||
void _pthread_free(struct PosixThread *) libcesque paramsnonnull();
|
||||
void _pthread_lock(void) libcesque;
|
||||
void _pthread_onfork_child(void) libcesque;
|
||||
void _pthread_onfork_parent(void) libcesque;
|
||||
|
|
|
@ -67,7 +67,7 @@ __static_yoink("_pthread_onfork_prepare");
|
|||
__static_yoink("_pthread_onfork_parent");
|
||||
__static_yoink("_pthread_onfork_child");
|
||||
|
||||
static void _pthread_free(struct PosixThread *pt) {
|
||||
void _pthread_free(struct PosixThread *pt) {
|
||||
|
||||
// thread must be removed from _pthread_list before calling
|
||||
unassert(dll_is_alone(&pt->list) && &pt->list != _pthread_list);
|
||||
|
@ -84,7 +84,7 @@ static void _pthread_free(struct PosixThread *pt) {
|
|||
// free any additional upstream system resources
|
||||
// our fork implementation wipes this handle in child automatically
|
||||
uint64_t syshand =
|
||||
atomic_load_explicit(&pt->tib->tib_syshand, memory_order_acquire);
|
||||
atomic_load_explicit(&pt->tib->tib_syshand, memory_order_relaxed);
|
||||
if (syshand) {
|
||||
if (IsWindows())
|
||||
unassert(CloseHandle(syshand)); // non-inheritable
|
||||
|
|
|
@ -62,33 +62,34 @@ static const char *DescribeReturnValue(char buf[30], int err, void **value) {
|
|||
* @cancelationpoint
|
||||
*/
|
||||
static errno_t _pthread_wait(atomic_int *ctid, struct timespec *abstime) {
|
||||
int x, e;
|
||||
errno_t err = 0;
|
||||
if (ctid == &__get_tls()->tib_tid) {
|
||||
// "If an implementation detects that the value specified by the
|
||||
// thread argument to pthread_join() refers to the calling thread,
|
||||
// it is recommended that the function should fail and report an
|
||||
// [EDEADLK] error." ──Quoth POSIX.1-2017
|
||||
err = EDEADLK;
|
||||
} else {
|
||||
// "If the thread calling pthread_join() is canceled, then the target
|
||||
// thread shall not be detached." ──Quoth POSIX.1-2017
|
||||
if (!(err = pthread_testcancel_np())) {
|
||||
BEGIN_CANCELATION_POINT;
|
||||
while ((x = atomic_load_explicit(ctid, memory_order_acquire))) {
|
||||
e = cosmo_futex_wait(ctid, x, !IsWindows() && !IsXnu(), CLOCK_REALTIME,
|
||||
|
||||
// "If an implementation detects that the value specified by the
|
||||
// thread argument to pthread_join() refers to the calling thread,
|
||||
// it is recommended that the function should fail and report an
|
||||
// [EDEADLK] error." ──Quoth POSIX.1-2017
|
||||
if (ctid == &__get_tls()->tib_tid)
|
||||
return EDEADLK;
|
||||
|
||||
// "If the thread calling pthread_join() is canceled, then the target
|
||||
// thread shall not be detached." ──Quoth POSIX.1-2017
|
||||
errno_t err;
|
||||
if ((err = pthread_testcancel_np()))
|
||||
return err;
|
||||
|
||||
BEGIN_CANCELATION_POINT;
|
||||
int x;
|
||||
while ((x = atomic_load_explicit(ctid, memory_order_acquire))) {
|
||||
int e = cosmo_futex_wait(ctid, x, !IsWindows() && !IsXnu(), CLOCK_REALTIME,
|
||||
abstime);
|
||||
if (e == -ECANCELED) {
|
||||
err = ECANCELED;
|
||||
break;
|
||||
} else if (e == -ETIMEDOUT) {
|
||||
err = EBUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
END_CANCELATION_POINT;
|
||||
if (e == -ECANCELED) {
|
||||
err = ECANCELED;
|
||||
break;
|
||||
} else if (e == -ETIMEDOUT) {
|
||||
err = EBUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
END_CANCELATION_POINT;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -117,12 +118,11 @@ static errno_t _pthread_wait(atomic_int *ctid, struct timespec *abstime) {
|
|||
errno_t pthread_timedjoin_np(pthread_t thread, void **value_ptr,
|
||||
struct timespec *abstime) {
|
||||
int tid;
|
||||
errno_t err = 0;
|
||||
errno_t err;
|
||||
struct PosixThread *pt;
|
||||
enum PosixThreadStatus status;
|
||||
pt = (struct PosixThread *)thread;
|
||||
unassert(thread);
|
||||
_pthread_ref(pt);
|
||||
|
||||
// "The behavior is undefined if the value specified by the thread
|
||||
// argument to pthread_join() does not refer to a joinable thread."
|
||||
|
@ -135,14 +135,23 @@ errno_t pthread_timedjoin_np(pthread_t thread, void **value_ptr,
|
|||
// specifying the same target thread are undefined."
|
||||
// ──Quoth POSIX.1-2017
|
||||
if (!(err = _pthread_wait(&pt->tib->tib_tid, abstime))) {
|
||||
atomic_store_explicit(&pt->pt_status, kPosixThreadZombie,
|
||||
memory_order_release);
|
||||
_pthread_zombify(pt);
|
||||
if (value_ptr)
|
||||
*value_ptr = pt->pt_val;
|
||||
if (atomic_load_explicit(&pt->pt_refs, memory_order_acquire)) {
|
||||
_pthread_lock();
|
||||
dll_remove(&_pthread_list, &pt->list);
|
||||
dll_make_last(&_pthread_list, &pt->list);
|
||||
atomic_store_explicit(&pt->pt_status, kPosixThreadZombie,
|
||||
memory_order_release);
|
||||
_pthread_unlock();
|
||||
} else {
|
||||
_pthread_lock();
|
||||
dll_remove(&_pthread_list, &pt->list);
|
||||
_pthread_unlock();
|
||||
_pthread_free(pt);
|
||||
}
|
||||
}
|
||||
|
||||
_pthread_unref(pt);
|
||||
STRACE("pthread_timedjoin_np(%d, %s, %s) → %s", tid,
|
||||
DescribeReturnValue(alloca(30), err, value_ptr),
|
||||
DescribeTimespec(err ? -1 : 0, abstime), DescribeErrno(err));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue