Blame arch/nt64/src/crt_glue.c

860627
#include <unistd.h>
6f8ae4
#include <stdint.h>
860627
#include <pthread.h>
860627
#include "atomic.h"
860627
#include "syscall.h"
860627
#include "psxglue.h"
860627
#include "pthread_impl.h"
860627
215106
extern const struct __ldso_vtbl * __ldso_vtbl;
215106
extern const struct __psx_vtbl *  __psx_vtbl;
860627
860627
typedef int __app_main();
860627
typedef int __pthread_surrogate_routine(struct pthread *);
860627
860627
static int __pthread_surrogate_init(struct pthread * self);
860627
860627
extern int __libc_start_main(
860627
	void *	main,
860627
	int	argc,
860627
	char **	argv);
860627
51d2a0
static void (*__global_ctors_fn)();
51d2a0
static void (*__global_dtors_fn)();
51d2a0
51d2a0
void _init()
51d2a0
{
51d2a0
	__global_ctors_fn();
51d2a0
}
51d2a0
51d2a0
void _fini()
51d2a0
{
51d2a0
	__global_dtors_fn();
51d2a0
}
51d2a0
5085e9
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
860627
void __libc_entry_routine(
860627
	__app_main *		__main,
71c767
	__psx_init_routine *	__psx_init,
554d2c
	const unsigned short *	__ctty,
860627
	int			options)
860627
{
860627
	int			argc;
860627
	char **			argv;
860627
	char **			envp;
860627
	struct __psx_context	ctx;
860627
860627
	/* ctx init */
860627
	ctx.size		= sizeof(ctx);
860627
	ctx.options		= options;
962692
	ctx.refaddr		= __main;
962692
	ctx.libcaddr		= _init;
554d2c
	ctx.ctty		= __ctty;
860627
	ctx.pthread_create_fn	= pthread_create;
860627
	ctx.pthread_surrogate_fn= __pthread_surrogate_init;
860627
860627
	/* __psx_init must succeed... */
71c767
	if (__psx_init(&argc,&argv,&envp,&ctx))
860627
		a_crash();
860627
860627
	/* ...and conform */
860627
	else if (envp != argv + (argc + 1))
860627
		a_crash();
860627
860627
	/* write once */
860627
	__syscall_vtbl	= (unsigned long **)ctx.sys_vtbl;
860627
	__ldso_vtbl	= ctx.ldso_vtbl;
860627
	__psx_vtbl	= ctx.psx_vtbl;
860627
	__teb_sys_idx	= ctx.teb_sys_idx;
860627
	__teb_libc_idx	= ctx.teb_libc_idx;
860627
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
860627
	/* enter libc */
215106
	__psx_vtbl->start_main(__main,argc,argv,__libc_start_main);
860627
860627
	/* guard */
860627
	a_crash();
860627
}
860627
860627
static int __pthread_surrogate_init(struct pthread * self)
860627
{
860627
	/**
860627
	 * invoked by psxscl upon creation of a surrogate libc
860627
	 * thread, which in turn may only call pthread_create();
860627
	 *
860627
	 * the purpose of this mecahnism is to support a scenario
860627
	 * where a third-party library creates a non-posix thread
860627
	 * which then calls, be it directly or via a callback
860627
	 * function, a libc api that depends on a valid
860627
	 * pthread_self.
860627
	 *
860627
	 * self: a pointer to an already zero'ed memory page
860627
	 *
860627
	 * struct pthread relevant members:
860627
	 * --------------------------------
860627
	 * cancel (already zero)
860627
	 * canary (already zero)
860627
	 *
860627
	 * pthread_create() reference:
860627
	 * 1a47ed15eebf96d0c8d5de4aea54108bc8cc3f53
860627
	**/
860627
860627
	return 0;
860627
}