Revert "libsysprof: parallelize capture symbolizing"

This reverts commit a7a0c782d1.
This commit is contained in:
Christian Hergert
2023-08-16 15:43:49 -07:00
parent 3b97252a8e
commit 48dc402c3b
7 changed files with 135 additions and 227 deletions

View File

@ -28,7 +28,6 @@
struct _SysprofAddressLayout struct _SysprofAddressLayout
{ {
GObject parent_instance; GObject parent_instance;
GRWLock rwlock;
GPtrArray *mmaps; GPtrArray *mmaps;
guint mmaps_dirty : 1; guint mmaps_dirty : 1;
}; };
@ -74,7 +73,6 @@ sysprof_address_layout_finalize (GObject *object)
SysprofAddressLayout *self = (SysprofAddressLayout *)object; SysprofAddressLayout *self = (SysprofAddressLayout *)object;
g_clear_pointer (&self->mmaps, g_ptr_array_unref); g_clear_pointer (&self->mmaps, g_ptr_array_unref);
g_rw_lock_clear (&self->rwlock);
G_OBJECT_CLASS (sysprof_address_layout_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_address_layout_parent_class)->finalize (object);
} }
@ -90,7 +88,6 @@ sysprof_address_layout_class_init (SysprofAddressLayoutClass *klass)
static void static void
sysprof_address_layout_init (SysprofAddressLayout *self) sysprof_address_layout_init (SysprofAddressLayout *self)
{ {
g_rw_lock_init (&self->rwlock);
self->mmaps = g_ptr_array_new_with_free_func (g_object_unref); self->mmaps = g_ptr_array_new_with_free_func (g_object_unref);
} }
@ -107,13 +104,9 @@ sysprof_address_layout_take (SysprofAddressLayout *self,
g_return_if_fail (SYSPROF_IS_ADDRESS_LAYOUT (self)); g_return_if_fail (SYSPROF_IS_ADDRESS_LAYOUT (self));
g_return_if_fail (SYSPROF_IS_DOCUMENT_MMAP (map)); g_return_if_fail (SYSPROF_IS_DOCUMENT_MMAP (map));
g_rw_lock_writer_lock (&self->rwlock);
g_ptr_array_add (self->mmaps, map); g_ptr_array_add (self->mmaps, map);
self->mmaps_dirty = TRUE; self->mmaps_dirty = TRUE;
g_rw_lock_writer_unlock (&self->rwlock);
} }
static int static int
@ -202,42 +195,26 @@ sysprof_address_layout_lookup (SysprofAddressLayout *self,
g_return_val_if_fail (SYSPROF_IS_ADDRESS_LAYOUT (self), NULL); g_return_val_if_fail (SYSPROF_IS_ADDRESS_LAYOUT (self), NULL);
g_rw_lock_reader_lock (&self->rwlock); if (self->mmaps_dirty)
while (self->mmaps_dirty)
{ {
g_autoptr(EggBitset) dups = NULL; g_autoptr(EggBitset) dups = NULL;
EggBitsetIter iter; EggBitsetIter iter;
guint old_len = self->mmaps->len;
guint i; guint i;
g_rw_lock_reader_unlock (&self->rwlock); self->mmaps_dirty = FALSE;
g_rw_lock_writer_lock (&self->rwlock);
if (self->mmaps_dirty) g_ptr_array_sort (self->mmaps, compare_mmaps);
dups = find_duplicates (self->mmaps);
if (egg_bitset_iter_init_last (&iter, dups, &i))
{ {
self->mmaps_dirty = FALSE; do
g_ptr_array_remove_index (self->mmaps, i);
g_ptr_array_sort (self->mmaps, compare_mmaps); while (egg_bitset_iter_previous (&iter, &i));
dups = find_duplicates (self->mmaps);
if (egg_bitset_iter_init_last (&iter, dups, &i))
{
do
g_ptr_array_remove_index (self->mmaps, i);
while (egg_bitset_iter_previous (&iter, &i));
}
/* We can't be monitored when we're in this path as the
* application cannot have gotten access yet. Ignore
* any sort of items changes.
*
* g_list_model_items_changed (G_LIST_MODEL (self),
* 0, old_len, self->mmaps->len);
*/
} }
g_rw_lock_writer_unlock (&self->rwlock); g_list_model_items_changed (G_LIST_MODEL (self), 0, old_len, self->mmaps->len);
g_rw_lock_reader_lock (&self->rwlock);
} }
ret = bsearch (&address, ret = bsearch (&address,
@ -246,7 +223,5 @@ sysprof_address_layout_lookup (SysprofAddressLayout *self,
sizeof (gpointer), sizeof (gpointer),
find_by_address); find_by_address);
g_rw_lock_reader_unlock (&self->rwlock);
return ret ? *ret : NULL; return ret ? *ret : NULL;
} }

