]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl/descr.h
Refactor hp-timing rtld usage
[thirdparty/glibc.git] / nptl / descr.h
index b9b9ed7b98d84394b4e12ca0a41827e7fac74385..b4db99fe3fc1ca02a8329736978748c507386beb 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -13,9 +13,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #ifndef _DESCR_H
 #define _DESCR_H       1
 #include <stdbool.h>
 #include <sys/types.h>
 #include <hp-timing.h>
-#include <list.h>
+#include <list_t.h>
 #include <lowlevellock.h>
 #include <pthreaddef.h>
 #include <dl-sysdep.h>
-#include "../nptl_db/thread_db.h"
+#include <thread_db.h>
 #include <tls.h>
-#ifdef HAVE_FORCED_UNWIND
-# include <unwind.h>
-#endif
-#define __need_res_state
-#include <resolv.h>
+#include <unwind.h>
+#include <bits/types/res_state.h>
+#include <kernel-features.h>
 
 #ifndef TCB_ALIGNMENT
 # define TCB_ALIGNMENT sizeof (double)
@@ -99,6 +96,7 @@ struct xid_command
   int syscall_no;
   long int id[3];
   volatile int cntr;
+  volatile int error; /* -1: no call yet, 0: success seen, >0: error seen.  */
 };
 
 
@@ -130,7 +128,23 @@ struct pthread
 #else
     struct
     {
+      /* multiple_threads is enabled either when the process has spawned at
+        least one thread or when a single-threaded process cancels itself.
+        This enables additional code to introduce locking before doing some
+        compare_and_exchange operations and also enable cancellation points.
+        The concepts of multiple threads and cancellation points ideally
+        should be separate, since it is not necessary for multiple threads to
+        have been created for cancellation points to be enabled, as is the
+        case is when single-threaded process cancels itself.
+
+        Since enabling multiple_threads enables additional code in
+        cancellation points and compare_and_exchange operations, there is a
+        potential for an unneeded performance hit when it is enabled in a
+        single-threaded, self-canceling process.  This is OK though, since a
+        single-threaded process will enable async cancellation only when it
+        looks to cancel itself and is hence going to end anyway.  */
       int multiple_threads;
+      int gscope_flag;
     } header;
 #endif
 
@@ -138,7 +152,7 @@ struct pthread
        is private and subject to change without affecting the official ABI.
        We just have it here in case it might be convenient for some
        implementation-specific instrumentation hack or suchlike.  */
-    void *__padding[16];
+    void *__padding[24];
   };
 
   /* This descriptor's link on the `stack_used' or `__stack_user' list.  */
@@ -148,11 +162,11 @@ struct pthread
      therefore stack) used' flag.  */
   pid_t tid;
 
-  /* Process ID - thread group ID in kernel speak.  */
-  pid_t pid;
+  /* Ununsed.  */
+  pid_t pid_ununsed;
 
   /* List of robust mutexes the thread is holding.  */
-#ifdef __PTHREAD_MUTEX_HAVE_PREV
+#if __PTHREAD_MUTEX_HAVE_PREV
   void *robust_prev;
   struct robust_list_head robust_head;
 
@@ -160,7 +174,16 @@ struct pthread
      but the pointer to the next/previous element of the list points
      in the middle of the object, the __next element.  Whenever
      casting to __pthread_list_t we need to adjust the pointer
-     first.  */
+     first.
+     These operations are effectively concurrent code in that the thread
+     can get killed at any point in time and the kernel takes over.  Thus,
+     the __next elements are a kind of concurrent list and we need to
+     enforce using compiler barriers that the individual operations happen
+     in such a way that the kernel always sees a consistent list.  The
+     backward links (ie, the __prev elements) are not used by the kernel.
+     FIXME We should use relaxed MO atomic operations here and signal fences
+     because this kind of concurrency is similar to synchronizing with a
+     signal handler.  */
 # define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next))
 
 # define ENQUEUE_MUTEX_BOTH(mutex, val)                                              \
@@ -172,6 +195,8 @@ struct pthread
     mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF,                \
                                                 robust_head.list);           \
     mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head;        \
+    /* Ensure that the new list entry is ready before we insert it.  */              \
+    __asm ("" ::: "memory");                                                 \
     THREAD_SETMEM (THREAD_SELF, robust_head.list,                            \
                   (void *) (((uintptr_t) &mutex->__data.__list.__next)       \
                             | val));                                         \
@@ -186,6 +211,9 @@ struct pthread
       ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul)           \
        - QUEUE_PTR_ADJUST);                                                  \
     prev->__next = mutex->__data.__list.__next;                                      \
+    /* Ensure that we remove the entry from the list before we change the     \
+       __next pointer of the entry, which is read by the kernel.  */         \
+    __asm ("" ::: "memory");                                                 \
     mutex->__data.__list.__prev = NULL;                                              \
     mutex->__data.__list.__next = NULL;                                              \
   } while (0)
@@ -200,8 +228,10 @@ struct pthread
   do {                                                                       \
     mutex->__data.__list.__next                                                      \
       = THREAD_GETMEM (THREAD_SELF, robust_list.__next);                     \
+    /* Ensure that the new list entry is ready before we insert it.  */              \
+    __asm ("" ::: "memory");                                                 \
     THREAD_SETMEM (THREAD_SELF, robust_list.__next,                          \
-                  ((uintptr_t) &mutex->__data.__list) | val);                \
+                  (void *) (((uintptr_t) &mutex->__data.__list) | val));     \
   } while (0)
 # define DEQUEUE_MUTEX(mutex) \
   do {                                                                       \
@@ -220,6 +250,9 @@ struct pthread
          }                                                                   \
                                                                              \
        runp->__next = next->__next;                                          \
+       /* Ensure that we remove the entry from the list before we change the \
+          __next pointer of the entry, which is read by the kernel.  */      \
+           __asm ("" ::: "memory");                                          \
        mutex->__data.__list.__next = NULL;                                   \
       }                                                                              \
   } while (0)
@@ -238,25 +271,25 @@ struct pthread
   int cancelhandling;
   /* Bit set if cancellation is disabled.  */
 #define CANCELSTATE_BIT                0
-#define CANCELSTATE_BITMASK    0x01
+#define CANCELSTATE_BITMASK    (0x01 << CANCELSTATE_BIT)
   /* Bit set if asynchronous cancellation mode is selected.  */
 #define CANCELTYPE_BIT         1
-#define CANCELTYPE_BITMASK     0x02
+#define CANCELTYPE_BITMASK     (0x01 << CANCELTYPE_BIT)
   /* Bit set if canceling has been initiated.  */
 #define CANCELING_BIT          2
-#define CANCELING_BITMASK      0x04
+#define CANCELING_BITMASK      (0x01 << CANCELING_BIT)
   /* Bit set if canceled.  */
 #define CANCELED_BIT           3
-#define CANCELED_BITMASK       0x08
+#define CANCELED_BITMASK       (0x01 << CANCELED_BIT)
   /* Bit set if thread is exiting.  */
 #define EXITING_BIT            4
-#define EXITING_BITMASK                0x10
+#define EXITING_BITMASK                (0x01 << EXITING_BIT)
   /* Bit set if thread terminated and TCB is freed.  */
 #define TERMINATED_BIT         5
-#define TERMINATED_BITMASK     0x20
+#define TERMINATED_BITMASK     (0x01 << TERMINATED_BIT)
   /* Bit set if thread is supposed to change XID.  */
 #define SETXID_BIT             6
-#define SETXID_BITMASK         0x40
+#define SETXID_BITMASK         (0x01 << SETXID_BIT)
   /* Mask for the rest.  Helps the compiler to optimize.  */
 #define CANCEL_RESTMASK                0xffffff80
 
@@ -268,6 +301,9 @@ struct pthread
               | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK))     \
    == (CANCELTYPE_BITMASK | CANCELED_BITMASK))
 
+  /* Flags.  Including those copied from the thread attribute.  */
+  int flags;
+
   /* We allocate one block of references here.  This should be enough
      to avoid allocating any memory dynamically for most applications.  */
   struct pthread_key_data
@@ -301,14 +337,13 @@ struct pthread
   int parent_cancelhandling;
 
   /* Lock to synchronize access to the descriptor.  */
-  lll_lock_t lock;
+  int lock;
 
   /* Lock for synchronizing setxid calls.  */
-  lll_lock_t setxid_futex;
+  unsigned int setxid_futex;
 
-#if HP_TIMING_AVAIL
-  /* Offset of the CPU clock at start thread start time.  */
-  hp_timing_t cpuclock_offset;
+#if HP_TIMING_INLINE
+  hp_timing_t cpuclock_offset_ununsed;
 #endif
 
   /* If the thread waits to join another one the ID of the latter is
@@ -321,9 +356,6 @@ struct pthread
   /* Check whether a thread is detached.  */
 #define IS_DETACHED(pd) ((pd)->joinid == (pd))
 
-  /* Flags.  Including those copied from the thread attribute.  */
-  int flags;
-
   /* The result of the thread function.  */
   void *result;
 
@@ -341,14 +373,12 @@ struct pthread
   /* Next descriptor with a pending event.  */
   struct pthread *nextevent;
 
-#ifdef HAVE_FORCED_UNWIND
   /* Machine-specific unwind info.  */
   struct _Unwind_Exception exc;
-#endif
 
-  /* If nonzero pointer to area allocated for the stack and its
-     size.  */
+  /* If nonzero, pointer to the area allocated for the stack and guard. */
   void *stackblock;
+  /* Size of the stackblock area including the guard.  */
   size_t stackblock_size;
   /* Size of the included guard area.  */
   size_t guardsize;
@@ -361,6 +391,9 @@ struct pthread
   /* Resolver state.  */
   struct __res_state res;
 
+  /* Indicates whether is a C11 thread created by thrd_creat.  */
+  bool c11;
+
   /* This member must be last.  */
   char end_padding[];