[glib] gslice: stop using ctors



commit 5bfb64d50704f334ae6692184e53de6dbb2e6be4
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Oct 4 16:38:28 2011 -0400

    gslice: stop using ctors
    
    We can't initialise gslice from a ctor because g_slice_set_config() must
    be called before gslice initialisation.
    
    Instead, do the initialisation in a threadsafe way from the
    initialisation function for the thread private data.  This will only be
    called once per thread so the synchronisation doesn't pose a significant
    overhead here.
    
    Ensure that we try to grab the thread private data directly on entrance
    to g_slice_alloc() so that we force the initialisation to occur.
    Grabbing the private data is the common case anyway.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=660887

 glib/gslice.c |   27 +++++++++++++++++++++------
 1 files changed, 21 insertions(+), 6 deletions(-)
---
diff --git a/glib/gslice.c b/glib/gslice.c
index 75afdd2..2cd44f5 100644
--- a/glib/gslice.c
+++ b/glib/gslice.c
@@ -51,7 +51,6 @@
 #include "gtestutils.h"
 #include "gthread.h"
 #include "glib_trace.h"
-#include "glib-ctor.h"
 
 /* the GSlice allocator is split up into 4 layers, roughly modelled after the slab
  * allocator and magazine extensions as outlined in:
@@ -297,7 +296,8 @@ slice_config_init (SliceConfig *config)
     config->debug_blocks = TRUE;
 }
 
-GLIB_CTOR (g_slice_init_nomessage)
+static void
+g_slice_init_nomessage (void)
 {
   /* we may not use g_error() or friends here */
   mem_assert (sys_page_size == 0);
@@ -361,8 +361,6 @@ GLIB_CTOR (g_slice_init_nomessage)
 static inline guint
 allocator_categorize (gsize aligned_chunk_size)
 {
-  GLIB_ENSURE_CTOR (g_slice_init_nomessage);
-
   /* speed up the likely path */
   if (G_LIKELY (aligned_chunk_size && aligned_chunk_size <= allocator->max_slab_chunk_size_for_magazine_cache))
     return 1;           /* use magazine cache */
@@ -414,7 +412,15 @@ thread_memory_from_self (void)
   ThreadMemory *tmem = g_private_get (&private_thread_memory);
   if (G_UNLIKELY (!tmem))
     {
-      const guint n_magazines = MAX_SLAB_INDEX (allocator);
+      static GMutex init_mutex;
+      guint n_magazines;
+
+      g_mutex_lock (&init_mutex);
+      if G_UNLIKELY (sys_page_size == 0)
+        g_slice_init_nomessage ();
+      g_mutex_unlock (&init_mutex);
+
+      n_magazines = MAX_SLAB_INDEX (allocator);
       tmem = g_malloc0 (sizeof (ThreadMemory) + sizeof (Magazine) * 2 * n_magazines);
       tmem->magazine1 = (Magazine*) (tmem + 1);
       tmem->magazine2 = &tmem->magazine1[n_magazines];
@@ -761,14 +767,23 @@ thread_memory_magazine2_free (ThreadMemory *tmem,
 gpointer
 g_slice_alloc (gsize mem_size)
 {
+  ThreadMemory *tmem;
   gsize chunk_size;
   gpointer mem;
   guint acat;
+
+  /* This gets the private structure for this thread.  If the private
+   * structure does not yet exist, it is created.
+   *
+   * This has a side effect of causing GSlice to be initialised, so it
+   * must come first.
+   */
+  tmem = thread_memory_from_self ();
+
   chunk_size = P2ALIGN (mem_size);
   acat = allocator_categorize (chunk_size);
   if (G_LIKELY (acat == 1))     /* allocate through magazine layer */
     {
-      ThreadMemory *tmem = thread_memory_from_self();
       guint ix = SLAB_INDEX (allocator, chunk_size);
       if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
         {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]