|
@@ -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
|
|
|
|
|
@@ -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
|
|
|
|
|
|
|
|
@@ -126,7 +137,7 @@ static void __check_one_fd(int fd, int mode)
|
|
|
int nullfd = open(_PATH_DEVNULL, mode);
|
|
|
|
|
|
* 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__
|
|
|
+
|
|
|
+ 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__
|
|
|
+
|
|
|
+ struct pthread_unwind_buf unwind_buf;
|
|
|
|
|
|
-#if defined(__UCLIBC_HAS_THREADS__) && !defined(SHARED)
|
|
|
-
|
|
|
- *
|
|
|
- * 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;
|
|
|
+
|
|
|
+
|
|
|
+ unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
|
|
|
+ unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup);
|
|
|
+
|
|
|
+
|
|
|
+ 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)
|
|
|
+
|
|
|
+ result = main (argc, argv, __environ);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+# ifdef SHARED
|
|
|
+ __libc_pthread_functions.ptr__nptl_deallocate_tsd ();
|
|
|
+# else
|
|
|
+ extern void __nptl_deallocate_tsd (void) __attribute ((weak));
|
|
|
+ __nptl_deallocate_tsd ();
|
|
|
# endif
|
|
|
+
|
|
|
+
|
|
|
+ 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))
|
|
|
+
|
|
|
+ __exit_thread_inline (0);
|
|
|
+ }
|
|
|
+
|
|
|
+ exit (result);
|
|
|
+#else
|
|
|
+
|
|
|
+ * Finally, invoke application's main and then exit.
|
|
|
+ */
|
|
|
+ exit (main (argc, argv, __environ));
|
|
|
#endif
|
|
|
+}
|