diff options
Diffstat (limited to 'libc/misc/internals/__uClibc_main.c')
-rw-r--r-- | libc/misc/internals/__uClibc_main.c | 109 |
1 files changed, 75 insertions, 34 deletions
diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index b166aaaa7..be63fe4cd 100644 --- a/libc/misc/internals/__uClibc_main.c +++ b/libc/misc/internals/__uClibc_main.c @@ -1,5 +1,6 @@ /* - * Copyright (C) Feb 2001 Manuel Novoa III + * Copyright (C) 2006 by Steven J. Hill <sjhill@realitydiluted.com> + * Copyright (C) 2001 by Manuel Novoa III <mjn3@uclibc.org> * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org> * * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. @@ -13,8 +14,10 @@ * avoided in the static library case. */ -#define _ERRNO_H #include <features.h> +#ifndef __UCLIBC_HAS_THREADS_NATIVE__ +#define _ERRNO_H +#endif #include <unistd.h> #include <stdlib.h> #include <string.h> @@ -22,10 +25,17 @@ #include <link.h> #include <bits/uClibc_page.h> #include <paths.h> +#include <unistd.h> #include <asm/errno.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/sysmacros.h> +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include <errno.h> +#include <pthread-functions.h> +#include <not-cancel.h> +#include <atomic.h> +#endif #ifndef SHARED @@ -56,7 +66,7 @@ uintptr_t __guard attribute_relro; /* * Needed to initialize _dl_phdr when statically linked */ - + void internal_function _dl_aux_init (ElfW(auxv_t) *av); #endif /* !SHARED */ @@ -64,16 +74,17 @@ void internal_function _dl_aux_init (ElfW(auxv_t) *av); * Prototypes. */ extern int *weak_const_function __errno_location(void); -libc_hidden_proto(__errno_location) extern int *weak_const_function __h_errno_location(void); -libc_hidden_proto(__h_errno_location) - extern void weak_function _stdio_init(void) attribute_hidden; #ifdef __UCLIBC_HAS_LOCALE__ extern void weak_function _locale_init(void) attribute_hidden; #endif #ifdef __UCLIBC_HAS_THREADS__ +#if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED) extern void weak_function __pthread_initialize_minimal(void); +#else +extern void __pthread_initialize_minimal(void); +#endif #endif /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation and finalisation @@ -126,7 +137,7 @@ static void __check_one_fd(int fd, int mode) int nullfd = open(_PATH_DEVNULL, mode); /* /dev/null is major=1 minor=3. Make absolutely certain * that is in fact the device that we have opened and not - * some other weird file... [removed in uclibc] */ + * some other wierd file... [removed in uclibc] */ if (nullfd!=fd) { abort(); @@ -183,7 +194,9 @@ void __uClibc_init(void) * __pthread_initialize_minimal so we can use pthread_locks * whenever they are needed. */ +#if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED) if (likely(__pthread_initialize_minimal!=NULL)) +#endif __pthread_initialize_minimal(); #endif @@ -267,6 +280,11 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, ElfW(auxv_t) auxvt[AT_EGID + 1]; #endif +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + /* Result of the 'main' function. */ + int result; +#endif + #ifndef SHARED __libc_stack_end = stack_end; #endif @@ -386,34 +404,57 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, if (likely(__h_errno_location!=NULL)) *(__h_errno_location()) = 0; - /* - * Finally, invoke application's main and then exit. - */ - exit(main(argc, argv, __environ)); -} +#if defined HAVE_CLEANUP_JMP_BUF && defined __UCLIBC_HAS_THREADS_NATIVE__ + /* Memory for the cancellation buffer. */ + struct pthread_unwind_buf unwind_buf; -#if defined(__UCLIBC_HAS_THREADS__) && !defined(SHARED) -/* Weaks for internal library use only. - * - * We need to define weaks here to cover all the pthread functions that - * libc itself will use so that we aren't forced to link libc against - * libpthread. This file is only used in libc.a and since we have - * weaks here, they will be automatically overridden by libpthread.a - * if it gets linked in. - */ + int not_first_call; + not_first_call = + setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + if (__builtin_expect (! not_first_call, 1)) + { + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); -static int __pthread_return_0 (void) { return 0; } -static void __pthread_return_void (void) { return; } - -weak_alias (__pthread_return_0, __pthread_mutex_init) -weak_alias (__pthread_return_0, __pthread_mutex_lock) -weak_alias (__pthread_return_0, __pthread_mutex_trylock) -weak_alias (__pthread_return_0, __pthread_mutex_unlock) -weak_alias (__pthread_return_void, _pthread_cleanup_push_defer) -weak_alias (__pthread_return_void, _pthread_cleanup_pop_restore) -# ifdef __UCLIBC_HAS_THREADS_NATIVE__ -weak_alias (__pthread_return_0, __pthread_mutexattr_init) -weak_alias (__pthread_return_0, __pthread_mutexattr_destroy) -weak_alias (__pthread_return_0, __pthread_mutexattr_settype) + /* Run the program. */ + result = main (argc, argv, __environ); + } + else + { + /* Remove the thread-local data. */ +# ifdef SHARED + __libc_pthread_functions.ptr__nptl_deallocate_tsd (); +# else + extern void __nptl_deallocate_tsd (void) __attribute ((weak)); + __nptl_deallocate_tsd (); # endif + + /* One less thread. Decrement the counter. If it is zero we + terminate the entire process. */ + result = 0; +# ifdef SHARED + unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads; +# else + extern unsigned int __nptl_nthreads __attribute ((weak)); + unsigned int *const ptr = &__nptl_nthreads; +# endif + + if (! atomic_decrement_and_test (ptr)) + /* Not much left to do but to exit the thread, not the process. */ + __exit_thread_inline (0); + } + + exit (result); +#else + /* + * Finally, invoke application's main and then exit. + */ + exit (main (argc, argv, __environ)); #endif +} |