|  | @@ -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
 | 
	
		
			
				|  |  | +}
 |