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