Blame src/arch/nt32/crt_glue.c

716654
/**************************************************************************/
716654
/*  mmglue: midipix architecture- and target-specific bits for musl libc  */
716654
/*  Copyright (C) 2013--2023  SysDeer Technologies, LLC                   */
716654
/*  Released under the Standard MIT License; see COPYING.MMGLUE.          */
716654
/**************************************************************************/
716654
296178
#include <unistd.h>
6f8ae4
#include <stdint.h>
296178
#include <pthread.h>
296178
#include "atomic.h"
296178
#include "syscall.h"
296178
#include "psxglue.h"
296178
#include "pthread_impl.h"
296178
3d4ab4
volatile int __thread_list_lock;
3d4ab4
215106
extern const struct __ldso_vtbl * __ldso_vtbl;
215106
extern const struct __psx_vtbl *  __psx_vtbl;
116201
extern const struct __seh_vtbl *  __eh_vtbl;
296178
296178
static int __pthread_surrogate_init(struct pthread * self);
296178
296178
extern int __libc_start_main(
296178
	void *	main,
296178
	int	argc,
296178
	char **	argv);
296178
4a4697
static void (*__global_ctors_fn)();
4a4697
static void (*__global_dtors_fn)();
4a4697
4a4697
void _init()
4a4697
{
4a4697
	__global_ctors_fn();
4a4697
}
4a4697
4a4697
void _fini()
4a4697
{
4a4697
	__global_dtors_fn();
4a4697
}
4a4697
4a4697
struct __tls {
5085e9
	void *		pad[16/sizeof(void *)];
5085e9
	struct pthread	pt;
5085e9
} __builtin_tls = {{0}};
5085e9
5085e9
void __init_tls (size_t * auxv)
5085e9
{
5085e9
	#define T __builtin_tls
5085e9
5085e9
	__set_thread_area(&T.pt);
5085e9
5085e9
	T.pt.self	= &T.pt;
5085e9
	T.pt.locale	= &libc.global_locale;
3e250a
	T.pt.sysinfo	= __sysinfo;
5085e9
ca29c2
	T.pt.detach_state     = DT_JOINABLE;
ca29c2
	T.pt.locale           = &libc.global_locale;
ca29c2
	T.pt.robust_list.head = &T.pt.robust_list.head;
ca29c2
1fabb2
	libc.can_do_threads = 1;
5085e9
	libc.tls_size = sizeof(struct __tls);
3d4ab4
3d4ab4
#if defined(__LIBC_TD_TID_ADDR_TID)
3d4ab4
	T.pt.tid	= __syscall(SYS_set_tid_address, &T.pt.tid);
3d4ab4
#elif defined(__LIBC_TD_TID_ADDR_JOIN_FUTEX)
3d4ab4
	T.pt.join_futex = -1;
3d4ab4
	T.pt.tid	= __syscall(SYS_set_tid_address, &T.pt.join_futex);
3d4ab4
#elif defined(__LIBC_TD_TID_ADDR_DETACH_STATE)
3d4ab4
	T.pt.tid	= __syscall(SYS_set_tid_address, &T.pt.detach_state);
3d4ab4
#elif defined(__LIBC_TD_TID_ADDR_THREAD_LIST_LOCK)
3d4ab4
	T.pt.tid	= __syscall(SYS_set_tid_address, &T.pt.detach_state);
3d4ab4
	T.pt.next       = &T.pt;
3d4ab4
	T.pt.prev       = &T.pt;
3d4ab4
#else
3d4ab4
	#error could not detect tid address logic.
3d4ab4
#endif
3d4ab4
5085e9
};
5085e9
296178
void __libc_entry_routine(
b945a6
	int			(*main)(),
296178
	__psx_init_routine *	__psx_init,
554d2c
	const unsigned short *	__ctty,
296178
	int			options)
296178
{
296178
	int			argc;
296178
	char **			argv;
296178
	char **			envp;
296178
	struct __psx_context	ctx;
296178
296178
	/* ctx init */
296178
	ctx.size		= sizeof(ctx);
296178
	ctx.options		= options;
b945a6
	ctx.usrmain		= main;
6c368a
	ctx.ldsoaddr		= _init;
554d2c
	ctx.ctty		= __ctty;
296178
	ctx.pthread_create_fn	= pthread_create;
296178
	ctx.pthread_surrogate_fn= __pthread_surrogate_init;
296178
296178
	/* __psx_init must succeed... */
296178
	if (__psx_init(&argc,&argv,&envp,&ctx))
296178
		a_crash();
296178
296178
	/* ...and conform */
296178
	else if (envp != argv + (argc + 1))
296178
		a_crash();
296178
296178
	/* write once */
296178
	__syscall_vtbl	= (unsigned long **)ctx.sys_vtbl;
296178
	__ldso_vtbl	= ctx.ldso_vtbl;
296178
	__psx_vtbl	= ctx.psx_vtbl;
116201
	__eh_vtbl	= ctx.seh_vtbl;
e1d268
296178
	__teb_sys_idx	= ctx.teb_sys_idx;
296178
	__teb_libc_idx	= ctx.teb_libc_idx;
296178
5085e9
	/* surrogate init/fini arrays */
03bf9a
	__global_ctors_fn = __psx_vtbl->do_global_ctors_fn;
03bf9a
	__global_dtors_fn = __psx_vtbl->do_global_dtors_fn;
5085e9
296178
	/* enter libc */
7f1932
	__psx_vtbl->mm_start_main(argc,argv,__libc_start_main);
296178
296178
	/* guard */
296178
	a_crash();
296178
}
296178
296178
static int __pthread_surrogate_init(struct pthread * self)
296178
{
296178
	/**
296178
	 * invoked by psxscl upon creation of a surrogate libc
296178
	 * thread, which in turn may only call pthread_create();
296178
	 *
296178
	 * the purpose of this mecahnism is to support a scenario
296178
	 * where a third-party library creates a non-posix thread
296178
	 * which then calls, be it directly or via a callback
296178
	 * function, a libc api that depends on a valid
296178
	 * pthread_self.
296178
	 *
296178
	 * self: a pointer to an already zero'ed memory page
296178
	 *
296178
	 * struct pthread relevant members:
296178
	 * --------------------------------
296178
	 * cancel (already zero)
296178
	 * canary (already zero)
296178
	 *
296178
	 * pthread_create() reference:
296178
	 * 1a47ed15eebf96d0c8d5de4aea54108bc8cc3f53
296178
	**/
296178
296178
	return 0;
296178
}