172 lines
4.6 KiB
C
172 lines
4.6 KiB
C
/*
|
|
* $QNXLicenseC:
|
|
* Copyright 2007, QNX Software Systems. All Rights Reserved.
|
|
*
|
|
* You must obtain a written license from and pay applicable license fees to QNX
|
|
* Software Systems before you may reproduce, modify or distribute this software,
|
|
* or any work that includes all or part of this software. Free development
|
|
* licenses are available for evaluation and non-commercial purposes. For more
|
|
* information visit http://licensing.qnx.com or email licensing@qnx.com.
|
|
*
|
|
* This file may contain contributions from others. Please review this entire
|
|
* file for other proprietary rights or license notices, as well as the QNX
|
|
* Development Suite License Guide at http://licensing.qnx.com/license-guide/
|
|
* for other information.
|
|
* $
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include <inttypes.h>
|
|
#include <errno.h>
|
|
#include <sys/auxv.h>
|
|
#include <sys/neutrino.h>
|
|
#include <sys/syspage.h>
|
|
#include "init.h"
|
|
#include "cpucfg.h"
|
|
#define EXT
|
|
#include "pls.h"
|
|
#undef errno /* Undefined so the main thread uses a global "errno" */
|
|
|
|
#if defined(__X86__)
|
|
/* X86 uses the fs register for cpupage, so one pointer is not valid */
|
|
#elif defined(__MIPS__) \
|
|
|| defined(__PPC__) \
|
|
|| defined(__ARM__) \
|
|
|| defined(__SH__)
|
|
#define WANT_CPUPAGE_PTR
|
|
#else
|
|
#error Not configured for CPU
|
|
#endif
|
|
|
|
|
|
int _argc;
|
|
char **_argv;
|
|
auxv_t *_auxv;
|
|
int errno;
|
|
char **environ;
|
|
char *__progname;
|
|
int _Multi_threaded;
|
|
struct syspage_entry *_syspage_ptr;
|
|
uint32_t __cpu_flags;
|
|
#if defined(__MIPS__) || defined(__SH__)
|
|
volatile unsigned long *__shadow_imask; //Kludge for MIPS and SH
|
|
#endif
|
|
#if defined(WANT_CPUPAGE_PTR)
|
|
struct cpupage_entry *_cpupage_ptr;
|
|
#endif
|
|
#ifdef __WATCOMC__
|
|
unsigned char __8087, __real87;
|
|
#endif
|
|
int __posixly_correct;
|
|
int __ealready_value;
|
|
|
|
extern void __my_thread_exit(void *);
|
|
|
|
|
|
void _init_libc(int argc, char *argv[], char *arge[], auxv_t auxv[], void (*exit_func)(void)) {
|
|
char *prog;
|
|
|
|
if(__progname == NULL) {
|
|
/* Initialize the system page pointer */
|
|
_syspage_ptr = __SysCpupageGet(CPUPAGE_SYSPAGE);
|
|
#if defined(__MIPS__)
|
|
__shadow_imask = &_syspage_ptr->un.mips.shadow_imask;
|
|
#endif
|
|
|
|
/* Tell the process manager where our process local storage is */
|
|
(void)__SysCpupageSet(CPUPAGE_PLS, (intptr_t)&_pls);
|
|
|
|
#if defined(WANT_CPUPAGE_PTR)
|
|
/* Initialize the cpupage pointer if the processor has it at a fixed address */
|
|
_cpupage_ptr = __SysCpupageGet(CPUPAGE_ADDR);
|
|
#endif
|
|
|
|
/* Initialize the math emulator hook */
|
|
_pls.__mathemulator = _math_emu_stub;
|
|
|
|
/* So the kernel always knows what to use for SIGEV_THREAD's */
|
|
LIBC_TLS()->__exitfunc = __my_thread_exit;
|
|
|
|
/* extract the cpu flags from syspage so we can get at them faster */
|
|
__cpu_flags = SYSPAGE_ENTRY(cpuinfo)->flags;
|
|
|
|
#if defined(__SH__)
|
|
if (_syspage_ptr->num_cpu > 1) {
|
|
__shadow_imask = &_cpupage_ptr->un.sh.imask;
|
|
}
|
|
else {
|
|
__shadow_imask = &_syspage_ptr->un.sh.imask;
|
|
}
|
|
#endif
|
|
|
|
#ifdef __WATCOMC__
|
|
/* Watcom uses this for its floating point support routines */
|
|
if(SYSPAGE_ENTRY(cpuinfo)->flags & CPU_FLAG_FPU) {
|
|
__8087 = __real87 = SYSPAGE_ENTRY(cpuinfo)->cpu / 100;
|
|
}
|
|
#endif
|
|
|
|
#if defined(__SH__)
|
|
/* set __cpu_flags for inline ops in case startup didn't set any flags */
|
|
if (_syspage_ptr->num_cpu > 1) {
|
|
__cpu_flags |= SH_CPU_FLAG_SMP;
|
|
}
|
|
if (SH4_PVR_FAM(SYSPAGE_ENTRY(cpuinfo)->cpu) == SH4_PVR_SH4A) {
|
|
__cpu_flags |= SH_CPU_FLAG_MOVLICO;
|
|
}
|
|
#endif
|
|
|
|
//Get the basename of the program, but don't use basename() - it might
|
|
//modify the argv[0] storage.
|
|
prog = argv[0];
|
|
__progname = strrchr(prog, '/');
|
|
if(__progname == NULL) {
|
|
__progname = prog;
|
|
} else {
|
|
__progname++;
|
|
}
|
|
|
|
#ifdef __PIC__
|
|
/* This routine will fill _pls with the address of shared objects */
|
|
(void) _dll_list();
|
|
#endif
|
|
|
|
/* Set up globals for common information */
|
|
_argc = argc;
|
|
_argv = argv;
|
|
environ = arge;
|
|
_auxv = auxv;
|
|
|
|
/* check if strict POSIX behaviour is required */
|
|
if (getenv("POSIXLY_CORRECT") != 0) {
|
|
__posixly_correct = 1;
|
|
}
|
|
if (SYSPAGE_ENTRY(system_private)->private_flags & SYSTEM_PRIVATE_FLAG_EALREADY_NEW) {
|
|
__ealready_value = EALREADY_NEW;
|
|
} else {
|
|
__ealready_value = EALREADY_OLD;
|
|
}
|
|
}
|
|
|
|
/* Add exit function for runtime linker if passed */
|
|
if(exit_func) {
|
|
(void)atexit(exit_func);
|
|
}
|
|
|
|
/*
|
|
This is done here so that crt1.S & _init_libc both have the
|
|
same idea about what the address of the variable 'errno' is.
|
|
*/
|
|
LIBC_TLS()->__errptr = &errno;
|
|
/* Do this last to make sure errno is zero (as per ANSI C 7.1.4) */
|
|
errno = 0;
|
|
}
|
|
|
|
__SRCVERSION("_init_libc.c $Rev: 153381 $");
|