mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
a4b455185b
Renaming gc() to _gc() was a mistake since the better thing to do is put it behind the _COSMO_SOURCE macro. We need this change because I haven't wanted to use my amazing garbage collector ever since we renamed it. You now need to define _COSMO_SOURCE yourself when using amalgamation header and cosmocc users need to pass the -mcosmo flag to get the gc() function Some other issues relating to cancelation have been fixed along the way. We're also now putting cosmocc in a folder named `.cosmocc` so it can be more safely excluded by grep --exclude-dir=.cosmocc --exclude-dir=o etc.
128 lines
4.4 KiB
C
128 lines
4.4 KiB
C
#ifndef COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_
|
|
#define COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_
|
|
#include "libc/calls/struct/sched_param.h"
|
|
#include "libc/calls/struct/sigaltstack.h"
|
|
#include "libc/intrin/atomic.h"
|
|
#include "libc/intrin/dll.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/thread/pt.internal.h"
|
|
#include "libc/thread/thread.h"
|
|
#include "libc/thread/tls.h"
|
|
|
|
#define PT_BLOCKER_SEM ((atomic_int *)-1)
|
|
#define PT_BLOCKER_IO ((atomic_int *)-2)
|
|
|
|
COSMOPOLITAN_C_START_
|
|
|
|
// LEGAL TRANSITIONS ┌──> TERMINATED ─┐
|
|
// pthread_create ─┬─> JOINABLE ─┴┬─> DETACHED ───┴─> ZOMBIE
|
|
// └──────────────┘
|
|
enum PosixThreadStatus {
|
|
|
|
// this is a running thread that needs pthread_join()
|
|
//
|
|
// the following transitions are possible:
|
|
//
|
|
// - kPosixThreadJoinable -> kPosixThreadTerminated if start_routine()
|
|
// returns, or is longjmp'd out of by pthread_exit(), and the thread
|
|
// is waiting to be joined.
|
|
//
|
|
// - kPosixThreadJoinable -> kPosixThreadDetached if pthread_detach()
|
|
// is called on this thread.
|
|
//
|
|
// - kPosixThreadJoinable -> kPosixThreadZombie if another thread
|
|
// calls fork().
|
|
kPosixThreadJoinable,
|
|
|
|
// this is a managed thread that'll be cleaned up by the library.
|
|
//
|
|
// the following transitions are possible:
|
|
//
|
|
// - kPosixThreadDetached -> kPosixThreadZombie if start_routine()
|
|
// returns, or is longjmp'd out of by pthread_exit(), and the thread
|
|
// is waiting to be joined.
|
|
//
|
|
// - kPosixThreadDetached -> kPosixThreadZombie if another thread
|
|
// calls fork().
|
|
kPosixThreadDetached,
|
|
|
|
// this is a joinable thread that terminated.
|
|
//
|
|
// the following transitions are possible:
|
|
//
|
|
// - kPosixThreadTerminated -> _pthread_free() will happen when
|
|
// pthread_join() is called by the user.
|
|
// - kPosixThreadTerminated -> kPosixThreadZombie will happen when
|
|
// pthread_detach() is called by the user.
|
|
// - kPosixThreadTerminated -> kPosixThreadZombie if another thread
|
|
// calls fork().
|
|
kPosixThreadTerminated,
|
|
|
|
// this is a detached thread that terminated.
|
|
//
|
|
// the following transitions are possible:
|
|
//
|
|
// - kPosixThreadZombie -> _pthread_free() will happen whenever
|
|
// convenient, e.g. pthread_create() entry or atexit handler.
|
|
kPosixThreadZombie,
|
|
};
|
|
|
|
#define POSIXTHREAD_CONTAINER(e) DLL_CONTAINER(struct PosixThread, list, e)
|
|
|
|
struct PosixThread {
|
|
int pt_flags; // 0x00: see PT_* constants
|
|
atomic_int pt_canceled; // 0x04: thread has bad beliefs
|
|
_Atomic(enum PosixThreadStatus) pt_status;
|
|
atomic_int ptid; // transitions 0 → tid
|
|
atomic_int pt_refs; // negative means free
|
|
void *(*pt_start)(void *); // creation callback
|
|
void *pt_arg; // start's parameter
|
|
void *pt_rc; // start's return value
|
|
char *pt_tls; // bottom of tls allocation
|
|
struct CosmoTib *tib; // middle of tls allocation
|
|
struct Dll list; // list of threads
|
|
struct _pthread_cleanup_buffer *pt_cleanup;
|
|
_Atomic(atomic_int *) pt_blocker;
|
|
uint64_t pt_blkmask;
|
|
int64_t pt_semaphore;
|
|
intptr_t pt_iohandle;
|
|
void *pt_ioverlap;
|
|
jmp_buf pt_exiter;
|
|
pthread_attr_t pt_attr;
|
|
};
|
|
|
|
typedef void (*atfork_f)(void);
|
|
|
|
extern struct Dll *_pthread_list;
|
|
extern struct PosixThread _pthread_static;
|
|
extern _Atomic(pthread_key_dtor) _pthread_key_dtor[PTHREAD_KEYS_MAX];
|
|
|
|
int _pthread_atfork(atfork_f, atfork_f, atfork_f);
|
|
int _pthread_reschedule(struct PosixThread *);
|
|
int _pthread_setschedparam_freebsd(int, int, const struct sched_param *);
|
|
int _pthread_tid(struct PosixThread *);
|
|
intptr_t _pthread_syshand(struct PosixThread *);
|
|
long _pthread_cancel_ack(void);
|
|
void _pthread_decimate(void);
|
|
void _pthread_free(struct PosixThread *, bool);
|
|
void _pthread_lock(void);
|
|
void _pthread_onfork_child(void);
|
|
void _pthread_onfork_parent(void);
|
|
void _pthread_onfork_prepare(void);
|
|
void _pthread_ungarbage(void);
|
|
void _pthread_unkey(struct CosmoTib *);
|
|
void _pthread_unlock(void);
|
|
void _pthread_unref(struct PosixThread *);
|
|
void _pthread_unwind(struct PosixThread *);
|
|
void _pthread_zombify(struct PosixThread *);
|
|
|
|
forceinline pureconst struct PosixThread *_pthread_self(void) {
|
|
return (struct PosixThread *)__get_tls()->tib_pthread;
|
|
}
|
|
|
|
forceinline void _pthread_ref(struct PosixThread *pt) {
|
|
atomic_fetch_add_explicit(&pt->pt_refs, 1, memory_order_relaxed);
|
|
}
|
|
|
|
COSMOPOLITAN_C_END_
|
|
#endif /* COSMOPOLITAN_LIBC_THREAD_POSIXTHREAD_INTERNAL_H_ */
|