diff options
Diffstat (limited to 'libc/misc/internals/__uClibc_main.c')
| -rw-r--r-- | libc/misc/internals/__uClibc_main.c | 107 | 
1 files changed, 74 insertions, 33 deletions
| diff --git a/libc/misc/internals/__uClibc_main.c b/libc/misc/internals/__uClibc_main.c index b166aaaa7..85dbe7123 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 @@ -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); + +		/* 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 -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) +		/* 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 +} | 
