about summary refs log tree commit diff
path: root/linuxthreads
diff options
context:
space:
mode:
Diffstat (limited to 'linuxthreads')
-rw-r--r--linuxthreads/ChangeLog6
-rw-r--r--linuxthreads/attr.c9
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S39
3 files changed, 46 insertions, 8 deletions
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index cd5eb8e61f..5a86b94232 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -1,3 +1,9 @@
+2003-09-17  Philip Blundell  <philb@gnu.org>
+
+	* sysdeps/unix/sysv/linux/arm/vfork.S: Branch to fork if
+	libpthread is loaded.  Elide backwards compatibility code when not
+	required.
+
 2003-09-17  Jakub Jelinek  <jakub@redhat.com>
 
 	* descr.h (manager_thread): Rename to...
diff --git a/linuxthreads/attr.c b/linuxthreads/attr.c
index a66eb72c27..687334ffdb 100644
--- a/linuxthreads/attr.c
+++ b/linuxthreads/attr.c
@@ -404,7 +404,11 @@ int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
 # endif
 #endif
 
+#ifdef USE_TLS
   if (attr->__stackaddr == NULL)
+#else
+  if (descr == &__pthread_initial_thread)
+#endif
     {
       /* Defined in ld.so.  */
       extern void *__libc_stack_end;
@@ -448,6 +452,11 @@ int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
 		  attr->__stacksize = rl.rlim_cur;
 		  attr->__stackaddr = (void *) to;
 
+		  /* The limit might be too high.  This is a bogus
+		     situation but try to avoid making it worse.  */
+		  if ((size_t) attr->__stacksize > (size_t) attr->__stackaddr)
+		    attr->__stacksize = (size_t) attr->__stackaddr;
+
 		  /* We succeed and no need to look further.  */
 		  ret = 0;
 		  break;
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
index 8d3338afd0..23687342d1 100644
--- a/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
+++ b/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S
@@ -20,37 +20,60 @@
 #include <sysdep-cancel.h>
 #define _ERRNO_H	1
 #include <bits/errno.h>
+#include <kernel-features.h>
 
-/* Clone the calling process, but without copying the whole address
-pace.
+/* Clone the calling process, but without copying the whole address space.
    The calling process is suspended until the new process exits or is
-   replaced by a call to `execve'.  Return -1 for errors, 0 to the new
-rocess,
+   replaced by a call to `execve'.  Return -1 for errors, 0 to the new process,
    and the process ID of the new process to the old process.  */
 
 	PSEUDO_PROLOGUE
 
 ENTRY (__vfork)
 
-	SINGLE_THREAD_P
-	bne	HIDDEN_JUMPTARGET (__fork)
 #ifdef __NR_vfork
+
+#ifdef SHARED
+	ldr	ip, 1f
+	ldr	r0, 2f
+3:	add	ip, pc, ip
+	ldr	r0, [ip, r0]
+#else
+	ldr	r0, 1f
+#endif
+	movs	r0, r0
+	bne	HIDDEN_JUMPTARGET (__fork)
+		
 	swi	__NR_vfork
 	cmn	a1, #4096
 	RETINSTR(movcc, pc, lr)
 
+#ifndef __ASSUME_VFORK_SYSCALL
 	/* Check if vfork syscall is known at all.  */
-	ldr	a2, =-ENOSYS
-	teq	a1, a2
+	cmn	a1, #ENOSYS
 	bne	PLTJMP(C_SYMBOL_NAME(__syscall_error))
 #endif
 
+#endif
+
+#ifndef __ASSUME_VFORK_SYSCALL
 	/* If we don't have vfork, fork is close enough.  */
 	swi	__NR_fork
 	cmn	a1, #4096
 	RETINSTR(movcc, pc, lr)
+#elif !defined __NR_vfork
+# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined"
+#endif
     	b	PLTJMP(C_SYMBOL_NAME(__syscall_error))
 
+#ifdef SHARED
+1:	.word	_GLOBAL_OFFSET_TABLE_ - 3b - 8
+2:	.word	__libc_pthread_functions(GOTOFF)
+#else
+	.weak	pthread_create
+1:	.word	pthread_create
+#endif
+
 PSEUDO_END (__vfork)
 libc_hidden_def (__vfork)