]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
htl: Add support for static TSD data
authorSamuel Thibault <samuel.thibault@ens-lyon.org>
Tue, 8 Aug 2023 10:10:06 +0000 (12:10 +0200)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Tue, 8 Aug 2023 10:17:48 +0000 (12:17 +0200)
When using jemalloc, malloc() needs to use TSD, while libpthread
initialization needs malloc(). Supporting a static TSD area allows jemalloc
and libpthread to initialize together.

sysdeps/htl/pt-destroy-specific.c
sysdeps/htl/pt-getspecific.c
sysdeps/htl/pt-init-specific.c
sysdeps/htl/pt-key-create.c
sysdeps/htl/pt-key-delete.c
sysdeps/htl/pt-key.h
sysdeps/htl/pt-setspecific.c

index 7c1acb50682fc60c9eb7ef5210857e9e2a5788a3..6d1ad6baed651465d3d83bd5c66d056866e35e9c 100644 (file)
@@ -29,7 +29,16 @@ __pthread_destroy_specific (struct __pthread *thread)
 
   /* Check if there is any thread specific data.  */
   if (thread->thread_specifics == NULL)
-    return;
+    {
+      for (i = 0; i < PTHREAD_STATIC_KEYS; i++)
+       {
+         if (thread->static_thread_specifics[i] != NULL)
+           break;
+       }
+
+      if (i == PTHREAD_STATIC_KEYS)
+       return;
+    }
 
   __pthread_key_lock_ready ();
 
@@ -40,18 +49,32 @@ __pthread_destroy_specific (struct __pthread *thread)
 
       __pthread_mutex_lock (&__pthread_key_lock);
 
