mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-06-22 12:14:52 +02:00
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
This commit is contained in:
parent
f1512917e6
commit
5bfb64d507
@ -51,7 +51,6 @@
|
|||||||
#include "gtestutils.h"
|
#include "gtestutils.h"
|
||||||
#include "gthread.h"
|
#include "gthread.h"
|
||||||
#include "glib_trace.h"
|
#include "glib_trace.h"
|
||||||
#include "glib-ctor.h"
|
|
||||||
|
|
||||||
/* the GSlice allocator is split up into 4 layers, roughly modelled after the slab
|
/* the GSlice allocator is split up into 4 layers, roughly modelled after the slab
|
||||||
* allocator and magazine extensions as outlined in:
|
* allocator and magazine extensions as outlined in:
|
||||||
@ -297,7 +296,8 @@ slice_config_init (SliceConfig *config)
|
|||||||
config->debug_blocks = TRUE;
|
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 */
|
/* we may not use g_error() or friends here */
|
||||||
mem_assert (sys_page_size == 0);
|
mem_assert (sys_page_size == 0);
|
||||||
@ -361,8 +361,6 @@ GLIB_CTOR (g_slice_init_nomessage)
|
|||||||
static inline guint
|
static inline guint
|
||||||
allocator_categorize (gsize aligned_chunk_size)
|
allocator_categorize (gsize aligned_chunk_size)
|
||||||
{
|
{
|
||||||
GLIB_ENSURE_CTOR (g_slice_init_nomessage);
|
|
||||||
|
|
||||||
/* speed up the likely path */
|
/* speed up the likely path */
|
||||||
if (G_LIKELY (aligned_chunk_size && aligned_chunk_size <= allocator->max_slab_chunk_size_for_magazine_cache))
|
if (G_LIKELY (aligned_chunk_size && aligned_chunk_size <= allocator->max_slab_chunk_size_for_magazine_cache))
|
||||||
return 1; /* use magazine cache */
|
return 1; /* use magazine cache */
|
||||||
@ -414,7 +412,15 @@ thread_memory_from_self (void)
|
|||||||
ThreadMemory *tmem = g_private_get (&private_thread_memory);
|
ThreadMemory *tmem = g_private_get (&private_thread_memory);
|
||||||
if (G_UNLIKELY (!tmem))
|
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 = g_malloc0 (sizeof (ThreadMemory) + sizeof (Magazine) * 2 * n_magazines);
|
||||||
tmem->magazine1 = (Magazine*) (tmem + 1);
|
tmem->magazine1 = (Magazine*) (tmem + 1);
|
||||||
tmem->magazine2 = &tmem->magazine1[n_magazines];
|
tmem->magazine2 = &tmem->magazine1[n_magazines];
|
||||||
@ -761,14 +767,23 @@ thread_memory_magazine2_free (ThreadMemory *tmem,
|
|||||||
gpointer
|
gpointer
|
||||||
g_slice_alloc (gsize mem_size)
|
g_slice_alloc (gsize mem_size)
|
||||||
{
|
{
|
||||||
|
ThreadMemory *tmem;
|
||||||
gsize chunk_size;
|
gsize chunk_size;
|
||||||
gpointer mem;
|
gpointer mem;
|
||||||
guint acat;
|
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);
|
chunk_size = P2ALIGN (mem_size);
|
||||||
acat = allocator_categorize (chunk_size);
|
acat = allocator_categorize (chunk_size);
|
||||||
if (G_LIKELY (acat == 1)) /* allocate through magazine layer */
|
if (G_LIKELY (acat == 1)) /* allocate through magazine layer */
|
||||||
{
|
{
|
||||||
ThreadMemory *tmem = thread_memory_from_self();
|
|
||||||
guint ix = SLAB_INDEX (allocator, chunk_size);
|
guint ix = SLAB_INDEX (allocator, chunk_size);
|
||||||
if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
|
if (G_UNLIKELY (thread_memory_magazine1_is_empty (tmem, ix)))
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user