Blame arch/nt32/src/crt_glue.c

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
215106
extern const struct __ldso_vtbl * __ldso_vtbl;
215106
extern const struct __psx_vtbl *  __psx_vtbl;
296178
296178
typedef int __app_main();
296178
typedef int __pthread_surrogate_routine(struct pthread *);
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;
5085e9
	T.pt.tid	= __syscall(SYS_set_tid_address, &T.pt.tid);
5085e9
1fabb2
	libc.can_do_threads = 1;
5085e9
	libc.tls_size = sizeof(struct __tls);
5085e9
};
5085e9
296178
void __libc_entry_routine(
296178
	__app_main *		__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;
962692
	ctx.refaddr		= __main;
962692
	ctx.libcaddr		= _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;
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 */
215106
	__psx_vtbl->start_main(__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
}