-      for (i = 0; i < __pthread_key_count && i < thread->thread_specifics_size;
-          i++)
+      for (i = 0; i < __pthread_key_count; i++)
        {
          void *value;
 
          if (__pthread_key_destructors[i] == PTHREAD_KEY_INVALID)
            continue;
 
-         value = thread->thread_specifics[i];
+         if (thread->thread_specifics == NULL)
+           {
+             if (i >= PTHREAD_STATIC_KEYS)
+               break;
+             value = thread->static_thread_specifics[i];
+           }
+         else
+           {
+             if (i >= thread->thread_specifics_size)
+               break;
+             value = thread->thread_specifics[i];
+           }
+
          if (value != NULL)
            {
-             thread->thread_specifics[i] = 0;
+             if (thread->thread_specifics == NULL)
+               thread->static_thread_specifics[i] = 0;
+             else
+               thread->thread_specifics[i] = 0;
 
              if (__pthread_key_destructors[i])
                {
@@ -74,4 +97,6 @@ __pthread_destroy_specific (struct __pthread *thread)
   free (thread->thread_specifics);
   thread->thread_specifics = 0;
   thread->thread_specifics_size = 0;
+  memset (&thread->static_thread_specifics, 0,
+         sizeof (thread->static_thread_specifics));
 }
index 68a2503563ab2262428fea626cc6fa03f72e0236..4d42cba93d4b0706529b32ba627106381d7decce 100644 (file)
@@ -29,6 +29,14 @@ __pthread_getspecific (pthread_key_t key)
     return NULL;
 
   self = _pthread_self ();
+
+  if (self->thread_specifics == NULL)
+    {
+      if (key >= PTHREAD_STATIC_KEYS)
+       return NULL;
+      return self->static_thread_specifics[key];
+    }
+
   if (key >= self->thread_specifics_size)
     return 0;
 
index 8c4d23cb13f58098e61ce5f938870562b5be7808..ed6c6f2d0cdb74e3d2cfabb42c4b3cd81f0148cf 100644 (file)
@@ -26,5 +26,7 @@ __pthread_init_specific (struct __pthread *thread)
 {
   thread->thread_specifics = 0;
   thread->thread_specifics_size = 0;
+  memset (&thread->static_thread_specifics, 0,
+         sizeof (thread->static_thread_specifics));
   return 0;
 }
index 51c0ef72b8759567ee13aeeba53d865b10b57439..b7057434e354c3f4615b168498cac4218739a2fd 100644 (file)
 pthread_mutex_t __pthread_key_lock;
 pthread_once_t __pthread_key_once = PTHREAD_ONCE_INIT;
 
-void (**__pthread_key_destructors) (void *arg);
-int __pthread_key_size;
+void (*__pthread_static_key_destructors [PTHREAD_STATIC_KEYS]) (void *arg);
+void (**__pthread_key_destructors) (void *arg) = __pthread_static_key_destructors;
+int __pthread_key_size = PTHREAD_STATIC_KEYS;
 int __pthread_key_count;
-int __pthread_key_invalid_count;
+int __pthread_key_invalid_count = PTHREAD_STATIC_KEYS;
 
 int
 __pthread_key_create (pthread_key_t *key, void (*destructor) (void *))
@@ -80,13 +81,21 @@ do_search:
        void *t;
        int newsize;
 
-       if (__pthread_key_size == 0)
-         newsize = 8;
+       newsize = __pthread_key_size * 2;
+
+       if (__pthread_key_destructors == __pthread_static_key_destructors)
+         {
+           /* We were still using the static array.  Switch to dynamic.  */
+           t = malloc (newsize * sizeof (*__pthread_key_destructors));
+
+           if (t != NULL)
+             memcpy (t, __pthread_key_destructors,
+                     __pthread_key_size * sizeof (*__pthread_key_destructors));
+         }
        else
-         newsize = __pthread_key_size * 2;
+         t = realloc (__pthread_key_destructors,
+                      newsize * sizeof (*__pthread_key_destructors));
 
-       t = realloc (__pthread_key_destructors,
-                    newsize * sizeof (*__pthread_key_destructors));
        if (t == NULL)
          {
            __pthread_mutex_unlock (&__pthread_key_lock);
index ce77a573c26a2ca1f04810c013a3840276c59b60..6d128d2aaf976bace8f645a725ca22d249d6b2c7 100644 (file)
@@ -51,8 +51,16 @@ __pthread_key_delete (pthread_key_t key)
 
          /* Just remove the key, no need to care whether it was
             already there. */
-         if (key < t->thread_specifics_size)
-           t->thread_specifics[key] = 0;
+         if (t->thread_specifics == NULL)
+           {
+             if (key < PTHREAD_STATIC_KEYS)
+               t->static_thread_specifics[key] = 0;
+           }
+         else
+           {
+             if (key < t->thread_specifics_size)
+               t->thread_specifics[key] = 0;
+           }
        }
       __libc_rwlock_unlock (GL (dl_pthread_threads_lock));
     }
index 262006de9f26e338c4e43cde448740d5bb8b28be..047b7e24ba4beb86c58f8f850274ef496d0c4ad3 100644 (file)
 #include <libc-lockP.h>
 #include <pthreadP.h>
 
+/* When using e.g. jemalloc, we need to be able to create and use keys before
+   being able to allocate.  */
+#define PTHREAD_STATIC_KEYS 4
+
 #define PTHREAD_KEY_MEMBERS \
   void **thread_specifics;             /* This is only resized by the thread, and always growing */ \
-  unsigned thread_specifics_size;      /* Number of entries in thread_specifics */
+  unsigned thread_specifics_size;      /* Number of entries in thread_specifics */ \
+  void *static_thread_specifics[PTHREAD_STATIC_KEYS];  /* Static storage for a few entries */
 
 #define PTHREAD_KEY_INVALID (void *) (-1)
 
index 2b9a89dc70aff40b1067de1720b7440be58a2c83..30550e09c7e5aebe940ff7f2fe4de948d2e83ff3 100644 (file)
@@ -28,12 +28,34 @@ __pthread_setspecific (pthread_key_t key, const void *value)
   if (key < 0 || key >= __pthread_key_count)
     return EINVAL;
 
+  if (self->thread_specifics == NULL)
+    {
+      if (key < PTHREAD_STATIC_KEYS)
+       {
+         self->static_thread_specifics[key] = (void *) value;
+         return 0;
+       }
+    }
+
   if (key >= self->thread_specifics_size)
     {
       /* Amortize reallocation cost.  */
       int newsize = 2 * key + 1;
-      void **new = realloc (self->thread_specifics,
-                           newsize * sizeof (new[0]));
+      void **new;
+
+      if (self->thread_specifics == NULL)
+       {
+         self->thread_specifics_size = PTHREAD_STATIC_KEYS;
+         new = malloc (newsize * sizeof (new[0]));
+         if (new != NULL)
+           memcpy (new, self->static_thread_specifics,
+                   PTHREAD_STATIC_KEYS * sizeof (new[0]));
+       }
+      else
+       {
+         new = realloc (self->thread_specifics,
+                        newsize * sizeof (new[0]));
+       }
       if (new == NULL)
        return ENOMEM;