2003-03-11 Jakub Jelinek <jakub@redhat.com>
authorroland <roland>
Tue, 11 Mar 2003 09:20:36 +0000 (09:20 +0000)
committerroland <roland>
Tue, 11 Mar 2003 09:20:36 +0000 (09:20 +0000)
* sysdeps/pthread/createthread.c (ARCH_CLONE): Define if not defined.
(create_thread): Only assert PD->tcb != NULL under [TLS_TCB_AT_TP].
Use ARCH_CLONE.
* allocatestack.c (ALLOCATE_STACK_PARMS): New macro.
[NEED_SEPARATE_REGISTER_STACK] (STACK_VARIABLES,
STACK_VARIABLES_ARGS, STACK_VARIABLES_PARMS, ALLOCATE_STACK_PARMS,
ALLOCATE_STACK): New macros.
(TLS_TPADJ): New macro.
(get_cached_stack, queue_stack, __deallocate_stack): Use TLS_TPADJ.
(allocate_stack): Handle TLS_DTV_AT_TP and
NEED_SEPARATE_REGISTER_STACK.  Use TLS_TPADJ.
* pthread_create.c (__pthread_create_2_1) [! TLS_TCB_AT_TP]:
Don't set PD->self.
* init.c [__ia64__] (__NR_set_tid_address): Define.

nptl/allocatestack.c
nptl/init.c
nptl/pthread_create.c
nptl/sysdeps/pthread/createthread.c

index 3c9d54f..75e27d9 100644 (file)
@@ -29,6 +29,7 @@
 
 
 
+#ifndef NEED_SEPARATE_REGISTER_STACK
 
 /* Most architectures have exactly one stack pointer.  Some have more.  */
 #define STACK_VARIABLES void *stackaddr
 /* How to declare function which gets there parameters.  */
 #define STACK_VARIABLES_PARMS void *stackaddr
 
+/* How to declare allocate_stack.  */
+#define ALLOCATE_STACK_PARMS void **stack
+
+/* This is how the function is called.  We do it this way to allow
+   other variants of the function to have more parameters.  */
+#define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
+
+#else
+
+#define STACK_VARIABLES void *stackaddr; size_t stacksize
+#define STACK_VARIABLES_ARGS stackaddr, stacksize
+#define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize
+#define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize
+#define ALLOCATE_STACK(attr, pd) \
+  allocate_stack (attr, pd, &stackaddr, &stacksize)
+
+#endif
+
 
 /* Default alignment of stack.  */
 #ifndef STACK_ALIGN
 # define ARCH_MAP_FLAGS 0
 #endif
 
+/* This yields the pointer that TLS support code calls the thread pointer.  */
+#if TLS_TCB_AT_TP
+# define TLS_TPADJ(pd) (pd)
+#elif TLS_DTV_AT_TP
+# define TLS_TPADJ(pd) ((pd) + 1)
+#endif
 
 /* Cache handling for not-yet free stacks.  */
 
@@ -162,11 +187,13 @@ get_cached_stack (size_t *sizep, void **memp)
   result->nextevent = NULL;
 
   /* Clear the DTV.  */
-  dtv_t *dtv = GET_DTV (result);
+  dtv_t *dtv = GET_DTV (TLS_TPADJ (result));
   memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
 
   /* Re-initialize the TLS.  */
-  return _dl_allocate_tls_init (result);
+  _dl_allocate_tls_init (TLS_TPADJ (result));
+
+  return result;
 }
 
 
@@ -203,7 +230,7 @@ queue_stack (struct pthread *stack)
              stack_cache_actsize -= curr->stackblock_size;
 
              /* Free the memory associated with the ELF TLS.  */
-             _dl_deallocate_tls (curr, false);
+             _dl_deallocate_tls (TLS_TPADJ (curr), false);
 
              /* Remove this block.  This should never fail.  If it
                 does something is really wrong.  */
@@ -222,11 +249,12 @@ queue_stack (struct pthread *stack)
 
 static int
 allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
-               void **stack)
+               ALLOCATE_STACK_PARMS)
 {
   struct pthread *pd;
   size_t size;
   size_t pagesize_m1 = __getpagesize () - 1;
+  void *stacktop;
 
   assert (attr != NULL);
   assert (powerof2 (pagesize_m1 + 1));
@@ -248,15 +276,27 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
        return EINVAL;
 
       /* Adjust stack size for alignment of the TLS block.  */
-      adj = ((uintptr_t) attr->stackaddr) & __static_tls_align_m1;
+#if TLS_TCB_AT_TP
+      adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
+           & __static_tls_align_m1;
+      assert (size > adj + TLS_TCB_SIZE);
+#elif TLS_DTV_AT_TP
+      adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
+           & __static_tls_align_m1;
       assert (size > adj);
+#endif
 
       /* The user provided some memory.  Let's hope it matches the
         size...  We do not allocate guard pages if the user provided
         the stack.  It is the user's responsibility to do this if it
         is wanted.  */
-      pd = (struct pthread *) (((uintptr_t) attr->stackaddr - adj)
-                              & ~(__alignof (struct pthread) - 1)) - 1;
+#if TLS_TCB_AT_TP
+      pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+                              - TLS_TCB_SIZE - adj);
+#elif TLS_DTV_AT_TP
+      pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+                              - __static_tls_size - adj) - 1;
+#endif
 
       /* The user provided stack memory needs to be cleared.  */
       memset (pd, '\0', sizeof (struct pthread));
@@ -290,7 +330,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 #endif
 
       /* Allocate the DTV for this thread.  */
