Support STACK_GROWS_UP in linuxthreads
Matthew Wilcox
willy@ldl.fc.hp.com
Tue Jun 5 22:03:00 GMT 2001
2001-03-23 Matthew Wilcox <willy@ldl.fc.hp.com>
* linuxthreads/attr.c, linuxthreads/internals.h,
linuxthreads/manager.c, linuxthreads/pthread.c: make
_STACK_GROWS_UP work.
diff -urNx CVS glibc-223/linuxthreads/attr.c glibc-merge/linuxthreads/attr.c
--- glibc-223/linuxthreads/attr.c Tue Apr 24 14:10:57 2001
+++ glibc-merge/linuxthreads/attr.c Thu May 17 10:51:24 2001
@@ -283,8 +283,12 @@
attr->__inheritsched = descr->p_inheritsched;
attr->__scope = PTHREAD_SCOPE_SYSTEM;
+#ifdef _STACK_GROWS_DOWN
attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
- descr->p_guardsize;
+#else
+ attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
+#endif
attr->__guardsize = descr->p_guardsize;
attr->__stackaddr_set = descr->p_userstack;
#ifdef NEED_SEPARATE_REGISTER_STACK
@@ -298,7 +302,7 @@
#ifndef _STACK_GROWS_UP
attr->__stackaddr = (char *)(descr + 1);
#else
-# error __stackaddr not handled
+ attr->__stackaddr = (char *)descr;
#endif
return 0;
diff -urNx CVS glibc-223/linuxthreads/internals.h glibc-merge/linuxthreads/internals.h
--- glibc-223/linuxthreads/internals.h Tue Apr 24 14:10:57 2001
+++ glibc-merge/linuxthreads/internals.h Sat Apr 28 21:56:16 2001
@@ -384,7 +385,11 @@
else if (__pthread_nonstandard_stacks)
return __pthread_find_self();
else
+#ifdef _STACK_GROWS_DOWN
return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1;
+#else
+ return (pthread_descr)((unsigned long)sp &~ (STACK_SIZE-1));
+#endif
#endif
}
diff -urNx CVS glibc-223/linuxthreads/manager.c glibc-merge/linuxthreads/manager.c
--- glibc-223/linuxthreads/manager.c Tue Apr 24 14:10:57 2001
+++ glibc-merge/linuxthreads/manager.c Sun May 27 13:14:38 2001
@@ -32,6 +32,7 @@
#include "spinlock.h"
#include "restart.h"
#include "semaphore.h"
+#include <stackinfo.h>
/* Array of active threads. Entry 0 is reserved for the initial thread. */
struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] =
@@ -313,6 +314,13 @@
if (attr != NULL && attr->__stackaddr_set)
{
+#ifdef _STACK_GROWS_UP
+ /* The user provided a stack. */
+ new_thread = (pthread_descr) attr->__stackaddr;
+ new_thread_bottom = (char *) (new_thread + 1);
+ guardaddr = attr->__stackaddr + attr->__stacksize;
+ guardsize = 0;
+#else
/* The user provided a stack. For now we interpret the supplied
address as 1 + the highest addr. in the stack segment. If a
separate register stack is needed, we place it at the low end
@@ -328,6 +336,7 @@
new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize;
guardaddr = new_thread_bottom;
guardsize = 0;
+#endif
#ifndef THREAD_SELF
__pthread_nonstandard_stacks = 1;
#endif
@@ -423,12 +432,23 @@
/* No more memory available. */
return -1;
+# ifdef _STACK_GROWS_DOWN
guardaddr = map_addr;
if (guardsize > 0)
mprotect (guardaddr, guardsize, PROT_NONE);
new_thread_bottom = (char *) map_addr + guardsize;
new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1;
+# elif defined _STACK_GROWS_UP
+ guardaddr = map_addr + stacksize;
+ if (guardsize > 0)
+ mprotect (guardaddr, guardsize, PROT_NONE);
+
+ new_thread = (pthread_descr) map_addr;
+ new_thread_bottom = (char *) (new_thread + 1);
+# else
+# error You must define a stack direction
+# endif /* Stack direction */
# else /* !FLOATING_STACKS */
void *res_addr;
@@ -445,6 +465,7 @@
stacksize = STACK_SIZE - granularity;
}
+# ifdef _STACK_GROWS_DOWN
new_thread = default_new_thread;
new_thread_bottom = (char *) (new_thread + 1) - stacksize;
map_addr = new_thread_bottom - guardsize;
@@ -464,6 +485,23 @@
guardaddr = map_addr;
if (guardsize > 0)
mprotect (guardaddr, guardsize, PROT_NONE);
+# else
+ /* The thread description goes at the bottom of this area, and
+ * the stack starts directly above it.
+ */
+ new_thread = (pthread_descr)((unsigned long)default_new_thread &~ (STACK_SIZE - 1));
+ map_addr = mmap(new_thread, stacksize + guardsize,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (map_addr == MAP_FAILED)
+ return -1;
+
+ new_thread_bottom = map_addr + sizeof(*new_thread);
+ guardaddr = map_addr + stacksize;
+ if (guardsize > 0)
+ mprotect (guardaddr, guardsize, PROT_NONE);
+
+# endif /* stack direction */
# endif
#endif /* !NEED_SEPARATE_REGISTER_STACK */
}
@@ -591,6 +629,10 @@
(char *)new_thread - new_thread_bottom,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
__pthread_sig_cancel, new_thread);
+#elif _STACK_GROWS_UP
+ pid = __clone(pthread_start_thread_event, (void **) new_thread_bottom,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ __pthread_sig_cancel, new_thread);
#else
pid = __clone(pthread_start_thread_event, (void **) new_thread,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
@@ -627,6 +669,10 @@
(char *)new_thread - new_thread_bottom,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
__pthread_sig_cancel, new_thread);
+#elif _STACK_GROWS_UP
+ pid = __clone(pthread_start_thread, (void **) new_thread_bottom,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
+ __pthread_sig_cancel, new_thread);
#else
pid = __clone(pthread_start_thread, (void **) new_thread,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
@@ -643,6 +689,9 @@
- new_thread_bottom);
munmap((caddr_t)new_thread_bottom,
2 * stacksize + new_thread->p_guardsize);
+#elif _STACK_GROWS_UP
+ size_t stacksize = guardaddr - (char *)new_thread;
+ munmap(new_thread, stacksize + guardsize);
#else
size_t stacksize = (char *)(new_thread+1) - new_thread_bottom;
munmap(new_thread_bottom - guardsize, guardsize + stacksize);
@@ -708,6 +757,10 @@
size_t guardsize = th->p_guardsize;
/* Free the stack and thread descriptor area */
char *guardaddr = th->p_guardaddr;
+#ifdef _STACK_GROWS_UP
+ size_t stacksize = guardaddr - (char *)th;
+ guardaddr = (char *)th;
+#else
/* Guardaddr is always set, even if guardsize is 0. This allows
us to compute everything else. */
size_t stacksize = (char *)(th+1) - guardaddr - guardsize;
@@ -715,6 +768,7 @@
/* Take account of the register stack, which is below guardaddr. */
guardaddr -= stacksize;
stacksize *= 2;
+#endif
#endif
/* Unmap the stack. */
munmap(guardaddr, stacksize + guardsize);
diff -urNx CVS glibc-223/linuxthreads/pthread.c glibc-merge/linuxthreads/pthread.c
--- glibc-223/linuxthreads/pthread.c Tue Apr 24 14:10:57 2001
+++ glibc-merge/linuxthreads/pthread.c Thu May 17 10:52:10 2001
@@ -30,6 +30,7 @@
#include "internals.h"
#include "spinlock.h"
#include "restart.h"
+#include <stackinfo.h>
/* We need the global/static resolver state here. */
#include <resolv.h>
@@ -412,11 +413,17 @@
/* Test if compare-and-swap is available */
__pthread_has_cas = compare_and_swap_is_available();
#endif
+#ifdef _STACK_GROWS_UP
+ /* The initial thread already has all the stack it needs */
+ __pthread_initial_thread_bos = (char *)
+ ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1));
+#else
/* For the initial stack, reserve at least STACK_SIZE bytes of stack
below the current stack address, and align that on a
STACK_SIZE boundary. */
__pthread_initial_thread_bos =
(char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
+#endif
/* Update the descriptor for the initial thread. */
__pthread_initial_thread.p_pid = __getpid();
/* Likewise for the resolver state _res. */
@@ -544,6 +551,11 @@
THREAD_MANAGER_STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
+#elif _STACK_GROWS_UP
+ pid = __clone(__pthread_manager_event,
+ (void **) __pthread_manager_thread_bos,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+ (void *)(long)manager_pipe[0]);
#else
pid = __clone(__pthread_manager_event,
(void **) __pthread_manager_thread_tos,
@@ -580,6 +592,10 @@
THREAD_MANAGER_STACK_SIZE,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
(void *)(long)manager_pipe[0]);
+#elif _STACK_GROWS_UP
+ pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos,
+ CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
+ (void *)(long)manager_pipe[0]);
#else
pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos,
CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND,
More information about the Libc-alpha
mailing list