From b449baa205e7ab7b06276bc83b1c759789fc607e Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Tue, 30 Jun 2020 16:43:48 +0100 Subject: [PATCH] libsysprof-capture: Move MappedRingBufferSource to libsysprof As preparation for dropping the GLib dependency from libsysprof-capture, move the `GSource` which links a `MappedRingBuffer` to a `GMainContext` from libsysprof-capture to libsysprof. This requires adding one new piece of API to libsysprof-capture to check whether the `MappedRingBuffer` is empty. Signed-off-by: Philip Withnall Helps: #40 --- src/libsysprof-capture/mapped-ring-buffer.c | 114 +++--------------- src/libsysprof-capture/mapped-ring-buffer.h | 11 +- src/libsysprof/mapped-ring-buffer-source.c | 121 ++++++++++++++++++++ src/libsysprof/mapped-ring-buffer-source.h | 47 ++++++++ src/libsysprof/meson.build | 1 + src/libsysprof/sysprof-control-source.c | 1 + 6 files changed, 189 insertions(+), 106 deletions(-) create mode 100644 src/libsysprof/mapped-ring-buffer-source.c create mode 100644 src/libsysprof/mapped-ring-buffer-source.h diff --git a/src/libsysprof-capture/mapped-ring-buffer.c b/src/libsysprof-capture/mapped-ring-buffer.c index 656845c2..ebc3ee93 100644 --- a/src/libsysprof-capture/mapped-ring-buffer.c +++ b/src/libsysprof-capture/mapped-ring-buffer.c @@ -530,107 +530,29 @@ mapped_ring_buffer_drain (MappedRingBuffer *self, return TRUE; } -typedef struct _MappedRingSource +/** + * mapped_ring_buffer_is_empty: + * @self: a #MappedRingBuffer + * + * Checks whether the ring buffer is currently empty. + * + * This should only be called by a reader created with + * mapped_ring_buffer_new_reader(). + * + * Returns: %TRUE if the buffer is empty, %FALSE otherwise + */ +gboolean +mapped_ring_buffer_is_empty (MappedRingBuffer *self) { - GSource source; - MappedRingBuffer *self; -} MappedRingSource; - -static gboolean -mapped_ring_source_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - MappedRingSource *real_source = (MappedRingSource *)source; - - g_assert (source != NULL); - - return mapped_ring_buffer_drain (real_source->self, - (MappedRingBufferCallback)callback, - user_data); -} - -static void -mapped_ring_source_finalize (GSource *source) -{ - MappedRingSource *real_source = (MappedRingSource *)source; - - if (real_source != NULL) - g_clear_pointer (&real_source->self, mapped_ring_buffer_unref); -} - -static gboolean -mapped_ring_source_check (GSource *source) -{ - MappedRingSource *real_source = (MappedRingSource *)source; MappedRingHeader *header; + guint32 headpos, tailpos; - g_assert (real_source != NULL); - g_assert (real_source->self != NULL); + header = get_header (self); - header = get_header (real_source->self); + headpos = g_atomic_int_get (&header->head); + tailpos = g_atomic_int_get (&header->tail); - if (g_atomic_int_get (&header->head) != g_atomic_int_get (&header->tail)) - return TRUE; - - return FALSE; -} - -static gboolean -mapped_ring_source_prepare (GSource *source, - gint *timeout_) -{ - MappedRingSource *real_source = (MappedRingSource *)source; - MappedRingHeader *header; - - g_assert (real_source != NULL); - g_assert (real_source->self != NULL); - - header = get_header (real_source->self); - - if (g_atomic_int_get (&header->head) != g_atomic_int_get (&header->tail)) - return TRUE; - - *timeout_ = 5; - - return FALSE; -} - -static GSourceFuncs mapped_ring_source_funcs = { - .prepare = mapped_ring_source_prepare, - .check = mapped_ring_source_check, - .dispatch = mapped_ring_source_dispatch, - .finalize = mapped_ring_source_finalize, -}; - -guint -mapped_ring_buffer_create_source_full (MappedRingBuffer *self, - MappedRingBufferCallback source_func, - gpointer user_data, - GDestroyNotify destroy) -{ - MappedRingSource *source; - guint ret; - - g_return_val_if_fail (self != NULL, 0); - g_return_val_if_fail (source_func != NULL, 0); - - source = (MappedRingSource *)g_source_new (&mapped_ring_source_funcs, sizeof (MappedRingSource)); - source->self = mapped_ring_buffer_ref (self); - g_source_set_callback ((GSource *)source, (GSourceFunc)source_func, user_data, destroy); - g_source_set_name ((GSource *)source, "MappedRingSource"); - ret = g_source_attach ((GSource *)source, g_main_context_default ()); - g_source_unref ((GSource *)source); - - return ret; -} - -guint -mapped_ring_buffer_create_source (MappedRingBuffer *self, - MappedRingBufferCallback source_func, - gpointer user_data) -{ - return mapped_ring_buffer_create_source_full (self, source_func, user_data, NULL); + return headpos == tailpos; } /** diff --git a/src/libsysprof-capture/mapped-ring-buffer.h b/src/libsysprof-capture/mapped-ring-buffer.h index 4eee6953..19740e17 100644 --- a/src/libsysprof-capture/mapped-ring-buffer.h +++ b/src/libsysprof-capture/mapped-ring-buffer.h @@ -78,15 +78,6 @@ gboolean mapped_ring_buffer_drain (MappedRingBuffer MappedRingBufferCallback callback, gpointer user_data); G_GNUC_INTERNAL -guint mapped_ring_buffer_create_source (MappedRingBuffer *self, - MappedRingBufferCallback callback, - gpointer user_data); -G_GNUC_INTERNAL -guint mapped_ring_buffer_create_source_full (MappedRingBuffer *self, - MappedRingBufferCallback callback, - gpointer user_data, - GDestroyNotify destroy); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MappedRingBuffer, mapped_ring_buffer_unref) +gboolean mapped_ring_buffer_is_empty (MappedRingBuffer *self); G_END_DECLS diff --git a/src/libsysprof/mapped-ring-buffer-source.c b/src/libsysprof/mapped-ring-buffer-source.c new file mode 100644 index 00000000..fdeb4b77 --- /dev/null +++ b/src/libsysprof/mapped-ring-buffer-source.c @@ -0,0 +1,121 @@ +/* mapped-ring-buffer-source.c + * + * Copyright 2020 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define G_LOG_DOMAIN "sysprof-mapped-ring-buffer-source" + +#include "config.h" + +#include + +#include "mapped-ring-buffer-source.h" + +typedef struct _MappedRingSource +{ + GSource source; + MappedRingBuffer *buffer; +} MappedRingSource; + +static gboolean +mapped_ring_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + MappedRingSource *real_source = (MappedRingSource *)source; + + g_assert (source != NULL); + + return mapped_ring_buffer_drain (real_source->buffer, + (MappedRingBufferCallback)callback, + user_data); +} + +static void +mapped_ring_source_finalize (GSource *source) +{ + MappedRingSource *real_source = (MappedRingSource *)source; + + if (real_source != NULL) + g_clear_pointer (&real_source->buffer, mapped_ring_buffer_unref); +} + +static gboolean +mapped_ring_source_check (GSource *source) +{ + MappedRingSource *real_source = (MappedRingSource *)source; + + g_assert (real_source != NULL); + g_assert (real_source->buffer != NULL); + + return !mapped_ring_buffer_is_empty (real_source->buffer); +} + +static gboolean +mapped_ring_source_prepare (GSource *source, + gint *timeout_) +{ + MappedRingSource *real_source = (MappedRingSource *)source; + + g_assert (real_source != NULL); + g_assert (real_source->buffer != NULL); + + if (!mapped_ring_buffer_is_empty (real_source->buffer)) + return TRUE; + + *timeout_ = 5; + + return FALSE; +} + +static GSourceFuncs mapped_ring_source_funcs = { + .prepare = mapped_ring_source_prepare, + .check = mapped_ring_source_check, + .dispatch = mapped_ring_source_dispatch, + .finalize = mapped_ring_source_finalize, +}; + +guint +mapped_ring_buffer_create_source_full (MappedRingBuffer *self, + MappedRingBufferCallback source_func, + gpointer user_data, + GDestroyNotify destroy) +{ + MappedRingSource *source; + guint ret; + + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (source_func != NULL, 0); + + source = (MappedRingSource *)g_source_new (&mapped_ring_source_funcs, sizeof (MappedRingSource)); + source->buffer = mapped_ring_buffer_ref (self); + g_source_set_callback ((GSource *)source, (GSourceFunc)source_func, user_data, destroy); + g_source_set_name ((GSource *)source, "MappedRingSource"); + ret = g_source_attach ((GSource *)source, g_main_context_default ()); + g_source_unref ((GSource *)source); + + return ret; +} + +guint +mapped_ring_buffer_create_source (MappedRingBuffer *self, + MappedRingBufferCallback source_func, + gpointer user_data) +{ + return mapped_ring_buffer_create_source_full (self, source_func, user_data, NULL); +} diff --git a/src/libsysprof/mapped-ring-buffer-source.h b/src/libsysprof/mapped-ring-buffer-source.h new file mode 100644 index 00000000..167f4c84 --- /dev/null +++ b/src/libsysprof/mapped-ring-buffer-source.h @@ -0,0 +1,47 @@ +/* mapped-ring-buffer-source.h + * + * Copyright 2020 Christian Hergert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#if !defined (SYSPROF_INSIDE) && !defined (SYSPROF_COMPILATION) +# error "Only can be included directly." +#endif + +#include + +#include "sysprof-version-macros.h" + +#include "mapped-ring-buffer.h" + +G_BEGIN_DECLS + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MappedRingBuffer, mapped_ring_buffer_unref) + +G_GNUC_INTERNAL +guint mapped_ring_buffer_create_source (MappedRingBuffer *self, + MappedRingBufferCallback callback, + gpointer user_data); +G_GNUC_INTERNAL +guint mapped_ring_buffer_create_source_full (MappedRingBuffer *self, + MappedRingBufferCallback callback, + gpointer user_data, + GDestroyNotify destroy); + +G_END_DECLS diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build index e2df0b8c..cc5f96ff 100644 --- a/src/libsysprof/meson.build +++ b/src/libsysprof/meson.build @@ -72,6 +72,7 @@ libsysprof_private_sources = [ 'binfile.c', 'demangle.cpp', 'elfparser.c', + 'mapped-ring-buffer-source.c', 'sysprof-flatpak.c', 'sysprof-helpers.c', 'sysprof-kallsyms.c', diff --git a/src/libsysprof/sysprof-control-source.c b/src/libsysprof/sysprof-control-source.c index 4ccdc482..fdf8f504 100644 --- a/src/libsysprof/sysprof-control-source.c +++ b/src/libsysprof/sysprof-control-source.c @@ -33,6 +33,7 @@ #include #include "mapped-ring-buffer.h" +#include "mapped-ring-buffer-source.h" #include "sysprof-control-source.h"