mirror of
git://git.musl-libc.org/musl
synced 2024-12-17 12:14:42 +00:00
add C11 thread creation and related thread functions
based on patch by Jens Gustedt. the main difficulty here is handling the difference between start function signatures and thread return types for C11 threads versus POSIX threads. pointers to void are assumed to be able to represent faithfully all values of int. the function pointer for the thread start function is cast to an incorrect type for passing through pthread_create, but is cast back to its correct type before calling so that the behavior of the call is well-defined. changes to the existing threads implementation were kept minimal to reduce the risk of regressions, and duplication of code that carries implementation-specific assumptions was avoided for ease and safety of future maintenance.
This commit is contained in:
parent
14397cec2c
commit
23614b0fcb
@ -128,4 +128,6 @@ void __restore_sigs(void *);
|
||||
#define DEFAULT_STACK_SIZE 81920
|
||||
#define DEFAULT_GUARD_SIZE PAGE_SIZE
|
||||
|
||||
#define __ATTRP_C11_THREAD ((void*)(uintptr_t)-1)
|
||||
|
||||
#endif
|
||||
|
@ -119,7 +119,15 @@ static int start(void *p)
|
||||
if (self->unblock_cancel)
|
||||
__syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
|
||||
SIGPT_SET, 0, _NSIG/8);
|
||||
pthread_exit(self->start(self->start_arg));
|
||||
__pthread_exit(self->start(self->start_arg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int start_c11(void *p)
|
||||
{
|
||||
pthread_t self = p;
|
||||
int (*start)(void*) = (int(*)(void*)) self->start;
|
||||
__pthread_exit((void *)(uintptr_t)start(self->start_arg));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -145,7 +153,7 @@ void *__copy_tls(unsigned char *);
|
||||
|
||||
int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
|
||||
{
|
||||
int ret;
|
||||
int ret, c11 = (attrp == __ATTRP_C11_THREAD);
|
||||
size_t size, guard;
|
||||
struct pthread *self, *new;
|
||||
unsigned char *map = 0, *stack = 0, *tsd = 0, *stack_limit;
|
||||
@ -167,7 +175,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
|
||||
self->tsd = (void **)__pthread_tsd_main;
|
||||
libc.threaded = 1;
|
||||
}
|
||||
if (attrp) attr = *attrp;
|
||||
if (attrp && !c11) attr = *attrp;
|
||||
|
||||
__acquire_ptc();
|
||||
|
||||
@ -234,7 +242,7 @@ int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict att
|
||||
new->canary = self->canary;
|
||||
|
||||
a_inc(&libc.threads_minus_1);
|
||||
ret = __clone(start, stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
|
||||
ret = __clone((c11 ? start_c11 : start), stack, flags, new, &new->tid, TP_ADJ(new), &new->tid);
|
||||
|
||||
__release_ptc();
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <threads.h>
|
||||
|
||||
int __pthread_join(pthread_t, void **);
|
||||
|
||||
int __pthread_detach(pthread_t t)
|
||||
static int __pthread_detach(pthread_t t)
|
||||
{
|
||||
/* Cannot detach a thread that's already exiting */
|
||||
if (a_swap(t->exitlock, 1))
|
||||
@ -13,3 +14,4 @@ int __pthread_detach(pthread_t t)
|
||||
}
|
||||
|
||||
weak_alias(__pthread_detach, pthread_detach);
|
||||
weak_alias(__pthread_detach, thrd_detach);
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include <pthread.h>
|
||||
#include <threads.h>
|
||||
#include "libc.h"
|
||||
|
||||
int (pthread_equal)(pthread_t a, pthread_t b)
|
||||
static int __pthread_equal(pthread_t a, pthread_t b)
|
||||
{
|
||||
return a==b;
|
||||
}
|
||||
|
||||
weak_alias(__pthread_equal, pthread_equal);
|
||||
weak_alias(__pthread_equal, thrd_equal);
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <threads.h>
|
||||
#include "libc.h"
|
||||
|
||||
pthread_t pthread_self()
|
||||
static pthread_t __pthread_self_internal()
|
||||
{
|
||||
return __pthread_self();
|
||||
}
|
||||
|
||||
weak_alias(__pthread_self_internal, pthread_self);
|
||||
weak_alias(__pthread_self_internal, thrd_current);
|
||||
|
14
src/thread/thrd_create.c
Normal file
14
src/thread/thrd_create.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <threads.h>
|
||||
|
||||
int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict);
|
||||
|
||||
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
|
||||
{
|
||||
int ret = __pthread_create(thr, __ATTRP_C11_THREAD, (void *(*)(void *))func, arg);
|
||||
switch (ret) {
|
||||
case 0: return thrd_success;
|
||||
case EAGAIN: return thrd_nomem;
|
||||
default: return thrd_error;
|
||||
}
|
||||
}
|
9
src/thread/thrd_exit.c
Normal file
9
src/thread/thrd_exit.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "pthread_impl.h"
|
||||
#include <threads.h>
|
||||
|
||||
_Noreturn void __pthread_exit(void *);
|
||||
|
||||
_Noreturn void thrd_exit(int result)
|
||||
{
|
||||
__pthread_exit((void*)(intptr_t)result);
|
||||
}
|
12
src/thread/thrd_join.c
Normal file
12
src/thread/thrd_join.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdint.h>
|
||||
#include <threads.h>
|
||||
|
||||
int __pthread_join(thrd_t, void**);
|
||||
|
||||
int thrd_join(thrd_t t, int *res)
|
||||
{
|
||||
void *pthread_res;
|
||||
__pthread_join(t, &pthread_res);
|
||||
if (res) *res = (int)(intptr_t)pthread_res;
|
||||
return thrd_success;
|
||||
}
|
13
src/thread/thrd_sleep.c
Normal file
13
src/thread/thrd_sleep.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include <threads.h>
|
||||
#include <errno.h>
|
||||
#include "syscall.h"
|
||||
|
||||
int thrd_sleep(const struct timespec *req, struct timespec *rem)
|
||||
{
|
||||
int ret = __syscall(SYS_nanosleep, req, rem);
|
||||
switch (ret) {
|
||||
case 0: return 0;
|
||||
case -EINTR: return -1; /* value specified by C11 */
|
||||
default: return -2;
|
||||
}
|
||||
}
|
7
src/thread/thrd_yield.c
Normal file
7
src/thread/thrd_yield.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include <threads.h>
|
||||
#include "syscall.h"
|
||||
|
||||
void thrd_yield()
|
||||
{
|
||||
__syscall(SYS_sched_yield);
|
||||
}
|
Loading…
Reference in New Issue
Block a user