View File

@ -22,8 +22,6 @@
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <libdex.h>
#include "sysprof-address-layout-private.h" #include "sysprof-address-layout-private.h"
#include "sysprof-document-private.h" #include "sysprof-document-private.h"
#include "sysprof-document-symbols-private.h" #include "sysprof-document-symbols-private.h"
@ -72,9 +70,6 @@ typedef struct _Symbolize
ProgressFunc progress_func; ProgressFunc progress_func;
gpointer progress_data; gpointer progress_data;
GDestroyNotify progress_data_destroy; GDestroyNotify progress_data_destroy;
guint n_partitions;
guint partition_seq;
guint progress;
} Symbolize; } Symbolize;
static void static void
@ -145,108 +140,41 @@ add_traceable (SysprofDocumentSymbols *self,
} }
} }
static DexFuture * static void
symbolize_fiber (gpointer user_data) sysprof_document_symbols_worker (GTask *task,
gpointer source_object,
gpointer task_data,
GCancellable *cancellable)
{ {
Symbolize *state = user_data; static const struct {
g_autoptr(GListModel) model = NULL; const char *name;
guint partition; guint value;
guint count; } context_switches[] = {
guint n_items; { "- - Hypervisor - -", SYSPROF_ADDRESS_CONTEXT_HYPERVISOR },
guint max; { "- - Kernel - -", SYSPROF_ADDRESS_CONTEXT_KERNEL },
{ "- - User - -", SYSPROF_ADDRESS_CONTEXT_USER },
{ "- - Guest - -", SYSPROF_ADDRESS_CONTEXT_GUEST },
{ "- - Guest Kernel - -", SYSPROF_ADDRESS_CONTEXT_GUEST_KERNEL },
{ "- - Guest User - -", SYSPROF_ADDRESS_CONTEXT_GUEST_USER },
};
g_autoptr(GRefString) context_switch = g_ref_string_new_intern ("Context Switch");
Symbolize *state = task_data;
EggBitsetIter iter;
EggBitset *bitset;
GListModel *model;
guint count = 0;
guint i;
g_assert (source_object == NULL);
g_assert (G_IS_TASK (task));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
g_assert (state != NULL); g_assert (state != NULL);
g_assert (SYSPROF_IS_DOCUMENT (state->document)); g_assert (SYSPROF_IS_DOCUMENT (state->document));
g_assert (SYSPROF_IS_SYMBOLIZER (state->symbolizer)); g_assert (SYSPROF_IS_SYMBOLIZER (state->symbolizer));
g_assert (SYSPROF_IS_DOCUMENT_SYMBOLS (state->symbols)); g_assert (SYSPROF_IS_DOCUMENT_SYMBOLS (state->symbols));
g_assert (state->n_partitions > 1);
if (SYSPROF_IS_NO_SYMBOLIZER (state->symbolizer)) bitset = _sysprof_document_traceables (state->document);
return dex_future_new_for_boolean (TRUE); model = G_LIST_MODEL (state->document);
model = sysprof_document_list_traceables (state->document);
n_items = g_list_model_get_n_items (model);
partition = g_atomic_int_add (&state->partition_seq, 1);
count = n_items / (state->n_partitions - 1);
max = MIN (n_items, (partition + 1) * count);
for (guint i = count * partition; i < max; i++)
{
g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (model, i);
int pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable));
SysprofProcessInfo *process_info = g_hash_table_lookup (state->pid_to_process_info, GINT_TO_POINTER (pid));
add_traceable (state->symbols,
state->strings,
process_info,
traceable,
state->symbolizer);
if (g_atomic_int_add (&state->progress, 1) % 100 == 0)
{
if (state->progress_func)
state->progress_func (state->progress / (double)n_items, _("Symbolizing stack traces"), state->progress_data);
}
}
return dex_future_new_for_boolean (TRUE);
}
static DexFuture *
handle_symbolize_result (DexFuture *completed,
gpointer user_data)
{
Symbolize *state = user_data;
if (dex_future_get_status (completed) == DEX_FUTURE_STATUS_REJECTED)
return NULL;
return dex_future_new_take_object (g_object_ref (state->symbols));
}
static const struct {
const char *name;
guint value;
} context_switches[] = {
{ "- - Hypervisor - -", SYSPROF_ADDRESS_CONTEXT_HYPERVISOR },
{ "- - Kernel - -", SYSPROF_ADDRESS_CONTEXT_KERNEL },
{ "- - User - -", SYSPROF_ADDRESS_CONTEXT_USER },
{ "- - Guest - -", SYSPROF_ADDRESS_CONTEXT_GUEST },
{ "- - Guest Kernel - -", SYSPROF_ADDRESS_CONTEXT_GUEST_KERNEL },
{ "- - Guest User - -", SYSPROF_ADDRESS_CONTEXT_GUEST_USER },
};
void
_sysprof_document_symbols_new (SysprofDocument *document,
SysprofStrings *strings,
SysprofSymbolizer *symbolizer,
GHashTable *pid_to_process_info,
ProgressFunc progress_func,
gpointer progress_data,
GDestroyNotify progress_data_destroy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GRefString) context_switch = g_ref_string_new_intern ("Context Switch");
g_autoptr(DexAsyncResult) result = NULL;
g_autoptr(GPtrArray) futures = NULL;
DexFuture *future;
Symbolize *state;
g_return_if_fail (SYSPROF_IS_DOCUMENT (document));
g_return_if_fail (SYSPROF_IS_SYMBOLIZER (symbolizer));
state = g_new0 (Symbolize, 1);
state->document = g_object_ref (document);
state->symbolizer = g_object_ref (symbolizer);
state->symbols = g_object_new (SYSPROF_TYPE_DOCUMENT_SYMBOLS, NULL);
state->strings = sysprof_strings_ref (strings);
state->pid_to_process_info = g_hash_table_ref (pid_to_process_info);
state->progress_func = progress_func;
state->progress_data = progress_data;
state->progress_data_destroy = progress_data_destroy;
state->n_partitions = MAX (1, g_get_num_processors () / 2) + 1;
/* Create static symbols for context switch use */ /* Create static symbols for context switch use */
for (guint cs = 0; cs < G_N_ELEMENTS (context_switches); cs++) for (guint cs = 0; cs < G_N_ELEMENTS (context_switches); cs++)
@ -265,36 +193,80 @@ _sysprof_document_symbols_new (SysprofDocument *document,
state->symbols->context_switches[context_switches[cs].value] = g_steal_pointer (&symbol); state->symbols->context_switches[context_switches[cs].value] = g_steal_pointer (&symbol);
} }
futures = g_ptr_array_new_with_free_func (dex_unref); /* Walk through the available traceables which need symbols extracted */
if (!SYSPROF_IS_NO_SYMBOLIZER (state->symbolizer) &&
for (guint i = 0; i < state->n_partitions; i++) egg_bitset_iter_init_first (&iter, bitset, &i))
{ {
DexScheduler *scheduler = dex_thread_pool_scheduler_get_default (); guint n_items = egg_bitset_get_size (bitset);
g_ptr_array_add (futures, do
dex_scheduler_spawn (scheduler, 0, {
symbolize_fiber, g_autoptr(SysprofDocumentTraceable) traceable = g_list_model_get_item (model, i);
state, int pid = sysprof_document_frame_get_pid (SYSPROF_DOCUMENT_FRAME (traceable));
NULL)); SysprofProcessInfo *process_info = g_hash_table_lookup (state->pid_to_process_info, GINT_TO_POINTER (pid));
add_traceable (state->symbols,
state->strings,
process_info,
traceable,
state->symbolizer);
count++;
if (state->progress_func != NULL && count % 100 == 0)
state->progress_func (count / (double)n_items, _("Symbolizing stack traces"), state->progress_data);
}
while (egg_bitset_iter_next (&iter, &i));
} }
future = dex_future_allv ((DexFuture **)futures->pdata, futures->len); g_task_return_pointer (task,
future = dex_future_finally (future, g_object_ref (state->symbols),
handle_symbolize_result, g_object_unref);
state, }
(GDestroyNotify)symbolize_free);
result = dex_async_result_new (NULL, cancellable, callback, user_data); void
dex_async_result_await (result, future); _sysprof_document_symbols_new (SysprofDocument *document,
SysprofStrings *strings,
SysprofSymbolizer *symbolizer,
GHashTable *pid_to_process_info,
ProgressFunc progress_func,
gpointer progress_data,
GDestroyNotify progress_data_destroy,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
g_autoptr(GTask) task = NULL;
Symbolize *state;
g_return_if_fail (SYSPROF_IS_DOCUMENT (document));
g_return_if_fail (SYSPROF_IS_SYMBOLIZER (symbolizer));
state = g_new0 (Symbolize, 1);
state->document = g_object_ref (document);
state->symbolizer = g_object_ref (symbolizer);
state->symbols = g_object_new (SYSPROF_TYPE_DOCUMENT_SYMBOLS, NULL);
state->strings = sysprof_strings_ref (strings);
state->pid_to_process_info = g_hash_table_ref (pid_to_process_info);
state->progress_func = progress_func;
state->progress_data = progress_data;
state->progress_data_destroy = progress_data_destroy;
task = g_task_new (NULL, cancellable, callback, user_data);
g_task_set_source_tag (task, _sysprof_document_symbols_new);
g_task_set_task_data (task, state, (GDestroyNotify)symbolize_free);
g_task_run_in_thread (task, sysprof_document_symbols_worker);
} }
SysprofDocumentSymbols * SysprofDocumentSymbols *
_sysprof_document_symbols_new_finish (GAsyncResult *result, _sysprof_document_symbols_new_finish (GAsyncResult *result,
GError **error) GError **error)
{ {
g_return_val_if_fail (DEX_IS_ASYNC_RESULT (result), NULL); g_return_val_if_fail (G_IS_TASK (result), NULL);
g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
g_return_val_if_fail (g_task_get_source_tag (G_TASK (result)) == _sysprof_document_symbols_new, NULL);
return dex_async_result_propagate_pointer (DEX_ASYNC_RESULT (result), error); return g_task_propagate_pointer (G_TASK (result), error);
} }
/** /**

View File

@ -33,10 +33,10 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (SysprofElfLoader, sysprof_elf_loader, SYSPROF, ELF_LOADER, GObject) G_DECLARE_FINAL_TYPE (SysprofElfLoader, sysprof_elf_loader, SYSPROF, ELF_LOADER, GObject)
SysprofElfLoader *sysprof_elf_loader_new (void); SysprofElfLoader *sysprof_elf_loader_new (void);
char **sysprof_elf_loader_dup_debug_dirs (SysprofElfLoader *self); const char * const *sysprof_elf_loader_get_debug_dirs (SysprofElfLoader *self);
void sysprof_elf_loader_set_debug_dirs (SysprofElfLoader *self, void sysprof_elf_loader_set_debug_dirs (SysprofElfLoader *self,
const char * const *debug_dirs); const char * const *debug_dirs);
char **sysprof_elf_loader_dup_external_debug_dirs (SysprofElfLoader *self); const char * const *sysprof_elf_loader_get_external_debug_dirs (SysprofElfLoader *self);
void sysprof_elf_loader_set_external_debug_dirs (SysprofElfLoader *self, void sysprof_elf_loader_set_external_debug_dirs (SysprofElfLoader *self,
const char * const *debug_dirs); const char * const *debug_dirs);
SysprofElf *sysprof_elf_loader_load (SysprofElfLoader *self, SysprofElf *sysprof_elf_loader_load (SysprofElfLoader *self,

View File

@ -32,7 +32,6 @@
struct _SysprofElfLoader struct _SysprofElfLoader
{ {
GObject parent_instance; GObject parent_instance;
GRecMutex mutex;
GHashTable *cache; GHashTable *cache;
char **debug_dirs; char **debug_dirs;
char **external_debug_dirs; char **external_debug_dirs;
@ -72,7 +71,6 @@ sysprof_elf_loader_finalize (GObject *object)
g_clear_pointer (&self->debug_dirs, g_strfreev); g_clear_pointer (&self->debug_dirs, g_strfreev);
g_clear_pointer (&self->external_debug_dirs, g_strfreev); g_clear_pointer (&self->external_debug_dirs, g_strfreev);
g_clear_pointer (&self->cache, g_hash_table_unref); g_clear_pointer (&self->cache, g_hash_table_unref);
g_rec_mutex_clear (&self->mutex);
G_OBJECT_CLASS (sysprof_elf_loader_parent_class)->finalize (object); G_OBJECT_CLASS (sysprof_elf_loader_parent_class)->finalize (object);
} }
@ -88,11 +86,11 @@ sysprof_elf_loader_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_DEBUG_DIRS: case PROP_DEBUG_DIRS:
g_value_take_boxed (value, sysprof_elf_loader_dup_debug_dirs (self)); g_value_set_boxed (value, sysprof_elf_loader_get_debug_dirs (self));
break; break;
case PROP_EXTERNAL_DEBUG_DIRS: case PROP_EXTERNAL_DEBUG_DIRS:
g_value_take_boxed (value, sysprof_elf_loader_dup_external_debug_dirs (self)); g_value_set_boxed (value, sysprof_elf_loader_get_external_debug_dirs (self));
break; break;
default: default:
@ -151,13 +149,12 @@ sysprof_elf_loader_class_init (SysprofElfLoaderClass *klass)
static void static void
sysprof_elf_loader_init (SysprofElfLoader *self) sysprof_elf_loader_init (SysprofElfLoader *self)
{ {
g_rec_mutex_init (&self->mutex);
self->debug_dirs = g_strdupv ((char **)DEFAULT_DEBUG_DIRS); self->debug_dirs = g_strdupv ((char **)DEFAULT_DEBUG_DIRS);
self->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _g_object_xunref); self->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, _g_object_xunref);
} }
/** /**
* sysprof_elf_loader_dup_debug_dirs: * sysprof_elf_loader_get_debug_dirs:
* @self: a #SysprofElfLoader * @self: a #SysprofElfLoader
* *
* Gets the #SysprofElfLoader:debug-dirs property. * Gets the #SysprofElfLoader:debug-dirs property.
@ -167,18 +164,12 @@ sysprof_elf_loader_init (SysprofElfLoader *self)
* *
* Returns: (nullable): an array of debug directories, or %NULL * Returns: (nullable): an array of debug directories, or %NULL
*/ */
char ** const char * const *
sysprof_elf_loader_dup_debug_dirs (SysprofElfLoader *self) sysprof_elf_loader_get_debug_dirs (SysprofElfLoader *self)
{ {
char **ret;
g_return_val_if_fail (SYSPROF_IS_ELF_LOADER (self), NULL); g_return_val_if_fail (SYSPROF_IS_ELF_LOADER (self), NULL);
g_rec_mutex_lock (&self->mutex); return (const char * const *)self->debug_dirs;
ret = g_strdupv (self->debug_dirs);
g_rec_mutex_unlock (&self->mutex);
return ret;
} }
/** /**
@ -206,14 +197,12 @@ sysprof_elf_loader_set_debug_dirs (SysprofElfLoader *self,
g_return_if_fail (SYSPROF_IS_ELF_LOADER (self)); g_return_if_fail (SYSPROF_IS_ELF_LOADER (self));
g_return_if_fail (self->debug_dirs != NULL); g_return_if_fail (self->debug_dirs != NULL);
g_rec_mutex_lock (&self->mutex);
if (sysprof_set_strv (&self->debug_dirs, debug_dirs)) if (sysprof_set_strv (&self->debug_dirs, debug_dirs))
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUG_DIRS]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_DEBUG_DIRS]);
g_rec_mutex_unlock (&self->mutex);
} }
/** /**
* sysprof_elf_loader_dup_external_debug_dirs: * sysprof_elf_loader_get_external_debug_dirs:
* @self: a #SysprofElfLoader * @self: a #SysprofElfLoader
* *
* Gets the #SysprofElfLoader:external-debug-dirs property. * Gets the #SysprofElfLoader:external-debug-dirs property.
@ -221,20 +210,14 @@ sysprof_elf_loader_set_debug_dirs (SysprofElfLoader *self,
* See sysprof_elf_loader_set_external_debug_dirs() for how this * See sysprof_elf_loader_set_external_debug_dirs() for how this
* property is used to locate ELF files. * property is used to locate ELF files.
* *
* Returns: (transfer full) (nullable): an array of external debug directories, or %NULL * Returns: (nullable): an array of external debug directories, or %NULL
*/ */
char ** const char * const *
sysprof_elf_loader_dup_external_debug_dirs (SysprofElfLoader *self) sysprof_elf_loader_get_external_debug_dirs (SysprofElfLoader *self)
{ {
char **ret;
g_return_val_if_fail (SYSPROF_IS_ELF_LOADER (self), NULL); g_return_val_if_fail (SYSPROF_IS_ELF_LOADER (self), NULL);
g_rec_mutex_lock (&self->mutex); return (const char * const *)self->external_debug_dirs;
ret = g_strdupv (self->external_debug_dirs);
g_rec_mutex_lock (&self->mutex);
return ret;
} }
/** /**
@ -260,10 +243,8 @@ sysprof_elf_loader_set_external_debug_dirs (SysprofElfLoader *self,
{ {
g_return_if_fail (SYSPROF_IS_ELF_LOADER (self)); g_return_if_fail (SYSPROF_IS_ELF_LOADER (self));
g_rec_mutex_lock (&self->mutex);
if (sysprof_set_strv (&self->external_debug_dirs, external_debug_dirs)) if (sysprof_set_strv (&self->external_debug_dirs, external_debug_dirs))
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EXTERNAL_DEBUG_DIRS]); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_EXTERNAL_DEBUG_DIRS]);
g_rec_mutex_unlock (&self->mutex);
} }
static char * static char *
@ -433,8 +414,6 @@ sysprof_elf_loader_load (SysprofElfLoader *self,
g_return_val_if_fail (SYSPROF_IS_ELF_LOADER (self), NULL); g_return_val_if_fail (SYSPROF_IS_ELF_LOADER (self), NULL);
g_return_val_if_fail (!mount_namespace || SYSPROF_IS_MOUNT_NAMESPACE (mount_namespace), NULL); g_return_val_if_fail (!mount_namespace || SYSPROF_IS_MOUNT_NAMESPACE (mount_namespace), NULL);
g_rec_mutex_lock (&self->mutex);
/* We must translate the file into a number of paths that may possibly /* We must translate the file into a number of paths that may possibly
* locate the file in the case that there are overlays in the mount * locate the file in the case that there are overlays in the mount
* namespace. Each of the paths could be in a lower overlay layer. * namespace. Each of the paths could be in a lower overlay layer.
@ -474,10 +453,7 @@ sysprof_elf_loader_load (SysprofElfLoader *self,
if (cached_elf != NULL) if (cached_elf != NULL)
{ {
if (sysprof_elf_matches (cached_elf, file_inode, build_id)) if (sysprof_elf_matches (cached_elf, file_inode, build_id))
{ return g_object_ref (cached_elf);
g_rec_mutex_unlock (&self->mutex);
return g_object_ref (cached_elf);
}
} }
continue; continue;
@ -510,15 +486,10 @@ sysprof_elf_loader_load (SysprofElfLoader *self,
} }
if (elf != NULL) if (elf != NULL)
{ return g_steal_pointer (&elf);
g_rec_mutex_unlock (&self->mutex);
return g_steal_pointer (&elf);
}
} }
failure: failure:
g_rec_mutex_unlock (&self->mutex);
g_set_error_literal (error, g_set_error_literal (error,
G_FILE_ERROR, G_FILE_ERROR,
G_FILE_ERROR_NOENT, G_FILE_ERROR_NOENT,

View File

@ -199,11 +199,11 @@ sysprof_elf_symbolizer_get_property (GObject *object,
switch (prop_id) switch (prop_id)
{ {
case PROP_DEBUG_DIRS: case PROP_DEBUG_DIRS:
g_value_take_boxed (value, sysprof_elf_symbolizer_dup_debug_dirs (self)); g_value_set_boxed (value, sysprof_elf_symbolizer_get_debug_dirs (self));
break; break;
case PROP_EXTERNAL_DEBUG_DIRS: case PROP_EXTERNAL_DEBUG_DIRS:
g_value_take_boxed (value, sysprof_elf_symbolizer_dup_external_debug_dirs (self)); g_value_set_boxed (value, sysprof_elf_symbolizer_get_external_debug_dirs (self));
break; break;
default: default:
@ -277,12 +277,12 @@ sysprof_elf_symbolizer_new (void)
return g_object_new (SYSPROF_TYPE_ELF_SYMBOLIZER, NULL); return g_object_new (SYSPROF_TYPE_ELF_SYMBOLIZER, NULL);
} }
char ** const char * const *
sysprof_elf_symbolizer_dup_debug_dirs (SysprofElfSymbolizer *self) sysprof_elf_symbolizer_get_debug_dirs (SysprofElfSymbolizer *self)
{ {
g_return_val_if_fail (SYSPROF_IS_ELF_SYMBOLIZER (self), NULL); g_return_val_if_fail (SYSPROF_IS_ELF_SYMBOLIZER (self), NULL);
return sysprof_elf_loader_dup_debug_dirs (self->loader); return sysprof_elf_loader_get_debug_dirs (self->loader);
} }
void void
@ -294,12 +294,12 @@ sysprof_elf_symbolizer_set_debug_dirs (SysprofElfSymbolizer *self,
sysprof_elf_loader_set_debug_dirs (self->loader, debug_dirs); sysprof_elf_loader_set_debug_dirs (self->loader, debug_dirs);
} }
char ** const char * const *
sysprof_elf_symbolizer_dup_external_debug_dirs (SysprofElfSymbolizer *self) sysprof_elf_symbolizer_get_external_debug_dirs (SysprofElfSymbolizer *self)
{ {
g_return_val_if_fail (SYSPROF_IS_ELF_SYMBOLIZER (self), NULL); g_return_val_if_fail (SYSPROF_IS_ELF_SYMBOLIZER (self), NULL);
return sysprof_elf_loader_dup_external_debug_dirs (self->loader); return sysprof_elf_loader_get_external_debug_dirs (self->loader);
} }
void void

View File

@ -37,12 +37,12 @@ GType sysprof_elf_symbolizer_get_type (void) G_GNUC
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofSymbolizer *sysprof_elf_symbolizer_new (void); SysprofSymbolizer *sysprof_elf_symbolizer_new (void);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
char **sysprof_elf_symbolizer_dup_debug_dirs (SysprofElfSymbolizer *self); const char * const *sysprof_elf_symbolizer_get_debug_dirs (SysprofElfSymbolizer *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_elf_symbolizer_set_debug_dirs (SysprofElfSymbolizer *self, void sysprof_elf_symbolizer_set_debug_dirs (SysprofElfSymbolizer *self,
const char * const *debug_dirs); const char * const *debug_dirs);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
char **sysprof_elf_symbolizer_dup_external_debug_dirs (SysprofElfSymbolizer *self); const char * const *sysprof_elf_symbolizer_get_external_debug_dirs (SysprofElfSymbolizer *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_elf_symbolizer_set_external_debug_dirs (SysprofElfSymbolizer *self, void sysprof_elf_symbolizer_set_external_debug_dirs (SysprofElfSymbolizer *self,
const char * const *external_debug_dirs); const char * const *external_debug_dirs);

View File

@ -24,7 +24,7 @@
struct _SysprofStrings struct _SysprofStrings
{ {
GRWLock rwlock; GMutex mutex;
GHashTable *hashtable; GHashTable *hashtable;
}; };
@ -34,7 +34,7 @@ sysprof_strings_new (void)
SysprofStrings *self; SysprofStrings *self;
self = g_atomic_rc_box_new0 (SysprofStrings); self = g_atomic_rc_box_new0 (SysprofStrings);
g_rw_lock_init (&self->rwlock); g_mutex_init (&self->mutex);
self->hashtable = g_hash_table_new_full (g_str_hash, self->hashtable = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
(GDestroyNotify)g_ref_string_release, (GDestroyNotify)g_ref_string_release,
@ -54,7 +54,7 @@ sysprof_strings_finalize (gpointer data)
{ {
SysprofStrings *self = data; SysprofStrings *self = data;
g_rw_lock_clear (&self->rwlock); g_mutex_clear (&self->mutex);
g_clear_pointer (&self->hashtable, g_hash_table_unref); g_clear_pointer (&self->hashtable, g_hash_table_unref);
} }
@ -73,24 +73,14 @@ sysprof_strings_get (SysprofStrings *self,
if (string == NULL) if (string == NULL)
return NULL; return NULL;
g_rw_lock_reader_lock (&self->rwlock); g_mutex_lock (&self->mutex);
if (!(ret = g_hash_table_lookup (self->hashtable, string))) if (!(ret = g_hash_table_lookup (self->hashtable, string)))
{ {
g_rw_lock_reader_unlock (&self->rwlock); ret = g_ref_string_new (string);
g_rw_lock_writer_lock (&self->rwlock); g_hash_table_insert (self->hashtable, ret, ret);
/* Check again, now with write lock */
if (!(ret = g_hash_table_lookup (self->hashtable, string)))
{
ret = g_ref_string_new (string);
g_hash_table_insert (self->hashtable, ret, ret);
}
g_rw_lock_writer_unlock (&self->rwlock);
return g_ref_string_acquire (ret);
} }
g_rw_lock_reader_unlock (&self->rwlock); g_ref_string_acquire (ret);
g_mutex_unlock (&self->mutex);
return g_ref_string_acquire (ret); return ret;
} }