Implement swapcontext() and makecontext()

This change introduces support for Linux-style uc_context manipulation
that's fast and works well on all supported OSes and architectures. It
also integrates with the Cosmpolitan runtime which can show backtraces
comprised of multiple stacks and fibers. See the test and example code
for further details. This will be used by Mold once it's been vendored
This commit is contained in:
Justine Tunney 2023-07-02 03:50:29 -07:00
parent 7ec84655b4
commit 197aa0d465
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
28 changed files with 617 additions and 355 deletions

View file

@ -533,7 +533,7 @@ static int CloneLinux(int (*func)(void *arg, int rc), char *stk, size_t stksz,
* int worker(void *arg) { return 0; }
* struct CosmoTib tib = {.tib_self = &tib, .tib_tid = -1};
* atomic_int tid;
* char *stk = _mapstack();
* char *stk = NewCosmoStack();
* clone(worker, stk, GetStackSize() - 16,
* CLONE_VM | CLONE_THREAD | CLONE_FS | CLONE_FILES |
* CLONE_SYSVSEM | CLONE_SIGHAND | CLONE_PARENT_SETTID |
@ -545,7 +545,7 @@ static int CloneLinux(int (*func)(void *arg, int rc), char *stk, size_t stksz,
* // thread is running
* while (atomic_load(&tib.tib_tid) > 0) sched_yield();
* // thread has terminated
* _freestack(stk);
* FreeCosmoStack(stk);
*
* Threads are created in a detached manner. They currently can't be
* synchronized using wait() or posix signals. Threads created by this

View file

@ -32,10 +32,6 @@
#define GUARANTEE_TERMINATOR 1
#define INITIAL_CAPACITY (32 - GUARANTEE_TERMINATOR)
/**
* Grows array.
* @deprecated favor realloc
*/
bool __grow(void *pp, size_t *capacity, size_t itemsize, size_t extra) {
void **p, *p1, *p2;
size_t n1, n2;

View file

@ -39,7 +39,7 @@
*
* @return stack bottom address on success, or null w/ errno
*/
void *_mapstack(void) {
void *NewCosmoStack(void) {
char *p;
if ((p = mmap(0, GetStackSize(), PROT_READ | PROT_WRITE,
MAP_STACK | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) {
@ -56,8 +56,8 @@ void *_mapstack(void) {
/**
* Frees stack.
*
* @param stk was allocated by _mapstack()
* @param stk was allocated by NewCosmoStack()
*/
int _freestack(void *stk) {
int FreeCosmoStack(void *stk) {
return munmap(stk, GetStackSize());
}

View file

@ -120,8 +120,6 @@ long _missingno();
void _weakfree(void *);
void *_mapanon(size_t) attributeallocsize((1)) mallocesque;
void *_mapshared(size_t) attributeallocsize((1)) mallocesque;
void *_mapstack(void) returnsaligned((APE_PAGESIZE)) mallocesque;
int _freestack(void *);
void __oom_hook(size_t);
void _peekall(void);
bool _isheap(void *);

View file

@ -133,6 +133,9 @@ forceinline void CheckLargeStackAllocation(void *p, ssize_t n) {
}
}
void *NewCosmoStack(void) vallocesque;
int FreeCosmoStack(void *) libcesque;
#endif /* COSMO */
COSMOPOLITAN_C_END_
#endif /* GNU ELF */