-      if (_dl_allocate_tls (pd) == NULL)
+      if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
        /* Something went wrong.  */
        return errno;
 
@@ -371,7 +411,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 #endif
 
          /* Place the thread descriptor at the end of the stack.  */
+#if TLS_TCB_AT_TP
          pd = (struct pthread *) ((char *) mem + size - coloring) - 1;
+#elif TLS_DTV_AT_TP
+         pd = (struct pthread *) (((uintptr_t) mem + size - coloring
+                                   - __static_tls_size)
+                                  & ~__static_tls_align_m1) - 1;
+#endif
 
          /* Remember the stack-related values.  */
          pd->stackblock = mem;
@@ -400,7 +446,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 #endif
 
          /* Allocate the DTV for this thread.  */
-         if (_dl_allocate_tls (pd) == NULL)
+         if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL)
            {
              /* Something went wrong.  */
              int err = errno;
@@ -432,7 +478,12 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
       /* Create or resize the guard area if necessary.  */
       if (__builtin_expect (guardsize > pd->guardsize, 0))
        {
-         if (mprotect (mem, guardsize, PROT_NONE) != 0)
+#ifdef NEED_SEPARATE_REGISTER_STACK
+         char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
+#else
+         char *guard = mem;
+#endif
+         if (mprotect (guard, guardsize, PROT_NONE) != 0)
            {
              int err;
            mprot_error:
@@ -446,7 +497,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
              lll_unlock (stack_cache_lock);
 
              /* Get rid of the TLS block we allocated.  */
-             _dl_deallocate_tls (pd, false);
+             _dl_deallocate_tls (TLS_TPADJ (pd), false);
 
              /* Free the stack memory regardless of whether the size
                 of the cache is over the limit or not.  If this piece
@@ -464,9 +515,25 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
                                 0))
        {
          /* The old guard area is too large.  */
+
+#ifdef NEED_SEPARATE_REGISTER_STACK
+         char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
+         char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1);
+
+         if (oldguard < guard
+             && mprotect (oldguard, guard - oldguard,
+                          PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+           goto mprot_error;
+
+         if (mprotect (guard + guardsize,
+                       oldguard + pd->guardsize - guard - guardsize,
+                       PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+           goto mprot_error;
+#else
          if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
                        PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
            goto mprot_error;
+#endif
 
          pd->guardsize = guardsize;
        }
@@ -477,18 +544,21 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 
 #if TLS_TCB_AT_TP
   /* The stack begins before the TCB and the static TLS block.  */
-  *stack = ((char *) (pd + 1) - __static_tls_size);
+  stacktop = ((char *) (pd + 1) - __static_tls_size);
+#elif TLS_DTV_AT_TP
+  stacktop = (char *) (pd - 1);
+#endif
+
+#ifdef NEED_SEPARATE_REGISTER_STACK
+  *stack = pd->stackblock;
+  *stacksize = stacktop - *stack;
 #else
-# error "Implement me"
+  *stack = stacktop;
 #endif
 
   return 0;
 }
 
-/* This is how the function is called.  We do it this way to allow
-   other variants of the function to have more parameters.  */
-#define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr)
-
 
 void
 internal_function
@@ -508,7 +578,7 @@ __deallocate_stack (struct pthread *pd)
     (void) queue_stack (pd);
   else
     /* Free the memory associated with the ELF TLS.  */
-    _dl_deallocate_tls (pd, false);
+    _dl_deallocate_tls (TLS_TPADJ (pd), false);
 
   lll_unlock (stack_cache_lock);
 }
index e0100ee..df8e67a 100644 (file)
@@ -37,6 +37,8 @@
    having the definition remove these lines.  */
 #if defined __s390__
 # define __NR_set_tid_address  252
+#elif defined __ia64__
+# define __NR_set_tid_address  1233
 #else
 # define __NR_set_tid_address  258
 #endif
index c1da67d..58116f7 100644 (file)
@@ -344,10 +344,10 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
      performed in 'get_cached_stack'.  This way we avoid doing this if
      the stack freshly allocated with 'mmap'.  */
 
+#ifdef TLS_TCB_AT_TP
   /* Reference to the TCB itself.  */
   pd->self = pd;
 
-#ifdef TLS_TCB_AT_TP
   /* Self-reference for TLS.  */
   pd->tcb = pd;
 #endif
index 2fac2d1..0223fa8 100644 (file)
 # define TLS_VALUE pd
 #endif
 
+#ifndef ARCH_CLONE
+# define ARCH_CLONE __clone
+#endif
+
 
 static int
 create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
@@ -42,8 +46,9 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
   PREPARE_CREATE;
 #endif
 
+#ifdef TLS_TCB_AT_TP
   assert (pd->tcb != NULL);
-
+#endif
 
   if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
     {
@@ -62,11 +67,11 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
          lll_lock (pd->lock);
 
          /* Create the thread.  */
-         if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
-                      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
-                      CLONE_SETTLS | CLONE_PARENT_SETTID |
-                      CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
-                      pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+         if (ARCH_CLONE (start_thread_debug, STACK_VARIABLES_ARGS,
+                         CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+                         CLONE_SETTLS | CLONE_PARENT_SETTID |
+                         CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
+                         pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
            /* Failed.  */
            return errno;
 
@@ -135,10 +140,10 @@ create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
 
      The termination signal is chosen to be zero which means no signal
      is sent.  */
-  if (__clone (start_thread, STACK_VARIABLES_ARGS,
-              CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
-              CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
-              CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+  if (ARCH_CLONE (start_thread, STACK_VARIABLES_ARGS,
+                 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+                 CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+                 CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
     /* Failed.  */
     return errno;