forked from Bananymous/banan-os
LibC: Cleanup pthread code and add some pthread_attr functions
errno, pthread cleanup and pthread id are now stored in uthread. This allows using these without TLS
This commit is contained in:
parent
423386a052
commit
c957f1ddca
|
@ -350,6 +350,9 @@ namespace Kernel
|
||||||
.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size),
|
.self = reinterpret_cast<struct uthread*>(region->vaddr() + master_size),
|
||||||
.master_tls_addr = reinterpret_cast<void*>(master_addr),
|
.master_tls_addr = reinterpret_cast<void*>(master_addr),
|
||||||
.master_tls_size = master_size,
|
.master_tls_size = master_size,
|
||||||
|
.cleanup_stack = nullptr,
|
||||||
|
.id = -1,
|
||||||
|
.errno_ = 0,
|
||||||
};
|
};
|
||||||
const uintptr_t dtv[2] { 1, region->vaddr() };
|
const uintptr_t dtv[2] { 1, region->vaddr() };
|
||||||
|
|
||||||
|
@ -2468,11 +2471,7 @@ namespace Kernel
|
||||||
if (attr)
|
if (attr)
|
||||||
{
|
{
|
||||||
TRY(validate_pointer_access(attr, sizeof(*attr), false));
|
TRY(validate_pointer_access(attr, sizeof(*attr), false));
|
||||||
if (*attr)
|
dwarnln("TODO: ignoring thread attr");
|
||||||
{
|
|
||||||
dwarnln("pthread attr not supported");
|
|
||||||
return BAN::Error::from_errno(ENOTSUP);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LockGuard _(m_process_lock);
|
LockGuard _(m_process_lock);
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#if __disable_thread_local_storage
|
extern uthread* _get_uthread();
|
||||||
static int s_errno = 0;
|
|
||||||
#else
|
|
||||||
static thread_local int s_errno = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int* __errno_location()
|
int* __errno_location()
|
||||||
{
|
{
|
||||||
return &s_errno;
|
return &_get_uthread()->errno_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,12 @@ __BEGIN_DECLS
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define __need_off_t
|
#define __need_off_t
|
||||||
#define __need_pthread_attr_t
|
|
||||||
#define __need_size_t
|
#define __need_size_t
|
||||||
#define __need_ssize_t
|
#define __need_ssize_t
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <bits/types/pthread_attr_t.h>
|
||||||
|
|
||||||
struct aiocb
|
struct aiocb
|
||||||
{
|
{
|
||||||
int aio_fildes; /* File descriptor. */
|
int aio_fildes; /* File descriptor. */
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html
|
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
|
||||||
|
|
||||||
#if !defined(__pthread_attr_t_defined) && (defined(__need_all_types) || defined(__need_pthread_attr_t) || defined(__need_pthread_types))
|
|
||||||
#define __pthread_attr_t_defined 1
|
|
||||||
typedef int pthread_attr_t;
|
|
||||||
#endif
|
|
||||||
#undef __need_pthread_attr_t
|
|
||||||
|
|
||||||
#if !defined(__pthread_t_defined) && (defined(__need_all_types) || defined(__need_pthread_t) || defined(__need_pthread_types))
|
|
||||||
#define __pthread_t_defined 1
|
|
||||||
typedef pid_t pthread_t;
|
|
||||||
#endif
|
|
||||||
#undef __need_pthread_t
|
|
||||||
|
|
||||||
#if !defined(__pthread_types_defined) && (defined(__need_all_types) || defined(__need_pthread_types))
|
|
||||||
#define __pthread_types_defined 1
|
|
||||||
|
|
||||||
typedef int pthread_once_t;
|
|
||||||
|
|
||||||
typedef unsigned pthread_key_t;
|
|
||||||
|
|
||||||
typedef pthread_t pthread_spinlock_t;
|
|
||||||
|
|
||||||
typedef struct { int type; int shared; } pthread_mutexattr_t;
|
|
||||||
typedef struct { pthread_mutexattr_t attr; pthread_t locker; unsigned lock_depth; } pthread_mutex_t;
|
|
||||||
|
|
||||||
typedef struct { int shared; } pthread_barrierattr_t;
|
|
||||||
typedef struct { pthread_barrierattr_t attr; unsigned target; unsigned waiting; } pthread_barrier_t;
|
|
||||||
|
|
||||||
typedef struct { int clock; int shared; } pthread_condattr_t;
|
|
||||||
struct _pthread_cond_block { struct _pthread_cond_block* next; int signaled; };
|
|
||||||
typedef struct { pthread_condattr_t attr; pthread_spinlock_t lock; struct _pthread_cond_block* block_list; } pthread_cond_t;
|
|
||||||
|
|
||||||
typedef struct { int shared; } pthread_rwlockattr_t;
|
|
||||||
typedef struct { pthread_rwlockattr_t attr; unsigned lockers; unsigned writers; } pthread_rwlock_t;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#undef __need_pthread_types
|
|
||||||
|
|
||||||
__END_DECLS
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _BITS_LOCALE_T_H
|
#ifndef _BITS_TYPES_LOCALE_T_H
|
||||||
#define _BITS_LOCALE_T_H 1
|
#define _BITS_TYPES_LOCALE_T_H 1
|
||||||
|
|
||||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html
|
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef _BITS_TYPES_PTHREAD_ATTR_T_H
|
||||||
|
#define _BITS_TYPES_PTHREAD_ATTR_T_H 1
|
||||||
|
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <bits/types/sched_param.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int inheritsched;
|
||||||
|
struct sched_param schedparam;
|
||||||
|
int schedpolicy;
|
||||||
|
int detachstate;
|
||||||
|
int scope;
|
||||||
|
size_t stacksize;
|
||||||
|
size_t guardsize;
|
||||||
|
} pthread_attr_t;
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _BITS_TYPES_PTHREAD_T_H
|
||||||
|
#define _BITS_TYPES_PTHREAD_T_H 1
|
||||||
|
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define __need_pid_t
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
typedef pid_t pthread_t;
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,72 @@
|
||||||
|
#ifndef _BITS_TYPES_PTHREAD_TYPES_H
|
||||||
|
#define _BITS_TYPES_PTHREAD_TYPES_H 1
|
||||||
|
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/pthread.h.html
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <bits/types/pthread_attr_t.h>
|
||||||
|
#include <bits/types/pthread_t.h>
|
||||||
|
|
||||||
|
typedef int pthread_once_t;
|
||||||
|
|
||||||
|
typedef unsigned pthread_key_t;
|
||||||
|
|
||||||
|
typedef pthread_t pthread_spinlock_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int type;
|
||||||
|
int shared;
|
||||||
|
} pthread_mutexattr_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_mutexattr_t attr;
|
||||||
|
pthread_t locker;
|
||||||
|
unsigned lock_depth;
|
||||||
|
} pthread_mutex_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int shared;
|
||||||
|
} pthread_barrierattr_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_barrierattr_t attr;
|
||||||
|
unsigned target;
|
||||||
|
unsigned waiting;
|
||||||
|
} pthread_barrier_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int clock;
|
||||||
|
int shared;
|
||||||
|
} pthread_condattr_t;
|
||||||
|
struct _pthread_cond_block
|
||||||
|
{
|
||||||
|
struct _pthread_cond_block* next;
|
||||||
|
int signaled;
|
||||||
|
};
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_condattr_t attr;
|
||||||
|
pthread_spinlock_t lock;
|
||||||
|
struct _pthread_cond_block* block_list;
|
||||||
|
} pthread_cond_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int shared;
|
||||||
|
} pthread_rwlockattr_t;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
pthread_rwlockattr_t attr;
|
||||||
|
unsigned lockers;
|
||||||
|
unsigned writers;
|
||||||
|
} pthread_rwlock_t;
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef _BITS_TYPES_SCHED_PARAM_H
|
||||||
|
#define _BITS_TYPES_SCHED_PARAM_H 1
|
||||||
|
|
||||||
|
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sched.h.html
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
struct sched_param
|
||||||
|
{
|
||||||
|
int sched_priority; /* Process or thread execution scheduling priority. */
|
||||||
|
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
|
||||||
|
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
|
||||||
|
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
|
||||||
|
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
|
||||||
|
};
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _BITS_TIMEVAL_H
|
#ifndef _BITS_TYPES_TIMEVAL_H
|
||||||
#define _BITS_TIMEVAL_H 1
|
#define _BITS_TYPES_TIMEVAL_H 1
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,12 @@ __BEGIN_DECLS
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define __need_pthread_attr_t
|
|
||||||
#define __need_size_t
|
#define __need_size_t
|
||||||
#define __need_ssize_t
|
#define __need_ssize_t
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <bits/types/pthread_attr_t.h>
|
||||||
|
|
||||||
typedef int mqd_t;
|
typedef int mqd_t;
|
||||||
|
|
||||||
struct mq_attr
|
struct mq_attr
|
||||||
|
|
|
@ -13,29 +13,45 @@ __BEGIN_DECLS
|
||||||
|
|
||||||
#define __need_size_t
|
#define __need_size_t
|
||||||
#define __need_clockid_t
|
#define __need_clockid_t
|
||||||
#define __need_pthread_types
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <bits/types/pthread_types.h>
|
||||||
|
|
||||||
|
struct _pthread_cleanup_t
|
||||||
|
{
|
||||||
|
void (*routine)(void*);
|
||||||
|
void* arg;
|
||||||
|
struct _pthread_cleanup_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
struct uthread
|
struct uthread
|
||||||
{
|
{
|
||||||
struct uthread* self;
|
struct uthread* self;
|
||||||
void* master_tls_addr;
|
void* master_tls_addr;
|
||||||
size_t master_tls_size;
|
size_t master_tls_size;
|
||||||
|
struct _pthread_cleanup_t* cleanup_stack;
|
||||||
|
pthread_t id;
|
||||||
|
int errno_;
|
||||||
uintptr_t dtv[];
|
uintptr_t dtv[];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PTHREAD_CANCEL_ASYNCHRONOUS 2
|
#define PTHREAD_CANCELED 1
|
||||||
#define PTHREAD_CANCEL_ENABLE 3
|
|
||||||
#define PTHREAD_CANCEL_DEFERRED 4
|
#define PTHREAD_CANCEL_ASYNCHRONOUS 1
|
||||||
#define PTHREAD_CANCEL_DISABLE 5
|
#define PTHREAD_CANCEL_DEFERRED 0
|
||||||
#define PTHREAD_CANCELED 6
|
|
||||||
#define PTHREAD_EXPLICIT_SCHED 9
|
#define PTHREAD_CANCEL_DISABLE 0
|
||||||
#define PTHREAD_INHERIT_SCHED 10
|
#define PTHREAD_CANCEL_ENABLE 1
|
||||||
#define PTHREAD_PRIO_INHERIT 18
|
|
||||||
#define PTHREAD_PRIO_NONE 19
|
#define PTHREAD_PRIO_INHERIT 1
|
||||||
#define PTHREAD_PRIO_PROTECT 20
|
#define PTHREAD_PRIO_NONE 0
|
||||||
#define PTHREAD_SCOPE_PROCESS 23
|
#define PTHREAD_PRIO_PROTECT 2
|
||||||
#define PTHREAD_SCOPE_SYSTEM 24
|
|
||||||
|
#define PTHREAD_EXPLICIT_SCHED 1
|
||||||
|
#define PTHREAD_INHERIT_SCHED 0
|
||||||
|
|
||||||
|
#define PTHREAD_SCOPE_PROCESS 1
|
||||||
|
#define PTHREAD_SCOPE_SYSTEM 0
|
||||||
|
|
||||||
#define PTHREAD_CREATE_DETACHED 1
|
#define PTHREAD_CREATE_DETACHED 1
|
||||||
#define PTHREAD_CREATE_JOINABLE 0
|
#define PTHREAD_CREATE_JOINABLE 0
|
||||||
|
|
|
@ -12,14 +12,7 @@ __BEGIN_DECLS
|
||||||
#define __need_pid_t
|
#define __need_pid_t
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
struct sched_param
|
#include <bits/types/sched_param.h>
|
||||||
{
|
|
||||||
int sched_priority; /* Process or thread execution scheduling priority. */
|
|
||||||
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
|
|
||||||
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
|
|
||||||
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
|
|
||||||
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SCHED_FIFO 1
|
#define SCHED_FIFO 1
|
||||||
#define SCHED_RR 2
|
#define SCHED_RR 2
|
||||||
|
|
|
@ -14,13 +14,14 @@ __BEGIN_DECLS
|
||||||
#define SIG_HOLD ((void (*)(int))2)
|
#define SIG_HOLD ((void (*)(int))2)
|
||||||
#define SIG_IGN ((void (*)(int))3)
|
#define SIG_IGN ((void (*)(int))3)
|
||||||
|
|
||||||
#define __need_pthread_t
|
|
||||||
#define __need_size_t
|
#define __need_size_t
|
||||||
#define __need_uid_t
|
#define __need_uid_t
|
||||||
#define __need_pid_t
|
#define __need_pid_t
|
||||||
#define __need_pthread_attr_t
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <bits/types/pthread_attr_t.h>
|
||||||
|
#include <bits/types/pthread_t.h>
|
||||||
|
|
||||||
typedef int sig_atomic_t;
|
typedef int sig_atomic_t;
|
||||||
typedef unsigned long long sigset_t;
|
typedef unsigned long long sigset_t;
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,6 @@ __BEGIN_DECLS
|
||||||
&& !defined(__need_nlink_t) \
|
&& !defined(__need_nlink_t) \
|
||||||
&& !defined(__need_off_t) \
|
&& !defined(__need_off_t) \
|
||||||
&& !defined(__need_pid_t) \
|
&& !defined(__need_pid_t) \
|
||||||
&& !defined(__need_pthread_attr_t) \
|
|
||||||
&& !defined(__need_pthread_t) \
|
|
||||||
&& !defined(__need_pthread_types) \
|
|
||||||
&& !defined(__need_size_t) \
|
&& !defined(__need_size_t) \
|
||||||
&& !defined(__need_ssize_t) \
|
&& !defined(__need_ssize_t) \
|
||||||
&& !defined(__need_suseconds_t) \
|
&& !defined(__need_suseconds_t) \
|
||||||
|
@ -122,18 +119,12 @@ __BEGIN_DECLS
|
||||||
#endif
|
#endif
|
||||||
#undef __need_off_t
|
#undef __need_off_t
|
||||||
|
|
||||||
#ifdef __need_pthread_t
|
|
||||||
#define __need_pid_t
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__pid_t_defined) && (defined(__need_all_types) || defined(__need_pid_t))
|
#if !defined(__pid_t_defined) && (defined(__need_all_types) || defined(__need_pid_t))
|
||||||
#define __pid_t_defined 1
|
#define __pid_t_defined 1
|
||||||
typedef int pid_t;
|
typedef int pid_t;
|
||||||
#endif
|
#endif
|
||||||
#undef __need_pid_t
|
#undef __need_pid_t
|
||||||
|
|
||||||
#include <bits/pthread_types.h>
|
|
||||||
|
|
||||||
#if !defined(__size_t_defined) && (defined(__need_all_types) || defined(__need_size_t))
|
#if !defined(__size_t_defined) && (defined(__need_all_types) || defined(__need_size_t))
|
||||||
#define __size_t_defined 1
|
#define __size_t_defined 1
|
||||||
#define __need_size_t
|
#define __need_size_t
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <BAN/PlacementNew.h>
|
#include <BAN/PlacementNew.h>
|
||||||
|
|
||||||
#include <kernel/Arch.h>
|
#include <kernel/Arch.h>
|
||||||
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
@ -46,13 +47,16 @@ asm(
|
||||||
extern "C" void _pthread_trampoline_cpp(void* arg)
|
extern "C" void _pthread_trampoline_cpp(void* arg)
|
||||||
{
|
{
|
||||||
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
|
auto info = *reinterpret_cast<pthread_trampoline_info_t*>(arg);
|
||||||
|
info.uthread->id = syscall(SYS_PTHREAD_SELF);
|
||||||
|
info.uthread->errno_ = 0;
|
||||||
|
info.uthread->cleanup_stack = nullptr;
|
||||||
syscall(SYS_SET_TLS, info.uthread);
|
syscall(SYS_SET_TLS, info.uthread);
|
||||||
free(arg);
|
free(arg);
|
||||||
pthread_exit(info.start_routine(info.arg));
|
pthread_exit(info.start_routine(info.arg));
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
static uthread* get_uthread()
|
uthread* _get_uthread()
|
||||||
{
|
{
|
||||||
uthread* result;
|
uthread* result;
|
||||||
#if ARCH(x86_64)
|
#if ARCH(x86_64)
|
||||||
|
@ -75,22 +79,13 @@ static void free_uthread(uthread* uthread)
|
||||||
munmap(tls_addr, tls_size);
|
munmap(tls_addr, tls_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if not __disable_thread_local_storage
|
|
||||||
struct pthread_cleanup_t
|
|
||||||
{
|
|
||||||
void (*routine)(void*);
|
|
||||||
void* arg;
|
|
||||||
pthread_cleanup_t* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static thread_local pthread_cleanup_t* s_cleanup_stack = nullptr;
|
|
||||||
|
|
||||||
void pthread_cleanup_pop(int execute)
|
void pthread_cleanup_pop(int execute)
|
||||||
{
|
{
|
||||||
ASSERT(s_cleanup_stack);
|
uthread* uthread = _get_uthread();
|
||||||
|
ASSERT(uthread->cleanup_stack);
|
||||||
|
|
||||||
auto* cleanup = s_cleanup_stack;
|
auto* cleanup = uthread->cleanup_stack;
|
||||||
s_cleanup_stack = cleanup->next;
|
uthread->cleanup_stack = cleanup->next;
|
||||||
|
|
||||||
if (execute)
|
if (execute)
|
||||||
cleanup->routine(cleanup->arg);
|
cleanup->routine(cleanup->arg);
|
||||||
|
@ -100,16 +95,17 @@ void pthread_cleanup_pop(int execute)
|
||||||
|
|
||||||
void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
void pthread_cleanup_push(void (*routine)(void*), void* arg)
|
||||||
{
|
{
|
||||||
auto* cleanup = static_cast<pthread_cleanup_t*>(malloc(sizeof(pthread_cleanup_t)));
|
auto* cleanup = static_cast<_pthread_cleanup_t*>(malloc(sizeof(_pthread_cleanup_t)));
|
||||||
ASSERT(cleanup);
|
ASSERT(cleanup);
|
||||||
|
|
||||||
|
uthread* uthread = _get_uthread();
|
||||||
|
|
||||||
cleanup->routine = routine;
|
cleanup->routine = routine;
|
||||||
cleanup->arg = arg;
|
cleanup->arg = arg;
|
||||||
cleanup->next = s_cleanup_stack;
|
cleanup->next = uthread->cleanup_stack;
|
||||||
|
|
||||||
s_cleanup_stack = cleanup;
|
uthread->cleanup_stack = cleanup;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if not __disable_thread_local_storage
|
#if not __disable_thread_local_storage
|
||||||
static thread_local struct {
|
static thread_local struct {
|
||||||
|
@ -175,38 +171,156 @@ int pthread_attr_destroy(pthread_attr_t* attr)
|
||||||
|
|
||||||
int pthread_attr_init(pthread_attr_t* attr)
|
int pthread_attr_init(pthread_attr_t* attr)
|
||||||
{
|
{
|
||||||
*attr = 0;
|
*attr = {
|
||||||
return 0;
|
.inheritsched = PTHREAD_INHERIT_SCHED,
|
||||||
}
|
.schedparam = {},
|
||||||
|
.schedpolicy = SCHED_RR,
|
||||||
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
|
.detachstate = PTHREAD_CREATE_JOINABLE,
|
||||||
{
|
.scope = PTHREAD_SCOPE_SYSTEM,
|
||||||
(void)attr;
|
.stacksize = Kernel::Thread::userspace_stack_size,
|
||||||
(void)stacksize;
|
.guardsize = static_cast<size_t>(getpagesize()),
|
||||||
dwarnln("TODO: ignoring pthread_attr_setstacksize");
|
};
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate)
|
int pthread_attr_getdetachstate(const pthread_attr_t* attr, int* detachstate)
|
||||||
{
|
{
|
||||||
(void)attr;
|
*detachstate = attr->detachstate;
|
||||||
*detachstate = PTHREAD_CREATE_JOINABLE;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_attr_setdetachstate(pthread_attr_t* attr, int detachstate)
|
int pthread_attr_setdetachstate(pthread_attr_t* attr, int detachstate)
|
||||||
{
|
{
|
||||||
(void)attr;
|
|
||||||
switch (detachstate)
|
switch (detachstate)
|
||||||
{
|
{
|
||||||
case PTHREAD_CREATE_DETACHED:
|
case PTHREAD_CREATE_DETACHED:
|
||||||
dwarnln("TODO: pthread_attr_setdetachstate");
|
dwarnln("TODO: pthread_attr_setdetachstate");
|
||||||
return ENOTSUP;
|
return ENOTSUP;
|
||||||
case PTHREAD_CREATE_JOINABLE:
|
case PTHREAD_CREATE_JOINABLE:
|
||||||
|
attr->detachstate = detachstate;
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
|
||||||
return EINVAL;
|
|
||||||
}
|
}
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getguardsize(const pthread_attr_t* __restrict attr, size_t* __restrict guardsize)
|
||||||
|
{
|
||||||
|
*guardsize = attr->guardsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setguardsize(pthread_attr_t* attr, size_t guardsize)
|
||||||
|
{
|
||||||
|
attr->guardsize = guardsize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getinheritsched(const pthread_attr_t* __restrict attr, int* __restrict inheritsched)
|
||||||
|
{
|
||||||
|
*inheritsched = attr->inheritsched;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setinheritsched(pthread_attr_t* attr, int inheritsched)
|
||||||
|
{
|
||||||
|
switch (inheritsched)
|
||||||
|
{
|
||||||
|
case PTHREAD_INHERIT_SCHED:
|
||||||
|
case PTHREAD_EXPLICIT_SCHED:
|
||||||
|
attr->inheritsched = inheritsched;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getschedparam(const pthread_attr_t* __restrict attr, struct sched_param* __restrict param)
|
||||||
|
{
|
||||||
|
*param = attr->schedparam;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setschedparam(pthread_attr_t* __restrict attr, const struct sched_param* __restrict param)
|
||||||
|
{
|
||||||
|
attr->schedparam = *param;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getschedpolicy(const pthread_attr_t* __restrict attr, int* __restrict policy)
|
||||||
|
{
|
||||||
|
*policy = attr->schedpolicy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy)
|
||||||
|
{
|
||||||
|
switch (policy)
|
||||||
|
{
|
||||||
|
case SCHED_FIFO:
|
||||||
|
case SCHED_SPORADIC:
|
||||||
|
case SCHED_OTHER:
|
||||||
|
return ENOTSUP;
|
||||||
|
case SCHED_RR:
|
||||||
|
attr->schedpolicy = policy;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getscope(const pthread_attr_t* __restrict attr, int* __restrict contentionscope)
|
||||||
|
{
|
||||||
|
*contentionscope = attr->scope;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setscope(pthread_attr_t* attr, int contentionscope)
|
||||||
|
{
|
||||||
|
switch (contentionscope)
|
||||||
|
{
|
||||||
|
case PTHREAD_SCOPE_PROCESS:
|
||||||
|
return ENOTSUP;
|
||||||
|
case PTHREAD_SCOPE_SYSTEM:
|
||||||
|
attr->scope = contentionscope;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getstack(const pthread_attr_t* __restrict attr, void** __restrict stackaddr, size_t* __restrict stacksize)
|
||||||
|
{
|
||||||
|
(void)attr;
|
||||||
|
(void)stackaddr;
|
||||||
|
(void)stacksize;
|
||||||
|
dwarnln("TODO: pthread_attr_getstack");
|
||||||
|
return ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setstack(pthread_attr_t* attr, void* stackaddr, size_t stacksize)
|
||||||
|
{
|
||||||
|
(void)attr;
|
||||||
|
(void)stackaddr;
|
||||||
|
(void)stacksize;
|
||||||
|
dwarnln("TODO: pthread_attr_setstack");
|
||||||
|
return ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_getstacksize(const pthread_attr_t* __restrict attr, size_t* __restrict stacksize)
|
||||||
|
{
|
||||||
|
*stacksize = attr->stacksize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_attr_setstacksize(pthread_attr_t* attr, size_t stacksize)
|
||||||
|
{
|
||||||
|
attr->stacksize = stacksize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pthread_setcancelstate(int state, int* oldstate)
|
||||||
|
{
|
||||||
|
(void)state;
|
||||||
|
(void)oldstate;
|
||||||
|
dwarnln("TODO: pthread_setcancelstate");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
|
int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __restrict attr, void* (*start_routine)(void*), void* __restrict arg)
|
||||||
|
@ -223,14 +337,20 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
||||||
|
|
||||||
long syscall_ret = 0;
|
long syscall_ret = 0;
|
||||||
|
|
||||||
if (uthread* self = get_uthread(); self->master_tls_addr == nullptr)
|
if (uthread* self = _get_uthread(); self->master_tls_addr == nullptr)
|
||||||
{
|
{
|
||||||
uthread* uthread = static_cast<struct uthread*>(malloc(sizeof(struct uthread) + sizeof(uintptr_t)));
|
uthread* uthread = static_cast<struct uthread*>(malloc(sizeof(struct uthread) + sizeof(uintptr_t)));
|
||||||
if (uthread == nullptr)
|
if (uthread == nullptr)
|
||||||
goto pthread_create_error;
|
goto pthread_create_error;
|
||||||
uthread->self = uthread;
|
|
||||||
uthread->master_tls_addr = nullptr;
|
*uthread = {
|
||||||
uthread->master_tls_size = 0;
|
.self = uthread,
|
||||||
|
.master_tls_addr = nullptr,
|
||||||
|
.master_tls_size = 0,
|
||||||
|
.cleanup_stack = nullptr,
|
||||||
|
.id = -1,
|
||||||
|
.errno_ = 0,
|
||||||
|
};
|
||||||
uthread->dtv[0] = 0;
|
uthread->dtv[0] = 0;
|
||||||
|
|
||||||
info->uthread = uthread;
|
info->uthread = uthread;
|
||||||
|
@ -249,9 +369,14 @@ int pthread_create(pthread_t* __restrict thread_id, const pthread_attr_t* __rest
|
||||||
memcpy(tls_addr, self->master_tls_addr, self->master_tls_size);
|
memcpy(tls_addr, self->master_tls_addr, self->master_tls_size);
|
||||||
|
|
||||||
uthread* uthread = reinterpret_cast<struct uthread*>(tls_addr + self->master_tls_size);
|
uthread* uthread = reinterpret_cast<struct uthread*>(tls_addr + self->master_tls_size);
|
||||||
uthread->self = uthread;
|
*uthread = {
|
||||||
uthread->master_tls_addr = self->master_tls_addr;
|
.self = uthread,
|
||||||
uthread->master_tls_size = self->master_tls_size;
|
.master_tls_addr = self->master_tls_addr,
|
||||||
|
.master_tls_size = self->master_tls_size,
|
||||||
|
.cleanup_stack = nullptr,
|
||||||
|
.id = -1,
|
||||||
|
.errno_ = 0,
|
||||||
|
};
|
||||||
|
|
||||||
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
|
const uintptr_t self_addr = reinterpret_cast<uintptr_t>(self);
|
||||||
const uintptr_t uthread_addr = reinterpret_cast<uintptr_t>(uthread);
|
const uintptr_t uthread_addr = reinterpret_cast<uintptr_t>(uthread);
|
||||||
|
@ -288,9 +413,11 @@ int pthread_detach(pthread_t thread)
|
||||||
|
|
||||||
void pthread_exit(void* value_ptr)
|
void pthread_exit(void* value_ptr)
|
||||||
{
|
{
|
||||||
#if not __disable_thread_local_storage
|
uthread* uthread = _get_uthread();
|
||||||
while (s_cleanup_stack)
|
while (uthread->cleanup_stack)
|
||||||
pthread_cleanup_pop(1);
|
pthread_cleanup_pop(1);
|
||||||
|
|
||||||
|
#if not __disable_thread_local_storage
|
||||||
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
for (size_t iteration = 0; iteration < PTHREAD_DESTRUCTOR_ITERATIONS; iteration++)
|
||||||
{
|
{
|
||||||
bool called = false;
|
bool called = false;
|
||||||
|
@ -309,7 +436,8 @@ void pthread_exit(void* value_ptr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
free_uthread(get_uthread());
|
|
||||||
|
free_uthread(uthread);
|
||||||
syscall(SYS_PTHREAD_EXIT, value_ptr);
|
syscall(SYS_PTHREAD_EXIT, value_ptr);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -326,14 +454,7 @@ int pthread_join(pthread_t thread, void** value_ptr)
|
||||||
|
|
||||||
pthread_t pthread_self(void)
|
pthread_t pthread_self(void)
|
||||||
{
|
{
|
||||||
#if __disable_thread_local_storage
|
return _get_uthread()->id;
|
||||||
return syscall(SYS_PTHREAD_SELF);
|
|
||||||
#else
|
|
||||||
static thread_local pthread_t s_pthread_self { -1 };
|
|
||||||
if (s_pthread_self == -1) [[unlikely]]
|
|
||||||
s_pthread_self = syscall(SYS_PTHREAD_SELF);
|
|
||||||
return s_pthread_self;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
|
int pthread_once(pthread_once_t* once_control, void (*init_routine)(void))
|
||||||
|
@ -732,7 +853,7 @@ int pthread_condattr_getpshared(const pthread_condattr_t* __restrict attr, int*
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pthread_condattr_setpshared(pthread_barrierattr_t* attr, int pshared)
|
int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared)
|
||||||
{
|
{
|
||||||
switch (pshared)
|
switch (pshared)
|
||||||
{
|
{
|
||||||
|
@ -925,7 +1046,7 @@ struct tls_index
|
||||||
|
|
||||||
extern "C" void* __tls_get_addr(tls_index* ti)
|
extern "C" void* __tls_get_addr(tls_index* ti)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<void*>(get_uthread()->dtv[ti->ti_module] + ti->ti_offset);
|
return reinterpret_cast<void*>(_get_uthread()->dtv[ti->ti_module] + ti->ti_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARCH(i686)
|
#if ARCH(i686)
|
||||||
|
|
|
@ -34,7 +34,13 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
||||||
if (::environ == nullptr)
|
if (::environ == nullptr)
|
||||||
::environ = environ;
|
::environ = environ;
|
||||||
|
|
||||||
if (syscall(SYS_GET_TLS) == 0)
|
if (uthread* self = reinterpret_cast<uthread*>(syscall(SYS_GET_TLS)))
|
||||||
|
{
|
||||||
|
self->cleanup_stack = nullptr;
|
||||||
|
self->id = syscall(SYS_PTHREAD_SELF);
|
||||||
|
self->errno_ = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
alignas(uthread) static uint8_t storage[sizeof(uthread) + sizeof(uintptr_t)];
|
alignas(uthread) static uint8_t storage[sizeof(uthread) + sizeof(uintptr_t)];
|
||||||
|
|
||||||
|
@ -43,6 +49,9 @@ extern "C" void _init_libc(char** environ, init_funcs_t init_funcs, init_funcs_t
|
||||||
.self = &uthread,
|
.self = &uthread,
|
||||||
.master_tls_addr = nullptr,
|
.master_tls_addr = nullptr,
|
||||||
.master_tls_size = 0,
|
.master_tls_size = 0,
|
||||||
|
.cleanup_stack = nullptr,
|
||||||
|
.id = static_cast<pthread_t>(syscall(SYS_PTHREAD_SELF)),
|
||||||
|
.errno_ = 0,
|
||||||
};
|
};
|
||||||
uthread.dtv[0] = 0;
|
uthread.dtv[0] = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue