]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl/descr.h
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl / descr.h
index 77251d5e45d97dcd3e1066d7a47cee53bc6e2d34..5bd12826494910d59f5ea47b2813857d91d87554 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2015 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
@@ -26,6 +25,7 @@
 #include <stdbool.h>
 #include <sys/types.h>
 #include <hp-timing.h>
+#define __need_list_t
 #include <list.h>
 #include <lowlevellock.h>
 #include <pthreaddef.h>
@@ -37,6 +37,7 @@
 #endif
 #define __need_res_state
 #include <resolv.h>
+#include <kernel-features.h>
 
 #ifndef TCB_ALIGNMENT
 # define TCB_ALIGNMENT sizeof (double)
@@ -97,8 +98,26 @@ struct pthread_unwind_buf
 struct xid_command
 {
   int syscall_no;
-  long id[3];
+  long int id[3];
   volatile int cntr;
+  volatile int error; /* -1: no call yet, 0: success seen, >0: error seen.  */
+};
+
+
+/* Data structure used by the kernel to find robust futexes.  */
+struct robust_list_head
+{
+  void *list;
+  long int futex_offset;
+  void *list_op_pending;
+};
+
+
+/* Data strcture used to handle thread priority protection.  */
+struct priority_protection_data
+{
+  int priomax;
+  unsigned int priomap[];
 };
 
 
@@ -113,7 +132,26 @@ 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;
+# ifndef __ASSUME_PRIVATE_FUTEX
+      int private_futex;
+# endif
     } header;
 #endif
 
@@ -121,7 +159,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.  */
@@ -134,6 +172,82 @@ struct pthread
   /* Process ID - thread group ID in kernel speak.  */
   pid_t pid;
 
+  /* List of robust mutexes the thread is holding.  */
+#ifdef __PTHREAD_MUTEX_HAVE_PREV
+  void *robust_prev;
+  struct robust_list_head robust_head;
+
+  /* The list above is strange.  It is basically a double linked list
+     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.  */
+# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next))
+
+# define ENQUEUE_MUTEX_BOTH(mutex, val)                                              \
+  do {                                                                       \
+    __pthread_list_t *next = (__pthread_list_t *)                            \
+      ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul)   \
+       - QUEUE_PTR_ADJUST);                                                  \
+    next->__prev = (void *) &mutex->__data.__list.__next;                    \
+    mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF,                \
+                                                robust_head.list);           \
+    mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head;        \
+    THREAD_SETMEM (THREAD_SELF, robust_head.list,                            \
+                  (void *) (((uintptr_t) &mutex->__data.__list.__next)       \
+                            | val));                                         \
+  } while (0)
+# define DEQUEUE_MUTEX(mutex) \
+  do {                                                                       \
+    __pthread_list_t *next = (__pthread_list_t *)                            \
+      ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul)           \
+       - QUEUE_PTR_ADJUST);                                                  \
+    next->__prev = mutex->__data.__list.__prev;                                      \
+    __pthread_list_t *prev = (__pthread_list_t *)                            \
+      ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul)           \
+       - QUEUE_PTR_ADJUST);                                                  \
+    prev->__next = mutex->__data.__list.__next;                                      \
+    mutex->__data.__list.__prev = NULL;                                              \
+    mutex->__data.__list.__next = NULL;                                              \
+  } while (0)
+#else
+  union
+  {
+    __pthread_slist_t robust_list;
+    struct robust_list_head robust_head;
+  };
+
+# define ENQUEUE_MUTEX_BOTH(mutex, val)                                              \
+  do {                                                                       \
+    mutex->__data.__list.__next                                                      \
+      = THREAD_GETMEM (THREAD_SELF, robust_list.__next);                     \
+    THREAD_SETMEM (THREAD_SELF, robust_list.__next,                          \
+                  (void *) (((uintptr_t) &mutex->__data.__list) | val));     \
+  } while (0)
+# define DEQUEUE_MUTEX(mutex) \
+  do {                                                                       \
+    __pthread_slist_t *runp = (__pthread_slist_t *)                          \
+      (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \
+    if (runp == &mutex->__data.__list)                                       \
+      THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next);         \
+    else                                                                     \
+      {                                                                              \
+       __pthread_slist_t *next = (__pthread_slist_t *)               \
+         (((uintptr_t) runp->__next) & ~1ul);                                \
+       while (next != &mutex->__data.__list)                                 \
+         {                                                                   \
+           runp = next;                                                      \
+           next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \
+         }                                                                   \
+                                                                             \
+       runp->__next = next->__next;                                          \
+       mutex->__data.__list.__next = NULL;                                   \
+      }                                                                              \
+  } while (0)
+#endif
+#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0)
+#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1)
+
   /* List of cleanup buffers.  */
   struct _pthread_cleanup_buffer *cleanup;
 
@@ -145,24 +259,27 @@ 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         (0x01 << SETXID_BIT)
   /* Mask for the rest.  Helps the compiler to optimize.  */
-#define CANCEL_RESTMASK                0xffffffc0
+#define CANCEL_RESTMASK                0xffffff80
 
 #define CANCEL_ENABLED_AND_CANCELED(value) \
   (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK              \
@@ -172,6 +289,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
@@ -185,12 +305,12 @@ struct pthread
     void *data;
   } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
 
-  /* Flag which is set when specific data is set.  */
-  bool specific_used;
-
   /* Two-level array for the thread-specific data.  */
   struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];
 
+  /* Flag which is set when specific data is set.  */
+  bool specific_used;
+
   /* True if events must be reported.  */
   bool report_events;
 
@@ -200,8 +320,15 @@ struct pthread
   /* True if thread must stop at startup time.  */
   bool stopped_start;
 
+  /* The parent's cancel handling at the time of the pthread_create
+     call.  This might be needed to undo the effects of a cancellation.  */
+  int parent_cancelhandling;
+
   /* Lock to synchronize access to the descriptor.  */
-  lll_lock_t lock;
+  int lock;
+
+  /* Lock for synchronizing setxid calls.  */
+  int setxid_futex;
 
 #if HP_TIMING_AVAIL
   /* Offset of the CPU clock at start thread start time.  */
@@ -218,9 +345,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;
 
@@ -252,15 +376,17 @@ struct pthread
   /* This is what the user specified and what we will report.  */
   size_t reported_guardsize;
 
+  /* Thread Priority Protection data.  */
+  struct priority_protection_data *tpp;
+
   /* Resolver state.  */
   struct __res_state res;
 
-  /* If you add fields after the res field above, please adjust
-     the following macro.  */
-#define PTHREAD_STRUCT_END_PADDING \
-  (sizeof (struct pthread) - offsetof (struct pthread, res) \
-   - sizeof (((struct pthread *) 0)->res))
+  /* This member must be last.  */
+  char end_padding[];
 
+#define PTHREAD_STRUCT_END_PADDING \
+  (sizeof (struct pthread) - offsetof (struct pthread, end_padding))
 } __attribute ((aligned (TCB_ALIGNMENT)));