diff --git a/examples/app.c b/examples/app.c index c2544cb1..abb45aa6 100644 --- a/examples/app.c +++ b/examples/app.c @@ -11,6 +11,7 @@ # include #endif +#include #include #include #include diff --git a/examples/meson.build b/examples/meson.build index 124ac241..71a036a4 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -1,3 +1,3 @@ app = executable('example-app', 'app.c', - dependencies: [libsysprof_capture_dep], + dependencies: [dependency('glib-2.0'), libsysprof_capture_dep], ) diff --git a/meson.build b/meson.build index d9f032dc..6550126a 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,7 @@ gnome = import('gnome') pkgconfig = import('pkgconfig') i18n = import('i18n') -libsysprof_api_version = 3 +libsysprof_api_version = 4 version_split = meson.project_version().split('.') datadir = get_option('datadir') datadir_for_pc_file = join_paths('${prefix}', datadir) @@ -91,6 +91,8 @@ if cc.has_header('execinfo.h') config_h.set10('HAVE_EXECINFO_H', true) endif +config_h.set('HAVE_STRLCPY', cc.has_function('strlcpy')) + if get_option('libunwind') libunwind_dep = dependency('libunwind-generic', required: false) if libunwind_dep.found() diff --git a/src/libsysprof-capture/mapped-ring-buffer.c b/src/libsysprof-capture/mapped-ring-buffer.c index 656845c2..b7b56796 100644 --- a/src/libsysprof-capture/mapped-ring-buffer.c +++ b/src/libsysprof-capture/mapped-ring-buffer.c @@ -18,21 +18,23 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -#define G_LOG_DOMAIN "mapped-ring-buffer" - #include "config.h" +#include +#include +#include #include #include #include #include "sysprof-capture-util-private.h" +#include "sysprof-macros-internal.h" #include "sysprof-platform.h" #include "mapped-ring-buffer.h" #define DEFAULT_N_PAGES 32 -#define BUFFER_MAX_SIZE ((G_MAXUINT32/2)-_sysprof_getpagesize()) +#define BUFFER_MAX_SIZE ((UINT32_MAX/2)-_sysprof_getpagesize()) enum { MODE_READER = 1, @@ -47,13 +49,13 @@ enum { */ typedef struct _MappedRingHeader { - guint32 head; - guint32 tail; - guint32 offset; - guint32 size; + uint32_t head; + uint32_t tail; + uint32_t offset; + uint32_t size; } MappedRingHeader; -G_STATIC_ASSERT (sizeof (MappedRingHeader) == 16); +static_assert (sizeof (MappedRingHeader) == 16, "MappedRingHeader changed size"); /* * MappedRingBuffer is used to wrap both the reader and writer @@ -61,12 +63,12 @@ G_STATIC_ASSERT (sizeof (MappedRingHeader) == 16); */ struct _MappedRingBuffer { - volatile gint ref_count; + volatile int ref_count; int mode; int fd; void *map; - gsize body_size; - gsize page_size; + size_t body_size; + size_t page_size; }; static inline MappedRingHeader * @@ -75,19 +77,19 @@ get_header (MappedRingBuffer *self) return (MappedRingHeader *)self->map; } -static inline gpointer +static inline void * get_body_at_pos (MappedRingBuffer *self, - gsize pos) + size_t pos) { - g_assert (pos < (self->body_size + self->body_size)); + assert (pos < (self->body_size + self->body_size)); - return (guint8 *)self->map + self->page_size + pos; + return (uint8_t *)self->map + self->page_size + pos; } -static gpointer -map_head_and_body_twice (int fd, - gsize head_size, - gsize body_size) +static void * +map_head_and_body_twice (int fd, + size_t head_size, + size_t body_size) { void *map; void *second; @@ -118,7 +120,7 @@ map_head_and_body_twice (int fd, * By mmap()'ing over the old region, the previous region is automatically * munmap()'d for us. */ - second = mmap ((guint8 *)map + head_size + body_size, + second = mmap ((uint8_t *)map + head_size + body_size, body_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, @@ -131,7 +133,7 @@ map_head_and_body_twice (int fd, return NULL; } - g_assert (second == (gpointer)((guint8 *)map + head_size + body_size)); + assert (second == (void *)((uint8_t *)map + head_size + body_size)); return map; } @@ -157,16 +159,16 @@ map_head_and_body_twice (int fd, * Returns: (transfer full): a #MappedRingBuffer */ MappedRingBuffer * -mapped_ring_buffer_new_reader (gsize buffer_size) +mapped_ring_buffer_new_reader (size_t buffer_size) { MappedRingBuffer *self; MappedRingHeader *header; - gsize page_size; + size_t page_size; void *map; int fd; - g_return_val_if_fail ((buffer_size % _sysprof_getpagesize ()) == 0, NULL); - g_return_val_if_fail (buffer_size < BUFFER_MAX_SIZE, NULL); + assert ((buffer_size % _sysprof_getpagesize ()) == 0); + assert (buffer_size < BUFFER_MAX_SIZE); page_size = _sysprof_getpagesize (); @@ -200,7 +202,10 @@ mapped_ring_buffer_new_reader (gsize buffer_size) header->offset = page_size; header->size = buffer_size - page_size; - self = g_slice_new0 (MappedRingBuffer); + self = sysprof_malloc0 (sizeof (MappedRingBuffer)); + if (self == NULL) + return NULL; + self->ref_count = 1; self->mode = MODE_READER; self->body_size = buffer_size - page_size; @@ -208,11 +213,11 @@ mapped_ring_buffer_new_reader (gsize buffer_size) self->map = map; self->page_size = page_size; - return g_steal_pointer (&self); + return sysprof_steal_pointer (&self); } MappedRingBuffer * -mapped_ring_buffer_new_readwrite (gsize buffer_size) +mapped_ring_buffer_new_readwrite (size_t buffer_size) { MappedRingBuffer *self; @@ -234,50 +239,50 @@ mapped_ring_buffer_new_readwrite (gsize buffer_size) * Returns: (transfer full) (nullable): a new #MappedRingBuffer */ MappedRingBuffer * -mapped_ring_buffer_new_writer (gint fd) +mapped_ring_buffer_new_writer (int fd) { MappedRingBuffer *self; MappedRingHeader *header; - gssize buffer_size; - gsize page_size; + ssize_t buffer_size; + size_t page_size; void *map; - g_return_val_if_fail (fd > -1, NULL); + assert (fd > -1); page_size = _sysprof_getpagesize (); /* Make our own copy of the FD */ if ((fd = dup (fd)) < 0) { - g_printerr ("Failed to dup() fd, cannot continue\n"); + fprintf (stderr, "Failed to dup() fd, cannot continue\n"); return NULL; } /* Seek to end to get buffer size */ if ((buffer_size = lseek (fd, 0, SEEK_END)) < 0) { - g_printerr ("Failed to seek to end of file. Cannot determine buffer size.\n"); + fprintf (stderr, "Failed to seek to end of file. Cannot determine buffer size.\n"); return NULL; } /* Ensure non-zero sized buffer */ if (buffer_size < (page_size + page_size)) { - g_printerr ("Buffer is too small, cannot continue.\n"); + fprintf (stderr, "Buffer is too small, cannot continue.\n"); return NULL; } /* Make sure it is less than our max size */ if ((buffer_size - page_size) > BUFFER_MAX_SIZE) { - g_printerr ("Buffer is too large, cannot continue.\n"); + fprintf (stderr, "Buffer is too large, cannot continue.\n"); return NULL; } /* Ensure we have page-aligned buffer */ if ((buffer_size % page_size) != 0) { - g_printerr ("Invalid buffer size, not page aligned.\n"); + fprintf (stderr, "Invalid buffer size, not page aligned.\n"); return NULL; } @@ -298,7 +303,14 @@ mapped_ring_buffer_new_writer (gint fd) return NULL; } - self = g_slice_new0 (MappedRingBuffer); + self = sysprof_malloc0 (sizeof (MappedRingBuffer)); + if (self == NULL) + { + munmap (map, page_size + ((buffer_size - page_size) * 2)); + close (fd); + return NULL; + } + self->ref_count = 1; self->mode = MODE_WRITER; self->fd = fd; @@ -306,7 +318,7 @@ mapped_ring_buffer_new_writer (gint fd) self->map = map; self->page_size = page_size; - return g_steal_pointer (&self); + return sysprof_steal_pointer (&self); } static void @@ -328,28 +340,28 @@ mapped_ring_buffer_finalize (MappedRingBuffer *self) void mapped_ring_buffer_unref (MappedRingBuffer *self) { - g_return_if_fail (self != NULL); - g_return_if_fail (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - if (g_atomic_int_dec_and_test (&self->ref_count)) + if (__atomic_fetch_sub (&self->ref_count, 1, __ATOMIC_SEQ_CST) == 1) mapped_ring_buffer_finalize (self); } MappedRingBuffer * mapped_ring_buffer_ref (MappedRingBuffer *self) { - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (self->ref_count > 0, NULL); + assert (self != NULL); + assert (self->ref_count > 0); - g_atomic_int_inc (&self->ref_count); + __atomic_fetch_add (&self->ref_count, 1, __ATOMIC_SEQ_CST); return self; } -gint +int mapped_ring_buffer_get_fd (MappedRingBuffer *self) { - g_return_val_if_fail (self != NULL, -1); + assert (self != NULL); return self->fd; } @@ -377,23 +389,23 @@ mapped_ring_buffer_get_fd (MappedRingBuffer *self) * Returns: (nullable): a pointer to data of at least @length bytes * or %NULL if there is not enough space. */ -gpointer +void * mapped_ring_buffer_allocate (MappedRingBuffer *self, - gsize length) + size_t length) { MappedRingHeader *header; - gsize headpos; - gsize tailpos; + uint32_t headpos; + uint32_t tailpos; - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (self->mode & MODE_WRITER, NULL); - g_return_val_if_fail (length > 0, NULL); - g_return_val_if_fail (length < self->body_size, NULL); - g_return_val_if_fail ((length & 0x7) == 0, NULL); + assert (self != NULL); + assert (self->mode & MODE_WRITER); + assert (length > 0); + assert (length < self->body_size); + assert ((length & 0x7) == 0); header = get_header (self); - headpos = g_atomic_int_get (&header->head); - tailpos = g_atomic_int_get (&header->tail); + __atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST); + __atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST); /* We need to check that there is enough space for @length at the * current position in the write buffer. We cannot fully catch up @@ -436,16 +448,16 @@ mapped_ring_buffer_allocate (MappedRingBuffer *self, */ void mapped_ring_buffer_advance (MappedRingBuffer *self, - gsize length) + size_t length) { MappedRingHeader *header; - guint32 tail; + uint32_t tail; - g_return_if_fail (self != NULL); - g_return_if_fail (self->mode & MODE_WRITER); - g_return_if_fail (length > 0); - g_return_if_fail (length < self->body_size); - g_return_if_fail ((length & 0x7) == 0); + assert (self != NULL); + assert (self->mode & MODE_WRITER); + assert (length > 0); + assert (length < self->body_size); + assert ((length & 0x7) == 0); header = get_header (self); tail = header->tail; @@ -460,7 +472,7 @@ mapped_ring_buffer_advance (MappedRingBuffer *self, * we just update the position as the only way the head could have * moved is forward. */ - g_atomic_int_set (&header->tail, tail); + __atomic_store (&header->tail, &tail, __ATOMIC_SEQ_CST); } /** @@ -477,28 +489,28 @@ mapped_ring_buffer_advance (MappedRingBuffer *self, * Returns: %TRUE if the buffer was drained, %FALSE if @callback prematurely * returned while draining. */ -gboolean +bool mapped_ring_buffer_drain (MappedRingBuffer *self, MappedRingBufferCallback callback, - gpointer user_data) + void *user_data) { MappedRingHeader *header; - gsize headpos; - gsize tailpos; + uint32_t headpos; + uint32_t tailpos; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (self->mode & MODE_READER, FALSE); - g_return_val_if_fail (callback != NULL, FALSE); + assert (self != NULL); + assert (self->mode & MODE_READER); + assert (callback != NULL); header = get_header (self); - headpos = g_atomic_int_get (&header->head); - tailpos = g_atomic_int_get (&header->tail); + __atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST); + __atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST); - g_assert (headpos < self->body_size); - g_assert (tailpos < self->body_size); + assert (headpos < self->body_size); + assert (tailpos < self->body_size); if (headpos == tailpos) - return TRUE; + return true; /* If head needs to wrap around to get to tail, we can just rely on * our double mapping instead actually manually wrapping/copying data. @@ -506,131 +518,56 @@ mapped_ring_buffer_drain (MappedRingBuffer *self, if (tailpos < headpos) tailpos += self->body_size; - g_assert (headpos < tailpos); + assert (headpos < tailpos); while (headpos < tailpos) { - gconstpointer data = get_body_at_pos (self, headpos); - gsize len = tailpos - headpos; + const void *data = get_body_at_pos (self, headpos); + size_t len = tailpos - headpos; + uint32_t new_headpos; if (!callback (data, &len, user_data)) - return FALSE; + return false; if (len > (tailpos - headpos)) - return FALSE; + return false; headpos += len; if (headpos >= self->body_size) - g_atomic_int_set (&header->head, headpos - self->body_size); + new_headpos = headpos - self->body_size; else - g_atomic_int_set (&header->head, headpos); + new_headpos = headpos; + + __atomic_store (&header->head, &new_headpos, __ATOMIC_SEQ_CST); } - return TRUE; + 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 + */ +bool +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; + uint32_t headpos, tailpos; - g_assert (real_source != NULL); - g_assert (real_source->self != NULL); + header = get_header (self); - header = get_header (real_source->self); + __atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST); + __atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST); - 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; } /** @@ -648,7 +585,7 @@ mapped_ring_buffer_clear (MappedRingBuffer *self) { MappedRingHeader *header; - g_return_if_fail (self != NULL); + assert (self != NULL); header = get_header (self); header->head = 0; diff --git a/src/libsysprof-capture/mapped-ring-buffer.h b/src/libsysprof-capture/mapped-ring-buffer.h index 4eee6953..6bf2bb7a 100644 --- a/src/libsysprof-capture/mapped-ring-buffer.h +++ b/src/libsysprof-capture/mapped-ring-buffer.h @@ -20,9 +20,12 @@ #pragma once -#include +#include +#include -G_BEGIN_DECLS +#include "sysprof-macros.h" + +SYSPROF_BEGIN_DECLS typedef struct _MappedRingBuffer MappedRingBuffer; @@ -49,44 +52,35 @@ typedef struct _MappedRingBuffer MappedRingBuffer; * * Returns: %TRUE to coninue draining, otherwise %FALSE and draining stops */ -typedef gboolean (*MappedRingBufferCallback) (gconstpointer data, - gsize *length, - gpointer user_data); +typedef bool (*MappedRingBufferCallback) (const void *data, + size_t *length, + void *user_data); -G_GNUC_INTERNAL -MappedRingBuffer *mapped_ring_buffer_new_reader (gsize buffer_size); -G_GNUC_INTERNAL -MappedRingBuffer *mapped_ring_buffer_new_readwrite (gsize buffer_size); -G_GNUC_INTERNAL -MappedRingBuffer *mapped_ring_buffer_new_writer (gint fd); -G_GNUC_INTERNAL -gint mapped_ring_buffer_get_fd (MappedRingBuffer *self); -G_GNUC_INTERNAL +SYSPROF_INTERNAL +MappedRingBuffer *mapped_ring_buffer_new_reader (size_t buffer_size); +SYSPROF_INTERNAL +MappedRingBuffer *mapped_ring_buffer_new_readwrite (size_t buffer_size); +SYSPROF_INTERNAL +MappedRingBuffer *mapped_ring_buffer_new_writer (int fd); +SYSPROF_INTERNAL +int mapped_ring_buffer_get_fd (MappedRingBuffer *self); +SYSPROF_INTERNAL MappedRingBuffer *mapped_ring_buffer_ref (MappedRingBuffer *self); -G_GNUC_INTERNAL +SYSPROF_INTERNAL void mapped_ring_buffer_unref (MappedRingBuffer *self); -G_GNUC_INTERNAL +SYSPROF_INTERNAL void mapped_ring_buffer_clear (MappedRingBuffer *self); -G_GNUC_INTERNAL -gpointer mapped_ring_buffer_allocate (MappedRingBuffer *self, - gsize length); -G_GNUC_INTERNAL +SYSPROF_INTERNAL +void *mapped_ring_buffer_allocate (MappedRingBuffer *self, + size_t length); +SYSPROF_INTERNAL void mapped_ring_buffer_advance (MappedRingBuffer *self, - gsize length); -G_GNUC_INTERNAL -gboolean mapped_ring_buffer_drain (MappedRingBuffer *self, + size_t length); +SYSPROF_INTERNAL +bool mapped_ring_buffer_drain (MappedRingBuffer *self, 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); + void *user_data); +SYSPROF_INTERNAL +bool mapped_ring_buffer_is_empty (MappedRingBuffer *self); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (MappedRingBuffer, mapped_ring_buffer_unref) - -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/meson.build b/src/libsysprof-capture/meson.build index 8ed7934a..c8cd6895 100644 --- a/src/libsysprof-capture/meson.build +++ b/src/libsysprof-capture/meson.build @@ -7,6 +7,7 @@ libsysprof_capture_headers = files([ 'sysprof-capture-types.h', 'sysprof-capture-writer.h', 'sysprof-collector.h', + 'sysprof-macros.h', 'sysprof-platform.h', 'sysprof-capture.h', 'sysprof-version-macros.h', @@ -36,9 +37,7 @@ configure_file( ) libsysprof_capture_deps = [ - glib_dep, - gio_dep, - gio_unix_dep, + dependency('threads'), ] libsysprof_capture = static_library( @@ -68,7 +67,6 @@ pkgconfig.generate( filebase: 'sysprof-capture-@0@'.format(libsysprof_api_version), description: 'The static capture library for tools that generate profiling capture data', install_dir: join_paths(get_option('libdir'), 'pkgconfig'), - requires: [ 'glib-2.0' ], variables: [ 'datadir=' + datadir_for_pc_file, ], diff --git a/src/libsysprof-capture/sysprof-address.c b/src/libsysprof-capture/sysprof-address.c index e6009627..1b125015 100644 --- a/src/libsysprof-capture/sysprof-address.c +++ b/src/libsysprof-capture/sysprof-address.c @@ -61,10 +61,12 @@ #else # include "sysprof-address-fallback.h" #endif +#include +#include #include "sysprof-address.h" -gboolean +bool sysprof_address_is_context_switch (SysprofAddress address, SysprofAddressContext *context) { @@ -77,35 +79,35 @@ sysprof_address_is_context_switch (SysprofAddress address, { case PERF_CONTEXT_HV: *context = SYSPROF_ADDRESS_CONTEXT_HYPERVISOR; - return TRUE; + return true; case PERF_CONTEXT_KERNEL: *context = SYSPROF_ADDRESS_CONTEXT_KERNEL; - return TRUE; + return true; case PERF_CONTEXT_USER: *context = SYSPROF_ADDRESS_CONTEXT_USER; - return TRUE; + return true; case PERF_CONTEXT_GUEST: *context = SYSPROF_ADDRESS_CONTEXT_GUEST; - return TRUE; + return true; case PERF_CONTEXT_GUEST_KERNEL: *context = SYSPROF_ADDRESS_CONTEXT_GUEST_KERNEL; - return TRUE; + return true; case PERF_CONTEXT_GUEST_USER: *context = SYSPROF_ADDRESS_CONTEXT_GUEST_USER; - return TRUE; + return true; default: *context = SYSPROF_ADDRESS_CONTEXT_NONE; - return FALSE; + return false; } } -const gchar * +const char * sysprof_address_context_to_string (SysprofAddressContext context) { switch (context) diff --git a/src/libsysprof-capture/sysprof-address.h b/src/libsysprof-capture/sysprof-address.h index 88cb5b72..098bcc31 100644 --- a/src/libsysprof-capture/sysprof-address.h +++ b/src/libsysprof-capture/sysprof-address.h @@ -56,13 +56,19 @@ #pragma once +#include +#include +#include + +#include "sysprof-macros.h" #include "sysprof-version-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS -typedef guint64 SysprofAddress; +typedef uint64_t SysprofAddress; -G_STATIC_ASSERT (sizeof (SysprofAddress) >= sizeof (gpointer)); +static_assert (sizeof (SysprofAddress) >= sizeof (void *), + "Address space is too big"); typedef enum { @@ -76,12 +82,12 @@ typedef enum } SysprofAddressContext; SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_address_is_context_switch (SysprofAddress address, +bool sysprof_address_is_context_switch (SysprofAddress address, SysprofAddressContext *context); SYSPROF_AVAILABLE_IN_ALL -const gchar *sysprof_address_context_to_string (SysprofAddressContext context); +const char *sysprof_address_context_to_string (SysprofAddressContext context); -static inline gint +static inline int sysprof_address_compare (SysprofAddress a, SysprofAddress b) { @@ -93,4 +99,4 @@ sysprof_address_compare (SysprofAddress a, return 1; } -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-capture-condition.c b/src/libsysprof-capture/sysprof-capture-condition.c index 78fb0362..8f891577 100644 --- a/src/libsysprof-capture/sysprof-capture-condition.c +++ b/src/libsysprof-capture/sysprof-capture-condition.c @@ -54,13 +54,16 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-capture-condition" - #include "config.h" +#include +#include +#include #include #include "sysprof-capture-condition.h" +#include "sysprof-capture-util-private.h" +#include "sysprof-macros-internal.h" /** * SECTION:sysprof-capture-condition @@ -86,30 +89,39 @@ typedef enum struct _SysprofCaptureCondition { - volatile gint ref_count; + volatile int ref_count; SysprofCaptureConditionType type; union { - GArray *where_type_in; struct { - gint64 begin; - gint64 end; + SysprofCaptureFrameType *data; + size_t len; + } where_type_in; + struct { + int64_t begin; + int64_t end; } where_time_between; - GArray *where_pid_in; - GArray *where_counter_in; + struct { + int32_t *data; + size_t len; + } where_pid_in; + struct { + unsigned int *data; + size_t len; + } where_counter_in; struct { SysprofCaptureCondition *left; SysprofCaptureCondition *right; } and, or; - gchar *where_file; + char *where_file; } u; }; -gboolean +bool sysprof_capture_condition_match (const SysprofCaptureCondition *self, const SysprofCaptureFrame *frame) { - g_assert (self != NULL); - g_assert (frame != NULL); + assert (self != NULL); + assert (frame != NULL); switch (self->type) { @@ -122,34 +134,34 @@ sysprof_capture_condition_match (const SysprofCaptureCondition *self, sysprof_capture_condition_match (self->u.or.right, frame); case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN: - for (guint i = 0; i < self->u.where_type_in->len; i++) + for (size_t i = 0; i < self->u.where_type_in.len; i++) { - if (frame->type == g_array_index (self->u.where_type_in, SysprofCaptureFrameType, i)) - return TRUE; + if (frame->type == self->u.where_type_in.data[i]) + return true; } - return FALSE; + return false; case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN: return (frame->time >= self->u.where_time_between.begin && frame->time <= self->u.where_time_between.end); case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN: - for (guint i = 0; i < self->u.where_pid_in->len; i++) + for (size_t i = 0; i < self->u.where_pid_in.len; i++) { - if (frame->pid == g_array_index (self->u.where_pid_in, gint32, i)) - return TRUE; + if (frame->pid == self->u.where_pid_in.data[i]) + return true; } - return FALSE; + return false; case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN: if (frame->type == SYSPROF_CAPTURE_FRAME_CTRSET) { const SysprofCaptureCounterSet *set = (SysprofCaptureCounterSet *)frame; - for (guint i = 0; i < self->u.where_counter_in->len; i++) + for (size_t i = 0; i < self->u.where_counter_in.len; i++) { - guint counter = g_array_index (self->u.where_counter_in, guint, i); + unsigned int counter = self->u.where_counter_in.data[i]; - for (guint j = 0; j < set->n_values; j++) + for (unsigned int j = 0; j < set->n_values; j++) { if (counter == set->values[j].ids[0] || counter == set->values[j].ids[1] || @@ -159,7 +171,7 @@ sysprof_capture_condition_match (const SysprofCaptureCondition *self, counter == set->values[j].ids[5] || counter == set->values[j].ids[6] || counter == set->values[j].ids[7]) - return TRUE; + return true; } } } @@ -167,33 +179,36 @@ sysprof_capture_condition_match (const SysprofCaptureCondition *self, { const SysprofCaptureCounterDefine *def = (SysprofCaptureCounterDefine *)frame; - for (guint i = 0; i < self->u.where_counter_in->len; i++) + for (size_t i = 0; i < self->u.where_counter_in.len; i++) { - guint counter = g_array_index (self->u.where_counter_in, guint, i); + unsigned int counter = self->u.where_counter_in.data[i]; - for (guint j = 0; j < def->n_counters; j++) + for (unsigned int j = 0; j < def->n_counters; j++) { if (def->counters[j].id == counter) - return TRUE; + return true; } } } - return FALSE; + return false; case SYSPROF_CAPTURE_CONDITION_WHERE_FILE: if (frame->type != SYSPROF_CAPTURE_FRAME_FILE_CHUNK) - return FALSE; + return false; - return g_strcmp0 (((const SysprofCaptureFileChunk *)frame)->path, self->u.where_file) == 0; + if (self->u.where_file == NULL) + return false; + + return strcmp (((const SysprofCaptureFileChunk *)frame)->path, self->u.where_file) == 0; default: break; } - g_assert_not_reached (); + sysprof_assert_not_reached (); - return FALSE; + return false; } static SysprofCaptureCondition * @@ -201,12 +216,16 @@ sysprof_capture_condition_init (void) { SysprofCaptureCondition *self; - self = g_slice_new0 (SysprofCaptureCondition); + self = sysprof_malloc0 (sizeof (SysprofCaptureCondition)); + if (self == NULL) + return NULL; + self->ref_count = 1; - return g_steal_pointer (&self); + return sysprof_steal_pointer (&self); } +/* Returns NULL on allocation failure. */ SysprofCaptureCondition * sysprof_capture_condition_copy (const SysprofCaptureCondition *self) { @@ -224,8 +243,8 @@ sysprof_capture_condition_copy (const SysprofCaptureCondition *self) case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN: return sysprof_capture_condition_new_where_type_in ( - self->u.where_type_in->len, - (const SysprofCaptureFrameType *)(gpointer)self->u.where_type_in->data); + self->u.where_type_in.len, + self->u.where_type_in.data); case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN: return sysprof_capture_condition_new_where_time_between ( @@ -234,13 +253,13 @@ sysprof_capture_condition_copy (const SysprofCaptureCondition *self) case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN: return sysprof_capture_condition_new_where_pid_in ( - self->u.where_pid_in->len, - (const gint32 *)(gpointer)self->u.where_pid_in->data); + self->u.where_pid_in.len, + self->u.where_pid_in.data); case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN: return sysprof_capture_condition_new_where_counter_in ( - self->u.where_counter_in->len, - (const guint *)(gpointer)self->u.where_counter_in->data); + self->u.where_counter_in.len, + self->u.where_counter_in.data); case SYSPROF_CAPTURE_CONDITION_WHERE_FILE: return sysprof_capture_condition_new_where_file (self->u.where_file); @@ -249,7 +268,7 @@ sysprof_capture_condition_copy (const SysprofCaptureCondition *self) break; } - g_return_val_if_reached (NULL); + sysprof_assert_not_reached (); } static void @@ -268,83 +287,93 @@ sysprof_capture_condition_finalize (SysprofCaptureCondition *self) break; case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN: - g_array_free (self->u.where_type_in, TRUE); + free (self->u.where_type_in.data); break; case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN: break; case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN: - g_array_free (self->u.where_pid_in, TRUE); + free (self->u.where_pid_in.data); break; case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN: - g_array_free (self->u.where_counter_in, TRUE); + free (self->u.where_counter_in.data); break; case SYSPROF_CAPTURE_CONDITION_WHERE_FILE: - g_free (self->u.where_file); + free (self->u.where_file); break; default: - g_assert_not_reached (); + sysprof_assert_not_reached (); break; } - g_slice_free (SysprofCaptureCondition, self); + free (self); } SysprofCaptureCondition * sysprof_capture_condition_ref (SysprofCaptureCondition *self) { - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (self->ref_count > 0, NULL); + assert (self != NULL); + assert (self->ref_count > 0); - g_atomic_int_inc (&self->ref_count); + __atomic_fetch_add (&self->ref_count, 1, __ATOMIC_SEQ_CST); return self; } void sysprof_capture_condition_unref (SysprofCaptureCondition *self) { - g_return_if_fail (self != NULL); - g_return_if_fail (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - if (g_atomic_int_dec_and_test (&self->ref_count)) + if (__atomic_fetch_sub (&self->ref_count, 1, __ATOMIC_SEQ_CST) == 1) sysprof_capture_condition_finalize (self); } +/* Returns NULL on allocation failure. */ SysprofCaptureCondition * -sysprof_capture_condition_new_where_type_in (guint n_types, - const SysprofCaptureFrameType *types) +sysprof_capture_condition_new_where_type_in (unsigned int n_types, + const SysprofCaptureFrameType *types) { SysprofCaptureCondition *self; - g_return_val_if_fail (types != NULL, NULL); + assert (types != NULL); self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN; - self->u.where_type_in = g_array_sized_new (FALSE, FALSE, sizeof (SysprofCaptureFrameType), n_types); - g_array_set_size (self->u.where_type_in, n_types); - memcpy (self->u.where_type_in->data, types, sizeof (SysprofCaptureFrameType) * n_types); + self->u.where_type_in.data = calloc (n_types, sizeof (SysprofCaptureFrameType)); + if (self->u.where_type_in.data == NULL) + return NULL; + self->u.where_type_in.len = n_types; + memcpy (self->u.where_type_in.data, types, sizeof (SysprofCaptureFrameType) * n_types); return self; } +/* Returns NULL on allocation failure. */ SysprofCaptureCondition * -sysprof_capture_condition_new_where_time_between (gint64 begin_time, - gint64 end_time) +sysprof_capture_condition_new_where_time_between (int64_t begin_time, + int64_t end_time) { SysprofCaptureCondition *self; - if G_UNLIKELY (begin_time > end_time) + if SYSPROF_UNLIKELY (begin_time > end_time) { - gint64 tmp = begin_time; + int64_t tmp = begin_time; begin_time = end_time; end_time = tmp; } self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN; self->u.where_time_between.begin = begin_time; self->u.where_time_between.end = end_time; @@ -352,40 +381,56 @@ sysprof_capture_condition_new_where_time_between (gint64 begin_time, return self; } +/* Returns NULL on allocation failure. */ SysprofCaptureCondition * -sysprof_capture_condition_new_where_pid_in (guint n_pids, - const gint32 *pids) +sysprof_capture_condition_new_where_pid_in (unsigned int n_pids, + const int32_t *pids) { SysprofCaptureCondition *self; - g_return_val_if_fail (pids != NULL, NULL); + assert (pids != NULL); self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN; - self->u.where_pid_in = g_array_sized_new (FALSE, FALSE, sizeof (gint32), n_pids); - g_array_set_size (self->u.where_pid_in, n_pids); - memcpy (self->u.where_pid_in->data, pids, sizeof (gint32) * n_pids); + self->u.where_pid_in.data = calloc (n_pids, sizeof (int32_t)); + if (self->u.where_pid_in.data == NULL) + { + free (self); + return NULL; + } + self->u.where_pid_in.len = n_pids; + memcpy (self->u.where_pid_in.data, pids, sizeof (int32_t) * n_pids); return self; } +/* Returns NULL on allocation failure. */ SysprofCaptureCondition * -sysprof_capture_condition_new_where_counter_in (guint n_counters, - const guint *counters) +sysprof_capture_condition_new_where_counter_in (unsigned int n_counters, + const unsigned int *counters) { SysprofCaptureCondition *self; - g_return_val_if_fail (counters != NULL || n_counters == 0, NULL); + assert (counters != NULL || n_counters == 0); self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN; - self->u.where_counter_in = g_array_sized_new (FALSE, FALSE, sizeof (guint), n_counters); + self->u.where_counter_in.data = calloc (n_counters, sizeof (unsigned int)); + if (n_counters > 0 && self->u.where_counter_in.data == NULL) + { + free (self); + return NULL; + } + self->u.where_counter_in.len = n_counters; if (n_counters > 0) - { - g_array_set_size (self->u.where_counter_in, n_counters); - memcpy (self->u.where_counter_in->data, counters, sizeof (guint) * n_counters); - } + memcpy (self->u.where_counter_in.data, counters, sizeof (unsigned int) * n_counters); return self; } @@ -398,7 +443,8 @@ sysprof_capture_condition_new_where_counter_in (guint n_counters, * Creates a new #SysprofCaptureCondition that requires both left and right * to evaluate to %TRUE. * - * Returns: (transfer full): A new #SysprofCaptureCondition. + * Returns: (transfer full) (nullable): A new #SysprofCaptureCondition, or %NULL + * on allocation failure. */ SysprofCaptureCondition * sysprof_capture_condition_new_and (SysprofCaptureCondition *left, @@ -406,10 +452,13 @@ sysprof_capture_condition_new_and (SysprofCaptureCondition *left, { SysprofCaptureCondition *self; - g_return_val_if_fail (left != NULL, NULL); - g_return_val_if_fail (right != NULL, NULL); + assert (left != NULL); + assert (right != NULL); self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_AND; self->u.and.left = left; self->u.and.right = right; @@ -425,7 +474,8 @@ sysprof_capture_condition_new_and (SysprofCaptureCondition *left, * Creates a new #SysprofCaptureCondition that requires either left and right * to evaluate to %TRUE. * - * Returns: (transfer full): A new #SysprofCaptureCondition. + * Returns: (transfer full) (nullable): A new #SysprofCaptureCondition, or %NULL + * on allocation failure. */ SysprofCaptureCondition * sysprof_capture_condition_new_or (SysprofCaptureCondition *left, @@ -433,10 +483,13 @@ sysprof_capture_condition_new_or (SysprofCaptureCondition *left, { SysprofCaptureCondition *self; - g_return_val_if_fail (left != NULL, NULL); - g_return_val_if_fail (right != NULL, NULL); + assert (left != NULL); + assert (right != NULL); self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_OR; self->u.or.left = left; self->u.or.right = right; @@ -451,18 +504,27 @@ sysprof_capture_condition_new_or (SysprofCaptureCondition *left, * Creates a new condition that matches #SysprofCaptureFileChunk frames * which contain the path @path. * - * Returns: (transfer full): a new #SysprofCaptureCondition + * Returns: (transfer full) (nullable): a new #SysprofCaptureCondition, or %NULL + * on allocation failure. */ SysprofCaptureCondition * -sysprof_capture_condition_new_where_file (const gchar *path) +sysprof_capture_condition_new_where_file (const char *path) { SysprofCaptureCondition *self; - g_return_val_if_fail (path != NULL, NULL); + assert (path != NULL); self = sysprof_capture_condition_init (); + if (self == NULL) + return NULL; + self->type = SYSPROF_CAPTURE_CONDITION_WHERE_FILE; - self->u.where_file = g_strdup (path); + self->u.where_file = sysprof_strdup (path); + if (self->u.where_file == NULL) + { + free (self); + return NULL; + } return self; } diff --git a/src/libsysprof-capture/sysprof-capture-condition.h b/src/libsysprof-capture/sysprof-capture-condition.h index 077b8ce3..78ea7268 100644 --- a/src/libsysprof-capture/sysprof-capture-condition.h +++ b/src/libsysprof-capture/sysprof-capture-condition.h @@ -56,10 +56,13 @@ #pragma once +#include + #include "sysprof-capture-types.h" +#include "sysprof-macros.h" #include "sysprof-version-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS SYSPROF_AVAILABLE_IN_ALL SysprofCaptureCondition *sysprof_capture_condition_copy (const SysprofCaptureCondition *self); @@ -74,23 +77,21 @@ SYSPROF_AVAILABLE_IN_ALL SysprofCaptureCondition *sysprof_capture_condition_new_or (SysprofCaptureCondition *left, SysprofCaptureCondition *right); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureCondition *sysprof_capture_condition_new_where_type_in (guint n_types, +SysprofCaptureCondition *sysprof_capture_condition_new_where_type_in (unsigned int n_types, const SysprofCaptureFrameType *types); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureCondition *sysprof_capture_condition_new_where_time_between (gint64 begin_time, - gint64 end_time); +SysprofCaptureCondition *sysprof_capture_condition_new_where_time_between (int64_t begin_time, + int64_t end_time); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureCondition *sysprof_capture_condition_new_where_pid_in (guint n_pids, - const gint32 *pids); +SysprofCaptureCondition *sysprof_capture_condition_new_where_pid_in (unsigned int n_pids, + const int32_t *pids); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureCondition *sysprof_capture_condition_new_where_counter_in (guint n_counters, - const guint *counters); +SysprofCaptureCondition *sysprof_capture_condition_new_where_counter_in (unsigned int n_counters, + const unsigned int *counters); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureCondition *sysprof_capture_condition_new_where_file (const gchar *path); +SysprofCaptureCondition *sysprof_capture_condition_new_where_file (const char *path); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_condition_match (const SysprofCaptureCondition *self, +bool sysprof_capture_condition_match (const SysprofCaptureCondition *self, const SysprofCaptureFrame *frame); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureCondition, sysprof_capture_condition_unref) - -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-capture-cursor.c b/src/libsysprof-capture/sysprof-capture-cursor.c index d2d014fb..24563f0a 100644 --- a/src/libsysprof-capture/sysprof-capture-cursor.c +++ b/src/libsysprof-capture/sysprof-capture-cursor.c @@ -54,13 +54,16 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-capture-cursor" - #include "config.h" +#include +#include + #include "sysprof-capture-condition.h" #include "sysprof-capture-cursor.h" #include "sysprof-capture-reader.h" +#include "sysprof-capture-util-private.h" +#include "sysprof-macros-internal.h" #define READ_DELEGATE(f) ((ReadDelegate)(f)) @@ -68,18 +71,21 @@ typedef const SysprofCaptureFrame *(*ReadDelegate) (SysprofCaptureReader *); struct _SysprofCaptureCursor { - volatile gint ref_count; - GPtrArray *conditions; + volatile int ref_count; + SysprofCaptureCondition **conditions; /* (nullable) (owned) */ + size_t n_conditions; SysprofCaptureReader *reader; - guint reversed : 1; + unsigned int reversed : 1; }; static void sysprof_capture_cursor_finalize (SysprofCaptureCursor *self) { - g_clear_pointer (&self->conditions, g_ptr_array_unref); - g_clear_pointer (&self->reader, sysprof_capture_reader_unref); - g_slice_free (SysprofCaptureCursor, self); + for (size_t i = 0; i < self->n_conditions; i++) + sysprof_capture_condition_unref (self->conditions[i]); + sysprof_clear_pointer (&self->conditions, free); + sysprof_clear_pointer (&self->reader, sysprof_capture_reader_unref); + free (self); } static SysprofCaptureCursor * @@ -87,11 +93,15 @@ sysprof_capture_cursor_init (void) { SysprofCaptureCursor *self; - self = g_slice_new0 (SysprofCaptureCursor); - self->conditions = g_ptr_array_new_with_free_func ((GDestroyNotify) sysprof_capture_condition_unref); + self = sysprof_malloc0 (sizeof (SysprofCaptureCursor)); + if (self == NULL) + return NULL; + + self->conditions = NULL; + self->n_conditions = 0; self->ref_count = 1; - return g_steal_pointer (&self); + return sysprof_steal_pointer (&self); } /** @@ -105,10 +115,10 @@ sysprof_capture_cursor_init (void) SysprofCaptureCursor * sysprof_capture_cursor_ref (SysprofCaptureCursor *self) { - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (self->ref_count > 0, NULL); + assert (self != NULL); + assert (self->ref_count > 0); - g_atomic_int_inc (&self->ref_count); + __atomic_fetch_add (&self->ref_count, 1, __ATOMIC_SEQ_CST); return self; } @@ -121,10 +131,10 @@ sysprof_capture_cursor_ref (SysprofCaptureCursor *self) void sysprof_capture_cursor_unref (SysprofCaptureCursor *self) { - g_return_if_fail (self != NULL); - g_return_if_fail (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - if (g_atomic_int_dec_and_test (&self->ref_count)) + if (__atomic_fetch_sub (&self->ref_count, 1, __ATOMIC_SEQ_CST) == 1) sysprof_capture_cursor_finalize (self); } @@ -138,11 +148,11 @@ sysprof_capture_cursor_unref (SysprofCaptureCursor *self) void sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, SysprofCaptureCursorCallback callback, - gpointer user_data) + void *user_data) { - g_return_if_fail (self != NULL); - g_return_if_fail (self->reader != NULL); - g_return_if_fail (callback != NULL); + assert (self != NULL); + assert (self->reader != NULL); + assert (callback != NULL); for (;;) { @@ -224,16 +234,16 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, if (NULL == (frame = delegate (self->reader))) return; - if (self->conditions->len == 0) + if (self->n_conditions == 0) { if (!callback (frame, user_data)) return; } else { - for (guint i = 0; i < self->conditions->len; i++) + for (size_t i = 0; i < self->n_conditions; i++) { - const SysprofCaptureCondition *condition = g_ptr_array_index (self->conditions, i); + const SysprofCaptureCondition *condition = self->conditions[i]; if (sysprof_capture_condition_match (condition, frame)) { @@ -249,8 +259,8 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, void sysprof_capture_cursor_reset (SysprofCaptureCursor *self) { - g_return_if_fail (self != NULL); - g_return_if_fail (self->reader != NULL); + assert (self != NULL); + assert (self->reader != NULL); sysprof_capture_reader_reset (self->reader); } @@ -258,7 +268,7 @@ sysprof_capture_cursor_reset (SysprofCaptureCursor *self) void sysprof_capture_cursor_reverse (SysprofCaptureCursor *self) { - g_return_if_fail (self != NULL); + assert (self != NULL); self->reversed = !self->reversed; } @@ -275,10 +285,18 @@ void sysprof_capture_cursor_add_condition (SysprofCaptureCursor *self, SysprofCaptureCondition *condition) { - g_return_if_fail (self != NULL); - g_return_if_fail (condition != NULL); + assert (self != NULL); + assert (condition != NULL); - g_ptr_array_add (self->conditions, condition); + /* Grow the array linearly to keep the code simple: there are typically 0 or 1 + * conditions applied to a given cursor, just after it’s constructed. + * + * FIXME: There’s currently no error reporting from this function, so ENOMEM + * results in an abort. */ + self->conditions = reallocarray (self->conditions, ++self->n_conditions, sizeof (*self->conditions)); + assert (self->conditions != NULL); + + self->conditions[self->n_conditions - 1] = sysprof_steal_pointer (&condition); } /** @@ -292,7 +310,7 @@ sysprof_capture_cursor_new (SysprofCaptureReader *reader) { SysprofCaptureCursor *self; - g_return_val_if_fail (reader != NULL, NULL); + assert (reader != NULL); self = sysprof_capture_cursor_init (); self->reader = sysprof_capture_reader_copy (reader); @@ -311,7 +329,7 @@ sysprof_capture_cursor_new (SysprofCaptureReader *reader) SysprofCaptureReader * sysprof_capture_cursor_get_reader (SysprofCaptureCursor *self) { - g_return_val_if_fail (self != NULL, NULL); + assert (self != NULL); return self->reader; } diff --git a/src/libsysprof-capture/sysprof-capture-cursor.h b/src/libsysprof-capture/sysprof-capture-cursor.h index 19d4fb49..5d5693b5 100644 --- a/src/libsysprof-capture/sysprof-capture-cursor.h +++ b/src/libsysprof-capture/sysprof-capture-cursor.h @@ -56,10 +56,13 @@ #pragma once +#include + #include "sysprof-capture-types.h" +#include "sysprof-macros.h" #include "sysprof-version-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS typedef struct _SysprofCaptureCursor SysprofCaptureCursor; @@ -74,8 +77,8 @@ typedef struct _SysprofCaptureCursor SysprofCaptureCursor; * * Returns: %TRUE if iteration should continue, otherwise %FALSE. */ -typedef gboolean (*SysprofCaptureCursorCallback) (const SysprofCaptureFrame *frame, - gpointer user_data); +typedef bool (*SysprofCaptureCursorCallback) (const SysprofCaptureFrame *frame, + void *user_data); SYSPROF_AVAILABLE_IN_ALL SysprofCaptureCursor *sysprof_capture_cursor_new (SysprofCaptureReader *reader); @@ -88,7 +91,7 @@ SysprofCaptureReader *sysprof_capture_cursor_get_reader (SysprofCaptureCursor SYSPROF_AVAILABLE_IN_ALL void sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, SysprofCaptureCursorCallback callback, - gpointer user_data); + void *user_data); SYSPROF_AVAILABLE_IN_ALL void sysprof_capture_cursor_reset (SysprofCaptureCursor *self); SYSPROF_AVAILABLE_IN_ALL @@ -97,6 +100,4 @@ SYSPROF_AVAILABLE_IN_ALL void sysprof_capture_cursor_add_condition (SysprofCaptureCursor *self, SysprofCaptureCondition *condition); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureCursor, sysprof_capture_cursor_unref) - -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c index ed157621..67c6b28b 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.c +++ b/src/libsysprof-capture/sysprof-capture-reader.c @@ -54,12 +54,15 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-capture-reader" - #include "config.h" +#include +#include +#include #include #include +#include +#include #include #include #include @@ -68,53 +71,49 @@ #include "sysprof-capture-reader.h" #include "sysprof-capture-util-private.h" #include "sysprof-capture-writer.h" +#include "sysprof-macros-internal.h" struct _SysprofCaptureReader { - volatile gint ref_count; - gchar *filename; - guint8 *buf; - gsize bufsz; - gsize len; - gsize pos; - gsize fd_off; + volatile int ref_count; + char *filename; + uint8_t *buf; + size_t bufsz; + size_t len; + size_t pos; + size_t fd_off; int fd; - gint endian; + int endian; SysprofCaptureFileHeader header; - gint64 end_time; + int64_t end_time; SysprofCaptureStat st_buf; - guint st_buf_set : 1; + unsigned int st_buf_set : 1; }; -static gboolean -sysprof_capture_reader_read_file_header (SysprofCaptureReader *self, - SysprofCaptureFileHeader *header, - GError **error) +/* Sets @errno on failure. Sets @errno to EBADMSG if the file magic doesn’t + * match, and otherwise can return any error as for read(). */ +static bool +sysprof_capture_reader_read_file_header (SysprofCaptureReader *self, + SysprofCaptureFileHeader *header) { - g_assert (self != NULL); - g_assert (header != NULL); + assert (self != NULL); + assert (header != NULL); if (sizeof *header != _sysprof_pread (self->fd, header, sizeof *header, 0L)) { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - return FALSE; + /* errno is propagated */ + return false; } if (header->magic != SYSPROF_CAPTURE_MAGIC) { - g_set_error (error, - G_FILE_ERROR, - G_FILE_ERROR_FAILED, - "Capture file magic does not match"); - return FALSE; + errno = EBADMSG; + return false; } header->capture_time[sizeof header->capture_time - 1] = '\0'; - return TRUE; + return true; } static void @@ -123,24 +122,24 @@ sysprof_capture_reader_finalize (SysprofCaptureReader *self) if (self != NULL) { close (self->fd); - g_free (self->buf); - g_free (self->filename); - g_free (self); + free (self->buf); + free (self->filename); + free (self); } } -const gchar * +const char * sysprof_capture_reader_get_time (SysprofCaptureReader *self) { - g_return_val_if_fail (self != NULL, NULL); + assert (self != NULL); return self->header.capture_time; } -const gchar * +const char * sysprof_capture_reader_get_filename (SysprofCaptureReader *self) { - g_return_val_if_fail (self != NULL, NULL); + assert (self != NULL); return self->filename; } @@ -150,11 +149,11 @@ sysprof_capture_reader_discover_end_time (SysprofCaptureReader *self) { SysprofCaptureFrame frame; - g_assert (self != NULL); + assert (self != NULL); while (sysprof_capture_reader_peek_frame (self, &frame)) { - gint64 end_time = frame.time; + int64_t end_time = frame.time; switch (frame.type) { @@ -162,7 +161,7 @@ sysprof_capture_reader_discover_end_time (SysprofCaptureReader *self) const SysprofCaptureMark *mark = NULL; if ((mark = sysprof_capture_reader_read_mark (self))) - end_time = frame.time + MAX (0, mark->duration); + end_time = frame.time + ((mark->duration > 0) ? mark->duration : 0); } break; @@ -197,41 +196,56 @@ sysprof_capture_reader_discover_end_time (SysprofCaptureReader *self) /** * sysprof_capture_reader_new_from_fd: * @fd: an fd to take ownership from - * @error: a location for a #GError or %NULL * * Creates a new reader using the file-descriptor. * * This is useful if you don't necessarily have access to the filename itself. * + * If this function fails, `errno` is set. + * * Returns: (transfer full): an #SysprofCaptureReader or %NULL upon failure. */ SysprofCaptureReader * -sysprof_capture_reader_new_from_fd (int fd, - GError **error) +sysprof_capture_reader_new_from_fd (int fd) { SysprofCaptureReader *self; - g_assert (fd > -1); + assert (fd > -1); + + self = sysprof_malloc0 (sizeof (SysprofCaptureReader)); + if (self == NULL) + { + errno = ENOMEM; + return NULL; + } - self = g_new0 (SysprofCaptureReader, 1); self->ref_count = 1; - self->bufsz = G_MAXUSHORT * 2; - self->buf = g_malloc (self->bufsz); + self->bufsz = USHRT_MAX * 2; + self->buf = sysprof_malloc0 (self->bufsz); + if (self->buf == NULL) + { + free (self); + errno = ENOMEM; + return NULL; + } + self->len = 0; self->pos = 0; self->fd = fd; self->fd_off = sizeof (SysprofCaptureFileHeader); - if (!sysprof_capture_reader_read_file_header (self, &self->header, error)) + if (!sysprof_capture_reader_read_file_header (self, &self->header)) { + int errsv = errno; sysprof_capture_reader_finalize (self); + errno = errsv; return NULL; } if (self->header.little_endian) - self->endian = G_LITTLE_ENDIAN; + self->endian = __LITTLE_ENDIAN; else - self->endian = G_BIG_ENDIAN; + self->endian = __BIG_ENDIAN; /* If we detect a capture file that did not get an end time, or an erroneous * end time, then we need to take a performance hit here and scan the file @@ -244,30 +258,28 @@ sysprof_capture_reader_new_from_fd (int fd, } SysprofCaptureReader * -sysprof_capture_reader_new (const gchar *filename, - GError **error) +sysprof_capture_reader_new (const char *filename) { SysprofCaptureReader *self; int fd; - g_assert (filename != NULL); + assert (filename != NULL); if (-1 == (fd = open (filename, O_RDONLY, 0))) { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); + /* errno is propagated */ return NULL; } - if (NULL == (self = sysprof_capture_reader_new_from_fd (fd, error))) + if (NULL == (self = sysprof_capture_reader_new_from_fd (fd))) { + int errsv = errno; close (fd); + errno = errsv; return NULL; } - self->filename = g_strdup (filename); + self->filename = sysprof_strdup (filename); return self; } @@ -276,15 +288,15 @@ static inline void sysprof_capture_reader_bswap_frame (SysprofCaptureReader *self, SysprofCaptureFrame *frame) { - g_assert (self != NULL); - g_assert (frame!= NULL); + assert (self != NULL); + assert (frame!= NULL); - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) { - frame->len = GUINT16_SWAP_LE_BE (frame->len); - frame->cpu = GUINT16_SWAP_LE_BE (frame->cpu); - frame->pid = GUINT32_SWAP_LE_BE (frame->pid); - frame->time = GUINT64_SWAP_LE_BE (frame->time); + frame->len = bswap_16 (frame->len); + frame->cpu = bswap_16 (frame->cpu); + frame->pid = bswap_32 (frame->pid); + frame->time = bswap_64 (frame->time); } } @@ -292,37 +304,37 @@ static inline void sysprof_capture_reader_bswap_file_chunk (SysprofCaptureReader *self, SysprofCaptureFileChunk *file_chunk) { - g_assert (self != NULL); - g_assert (file_chunk != NULL); + assert (self != NULL); + assert (file_chunk != NULL); - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) - file_chunk->len = GUINT16_SWAP_LE_BE (file_chunk->len); + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + file_chunk->len = bswap_16 (file_chunk->len); } static inline void sysprof_capture_reader_bswap_log (SysprofCaptureReader *self, SysprofCaptureLog *log) { - g_assert (self != NULL); - g_assert (log != NULL); + assert (self != NULL); + assert (log != NULL); - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) - log->severity = GUINT16_SWAP_LE_BE (log->severity); + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + log->severity = bswap_16 (log->severity); } static inline void sysprof_capture_reader_bswap_map (SysprofCaptureReader *self, SysprofCaptureMap *map) { - g_assert (self != NULL); - g_assert (map != NULL); + assert (self != NULL); + assert (map != NULL); - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) { - map->start = GUINT64_SWAP_LE_BE (map->start); - map->end = GUINT64_SWAP_LE_BE (map->end); - map->offset = GUINT64_SWAP_LE_BE (map->offset); - map->inode = GUINT64_SWAP_LE_BE (map->inode); + map->start = bswap_64 (map->start); + map->end = bswap_64 (map->end); + map->offset = bswap_64 (map->offset); + map->inode = bswap_64 (map->inode); } } @@ -330,38 +342,38 @@ static inline void sysprof_capture_reader_bswap_mark (SysprofCaptureReader *self, SysprofCaptureMark *mark) { - g_assert (self != NULL); - g_assert (mark != NULL); + assert (self != NULL); + assert (mark != NULL); - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) - mark->duration = GUINT64_SWAP_LE_BE (mark->duration); + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + mark->duration = bswap_64 (mark->duration); } static inline void sysprof_capture_reader_bswap_jitmap (SysprofCaptureReader *self, SysprofCaptureJitmap *jitmap) { - g_assert (self != NULL); - g_assert (jitmap != NULL); + assert (self != NULL); + assert (jitmap != NULL); - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) - jitmap->n_jitmaps = GUINT64_SWAP_LE_BE (jitmap->n_jitmaps); + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + jitmap->n_jitmaps = bswap_64 (jitmap->n_jitmaps); } -static gboolean +static bool sysprof_capture_reader_ensure_space_for (SysprofCaptureReader *self, - gsize len) + size_t len) { - g_assert (self != NULL); - g_assert (self->pos <= self->len); - g_assert (len > 0); + assert (self != NULL); + assert (self->pos <= self->len); + assert (len > 0); /* Ensure alignment of length to read */ len = (len + SYSPROF_CAPTURE_ALIGN - 1) & ~(SYSPROF_CAPTURE_ALIGN - 1); if ((self->len - self->pos) < len) { - gssize r; + ssize_t r; if (self->len > self->pos) memmove (self->buf, &self->buf[self->pos], self->len - self->pos); @@ -370,8 +382,8 @@ sysprof_capture_reader_ensure_space_for (SysprofCaptureReader *self, while (self->len < len) { - g_assert ((self->pos + self->len) < self->bufsz); - g_assert (self->len < self->bufsz); + assert ((self->pos + self->len) < self->bufsz); + assert (self->len < self->bufsz); /* Read into our buffer after our current read position */ r = _sysprof_pread (self->fd, @@ -390,53 +402,53 @@ sysprof_capture_reader_ensure_space_for (SysprofCaptureReader *self, return (self->len - self->pos) >= len; } -gboolean +bool sysprof_capture_reader_skip (SysprofCaptureReader *self) { SysprofCaptureFrame *frame; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); if (!sysprof_capture_reader_ensure_space_for (self, sizeof (SysprofCaptureFrame))) - return FALSE; + return false; - frame = (SysprofCaptureFrame *)(gpointer)&self->buf[self->pos]; + frame = (SysprofCaptureFrame *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, frame); if (frame->len < sizeof (SysprofCaptureFrame)) - return FALSE; + return false; if (!sysprof_capture_reader_ensure_space_for (self, frame->len)) - return FALSE; + return false; - frame = (SysprofCaptureFrame *)(gpointer)&self->buf[self->pos]; + frame = (SysprofCaptureFrame *)(void *)&self->buf[self->pos]; self->pos += frame->len; if ((self->pos % SYSPROF_CAPTURE_ALIGN) != 0) - return FALSE; + return false; - return TRUE; + return true; } -gboolean +bool sysprof_capture_reader_peek_frame (SysprofCaptureReader *self, SysprofCaptureFrame *frame) { SysprofCaptureFrame *real_frame; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->len); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->len); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *real_frame)) - return FALSE; + return false; - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - real_frame = (SysprofCaptureFrame *)(gpointer)&self->buf[self->pos]; + real_frame = (SysprofCaptureFrame *)(void *)&self->buf[self->pos]; *frame = *real_frame; @@ -452,17 +464,17 @@ sysprof_capture_reader_peek_frame (SysprofCaptureReader *self, return frame->type > 0 && frame->type < SYSPROF_CAPTURE_FRAME_LAST; } -gboolean +bool sysprof_capture_reader_peek_type (SysprofCaptureReader *self, SysprofCaptureFrameType *type) { SysprofCaptureFrame frame; - g_assert (self != NULL); - g_assert (type != NULL); + assert (self != NULL); + assert (type != NULL); if (!sysprof_capture_reader_peek_frame (self, &frame)) - return FALSE; + return false; *type = frame.type; @@ -472,19 +484,19 @@ sysprof_capture_reader_peek_type (SysprofCaptureReader *self, static const SysprofCaptureFrame * sysprof_capture_reader_read_basic (SysprofCaptureReader *self, SysprofCaptureFrameType type, - gsize extra) + size_t extra) { SysprofCaptureFrame *frame; - gsize len = sizeof *frame + extra; + size_t len = sizeof *frame + extra; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, len)) return NULL; - frame = (SysprofCaptureFrame *)(gpointer)&self->buf[self->pos]; + frame = (SysprofCaptureFrame *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, frame); @@ -521,15 +533,15 @@ sysprof_capture_reader_read_fork (SysprofCaptureReader *self) { SysprofCaptureFork *fk; - g_assert (self != NULL); + assert (self != NULL); fk = (SysprofCaptureFork *) - sysprof_capture_reader_read_basic (self, SYSPROF_CAPTURE_FRAME_FORK, sizeof(guint32)); + sysprof_capture_reader_read_basic (self, SYSPROF_CAPTURE_FRAME_FORK, sizeof (uint32_t)); if (fk != NULL) { - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) - fk->child_pid = GUINT32_SWAP_LE_BE (fk->child_pid); + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + fk->child_pid = bswap_32 (fk->child_pid); } return fk; @@ -540,14 +552,14 @@ sysprof_capture_reader_read_map (SysprofCaptureReader *self) { SysprofCaptureMap *map; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *map)) return NULL; - map = (SysprofCaptureMap *)(gpointer)&self->buf[self->pos]; + map = (SysprofCaptureMap *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &map->frame); @@ -560,7 +572,7 @@ sysprof_capture_reader_read_map (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, map->frame.len)) return NULL; - map = (SysprofCaptureMap *)(gpointer)&self->buf[self->pos]; + map = (SysprofCaptureMap *)(void *)&self->buf[self->pos]; if (self->buf[self->pos + map->frame.len - 1] != '\0') return NULL; @@ -580,14 +592,14 @@ sysprof_capture_reader_read_log (SysprofCaptureReader *self) { SysprofCaptureLog *log; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *log)) return NULL; - log = (SysprofCaptureLog *)(gpointer)&self->buf[self->pos]; + log = (SysprofCaptureLog *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &log->frame); @@ -600,7 +612,7 @@ sysprof_capture_reader_read_log (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, log->frame.len)) return NULL; - log = (SysprofCaptureLog *)(gpointer)&self->buf[self->pos]; + log = (SysprofCaptureLog *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_log (self, log); @@ -612,7 +624,7 @@ sysprof_capture_reader_read_log (SysprofCaptureReader *self) /* Ensure trailing \0 in domain and message */ log->domain[sizeof log->domain - 1] = 0; if (log->frame.len > sizeof *log) - ((gchar *)log)[log->frame.len - 1] = 0; + ((char *)log)[log->frame.len - 1] = 0; return log; } @@ -622,14 +634,14 @@ sysprof_capture_reader_read_mark (SysprofCaptureReader *self) { SysprofCaptureMark *mark; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *mark)) return NULL; - mark = (SysprofCaptureMark *)(gpointer)&self->buf[self->pos]; + mark = (SysprofCaptureMark *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &mark->frame); @@ -642,7 +654,7 @@ sysprof_capture_reader_read_mark (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, mark->frame.len)) return NULL; - mark = (SysprofCaptureMark *)(gpointer)&self->buf[self->pos]; + mark = (SysprofCaptureMark *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_mark (self, mark); @@ -654,10 +666,10 @@ sysprof_capture_reader_read_mark (SysprofCaptureReader *self) /* Ensure trailing \0 in name and message */ mark->name[sizeof mark->name - 1] = 0; if (mark->frame.len > sizeof *mark) - ((gchar *)mark)[mark->frame.len - 1] = 0; + ((char *)mark)[mark->frame.len - 1] = 0; /* Maybe update end-time */ - if G_UNLIKELY ((mark->frame.time + mark->duration) > self->end_time) + if SYSPROF_UNLIKELY ((mark->frame.time + mark->duration) > self->end_time) self->end_time = mark->frame.time + mark->duration; return mark; @@ -668,14 +680,14 @@ sysprof_capture_reader_read_metadata (SysprofCaptureReader *self) { SysprofCaptureMetadata *metadata; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *metadata)) return NULL; - metadata = (SysprofCaptureMetadata *)(gpointer)&self->buf[self->pos]; + metadata = (SysprofCaptureMetadata *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &metadata->frame); @@ -688,7 +700,7 @@ sysprof_capture_reader_read_metadata (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, metadata->frame.len)) return NULL; - metadata = (SysprofCaptureMetadata *)(gpointer)&self->buf[self->pos]; + metadata = (SysprofCaptureMetadata *)(void *)&self->buf[self->pos]; self->pos += metadata->frame.len; @@ -698,7 +710,7 @@ sysprof_capture_reader_read_metadata (SysprofCaptureReader *self) /* Ensure trailing \0 in .id and .metadata */ metadata->id[sizeof metadata->id - 1] = 0; if (metadata->frame.len > sizeof *metadata) - ((gchar *)metadata)[metadata->frame.len - 1] = 0; + ((char *)metadata)[metadata->frame.len - 1] = 0; return metadata; } @@ -708,14 +720,14 @@ sysprof_capture_reader_read_process (SysprofCaptureReader *self) { SysprofCaptureProcess *process; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *process)) return NULL; - process = (SysprofCaptureProcess *)(gpointer)&self->buf[self->pos]; + process = (SysprofCaptureProcess *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &process->frame); @@ -728,7 +740,7 @@ sysprof_capture_reader_read_process (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, process->frame.len)) return NULL; - process = (SysprofCaptureProcess *)(gpointer)&self->buf[self->pos]; + process = (SysprofCaptureProcess *)(void *)&self->buf[self->pos]; if (self->buf[self->pos + process->frame.len - 1] != '\0') return NULL; @@ -741,23 +753,22 @@ sysprof_capture_reader_read_process (SysprofCaptureReader *self) return process; } -GHashTable * +const SysprofCaptureJitmap * sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self) { - g_autoptr(GHashTable) ret = NULL; SysprofCaptureJitmap *jitmap; - guint8 *buf; - guint8 *endptr; - guint i; + uint8_t *buf; + uint8_t *endptr; + unsigned int i; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *jitmap)) return NULL; - jitmap = (SysprofCaptureJitmap *)(gpointer)&self->buf[self->pos]; + jitmap = (SysprofCaptureJitmap *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &jitmap->frame); @@ -770,17 +781,15 @@ sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, jitmap->frame.len)) return NULL; - jitmap = (SysprofCaptureJitmap *)(gpointer)&self->buf[self->pos]; - - ret = g_hash_table_new_full (NULL, NULL, NULL, g_free); + jitmap = (SysprofCaptureJitmap *)(void *)&self->buf[self->pos]; buf = jitmap->data; endptr = &self->buf[self->pos + jitmap->frame.len]; + /* Check the strings are all nul-terminated. */ for (i = 0; i < jitmap->n_jitmaps; i++) { SysprofCaptureAddress addr; - const gchar *str; if (buf + sizeof addr >= endptr) return NULL; @@ -788,23 +797,19 @@ sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self) memcpy (&addr, buf, sizeof addr); buf += sizeof addr; - str = (gchar *)buf; - buf = memchr (buf, '\0', (endptr - buf)); if (buf == NULL) return NULL; buf++; - - g_hash_table_insert (ret, GSIZE_TO_POINTER (addr), g_strdup (str)); } sysprof_capture_reader_bswap_jitmap (self, jitmap); self->pos += jitmap->frame.len; - return g_steal_pointer (&ret); + return jitmap; } const SysprofCaptureSample * @@ -812,14 +817,14 @@ sysprof_capture_reader_read_sample (SysprofCaptureReader *self) { SysprofCaptureSample *sample; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *sample)) return NULL; - sample = (SysprofCaptureSample *)(gpointer)&self->buf[self->pos]; + sample = (SysprofCaptureSample *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &sample->frame); @@ -829,8 +834,8 @@ sysprof_capture_reader_read_sample (SysprofCaptureReader *self) if (sample->frame.len < sizeof *sample) return NULL; - if (self->endian != G_BYTE_ORDER) - sample->n_addrs = GUINT16_SWAP_LE_BE (sample->n_addrs); + if (self->endian != __BYTE_ORDER) + sample->n_addrs = bswap_16 (sample->n_addrs); if (sample->frame.len < (sizeof *sample + (sizeof(SysprofCaptureAddress) * sample->n_addrs))) return NULL; @@ -838,14 +843,14 @@ sysprof_capture_reader_read_sample (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, sample->frame.len)) return NULL; - sample = (SysprofCaptureSample *)(gpointer)&self->buf[self->pos]; + sample = (SysprofCaptureSample *)(void *)&self->buf[self->pos]; - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) { - guint i; + unsigned int i; for (i = 0; i < sample->n_addrs; i++) - sample->addrs[i] = GUINT64_SWAP_LE_BE (sample->addrs[i]); + sample->addrs[i] = bswap_64 (sample->addrs[i]); } self->pos += sample->frame.len; @@ -858,14 +863,14 @@ sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self) { SysprofCaptureCounterDefine *def; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *def)) return NULL; - def = (SysprofCaptureCounterDefine *)(gpointer)&self->buf[self->pos]; + def = (SysprofCaptureCounterDefine *)(void *)&self->buf[self->pos]; if (def->frame.type != SYSPROF_CAPTURE_FRAME_CTRDEF) return NULL; @@ -873,8 +878,8 @@ sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self) if (def->frame.len < sizeof *def) return NULL; - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) - def->n_counters = GUINT16_SWAP_LE_BE (def->n_counters); + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) + def->n_counters = bswap_16 (def->n_counters); if (def->frame.len < (sizeof *def + (sizeof (SysprofCaptureCounterDefine) * def->n_counters))) return NULL; @@ -882,16 +887,16 @@ sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, def->frame.len)) return NULL; - def = (SysprofCaptureCounterDefine *)(gpointer)&self->buf[self->pos]; + def = (SysprofCaptureCounterDefine *)(void *)&self->buf[self->pos]; - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) { - guint i; + unsigned int i; for (i = 0; i < def->n_counters; i++) { - def->counters[i].id = GUINT32_SWAP_LE_BE (def->counters[i].id); - def->counters[i].value.v64 = GUINT64_SWAP_LE_BE (def->counters[i].value.v64); + def->counters[i].id = bswap_32 (def->counters[i].id); + def->counters[i].value.v64 = bswap_64 (def->counters[i].value.v64); } } @@ -905,14 +910,14 @@ sysprof_capture_reader_read_counter_set (SysprofCaptureReader *self) { SysprofCaptureCounterSet *set; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *set)) return NULL; - set = (SysprofCaptureCounterSet *)(gpointer)&self->buf[self->pos]; + set = (SysprofCaptureCounterSet *)(void *)&self->buf[self->pos]; if (set->frame.type != SYSPROF_CAPTURE_FRAME_CTRSET) return NULL; @@ -920,8 +925,8 @@ sysprof_capture_reader_read_counter_set (SysprofCaptureReader *self) if (set->frame.len < sizeof *set) return NULL; - if (self->endian != G_BYTE_ORDER) - set->n_values = GUINT16_SWAP_LE_BE (set->n_values); + if (self->endian != __BYTE_ORDER) + set->n_values = bswap_16 (set->n_values); if (set->frame.len < (sizeof *set + (sizeof (SysprofCaptureCounterValues) * set->n_values))) return NULL; @@ -929,20 +934,20 @@ sysprof_capture_reader_read_counter_set (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, set->frame.len)) return NULL; - set = (SysprofCaptureCounterSet *)(gpointer)&self->buf[self->pos]; + set = (SysprofCaptureCounterSet *)(void *)&self->buf[self->pos]; - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) { - guint i; + unsigned int i; for (i = 0; i < set->n_values; i++) { - guint j; + unsigned int j; - for (j = 0; j < G_N_ELEMENTS (set->values[0].values); j++) + for (j = 0; j < SYSPROF_N_ELEMENTS (set->values[0].values); j++) { - set->values[i].ids[j] = GUINT32_SWAP_LE_BE (set->values[i].ids[j]); - set->values[i].values[j].v64 = GUINT64_SWAP_LE_BE (set->values[i].values[j].v64); + set->values[i].ids[j] = bswap_32 (set->values[i].ids[j]); + set->values[i].values[j].v64 = bswap_64 (set->values[i].values[j].v64); } } } @@ -952,25 +957,25 @@ sysprof_capture_reader_read_counter_set (SysprofCaptureReader *self) return set; } -gboolean +bool sysprof_capture_reader_reset (SysprofCaptureReader *self) { - g_assert (self != NULL); + assert (self != NULL); self->fd_off = sizeof (SysprofCaptureFileHeader); self->pos = 0; self->len = 0; - return TRUE; + return true; } SysprofCaptureReader * sysprof_capture_reader_ref (SysprofCaptureReader *self) { - g_assert (self != NULL); - g_assert (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - g_atomic_int_inc (&self->ref_count); + __atomic_fetch_add (&self->ref_count, 1, __ATOMIC_SEQ_CST); return self; } @@ -978,30 +983,26 @@ sysprof_capture_reader_ref (SysprofCaptureReader *self) void sysprof_capture_reader_unref (SysprofCaptureReader *self) { - g_assert (self != NULL); - g_assert (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - if (g_atomic_int_dec_and_test (&self->ref_count)) + if (__atomic_fetch_sub (&self->ref_count, 1, __ATOMIC_SEQ_CST) == 1) sysprof_capture_reader_finalize (self); } -gboolean -sysprof_capture_reader_splice (SysprofCaptureReader *self, - SysprofCaptureWriter *dest, - GError **error) +bool +sysprof_capture_reader_splice (SysprofCaptureReader *self, + SysprofCaptureWriter *dest) { - g_assert (self != NULL); - g_assert (self->fd != -1); - g_assert (dest != NULL); + assert (self != NULL); + assert (self->fd != -1); + assert (dest != NULL); /* Flush before writing anything to ensure consistency */ if (!sysprof_capture_writer_flush (dest)) { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - return FALSE; + /* errno is propagated */ + return false; } /* @@ -1009,33 +1010,35 @@ sysprof_capture_reader_splice (SysprofCaptureReader *self, * track the current position to avoid reseting it. */ - /* Perform the splice */ - return _sysprof_capture_writer_splice_from_fd (dest, self->fd, error); + /* Perform the splice; errno is propagated on failure */ + return _sysprof_capture_writer_splice_from_fd (dest, self->fd); } /** * sysprof_capture_reader_save_as: * @self: An #SysprofCaptureReader * @filename: the file to save the capture as - * @error: a location for a #GError or %NULL. * * This is a convenience function for copying a capture file for which * you may have already discarded the writer for. * - * Returns: %TRUE on success; otherwise %FALSE and @error is set. + * `errno` is set on failure. It may be any of the errors returned by + * `open()`, `fstat()`, `ftruncate()`, `lseek()` or `sendfile()`. + * + * Returns: %TRUE on success; otherwise %FALSE. */ -gboolean -sysprof_capture_reader_save_as (SysprofCaptureReader *self, - const gchar *filename, - GError **error) +bool +sysprof_capture_reader_save_as (SysprofCaptureReader *self, + const char *filename) { struct stat stbuf; off_t in_off; - gsize to_write; + size_t to_write; int fd = -1; + int errsv; - g_assert (self != NULL); - g_assert (filename != NULL); + assert (self != NULL); + assert (filename != NULL); if (-1 == (fd = open (filename, O_CREAT | O_WRONLY, 0640))) goto handle_errno; @@ -1054,7 +1057,7 @@ sysprof_capture_reader_save_as (SysprofCaptureReader *self, while (to_write > 0) { - gssize written; + ssize_t written; written = _sysprof_sendfile (fd, self->fd, &in_off, to_write); @@ -1064,37 +1067,36 @@ sysprof_capture_reader_save_as (SysprofCaptureReader *self, if (written == 0 && errno != EAGAIN) goto handle_errno; - g_assert (written <= (gssize)to_write); + assert (written <= (ssize_t)to_write); to_write -= written; } if (self->filename == NULL) - self->filename = g_strdup (filename); + self->filename = sysprof_strdup (filename); close (fd); - return TRUE; + return true; handle_errno: + errsv = errno; + if (fd != -1) close (fd); - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); + errno = errsv; - return FALSE; + return false; } -gint64 +int64_t sysprof_capture_reader_get_start_time (SysprofCaptureReader *self) { - g_return_val_if_fail (self != NULL, 0); + assert (self != NULL); - if (self->endian != G_BYTE_ORDER) - return GUINT64_SWAP_LE_BE (self->header.time); + if (self->endian != __BYTE_ORDER) + return bswap_64 (self->header.time); return self->header.time; } @@ -1114,22 +1116,22 @@ sysprof_capture_reader_get_start_time (SysprofCaptureReader *self) * * Since: 3.22.1 */ -gint64 +int64_t sysprof_capture_reader_get_end_time (SysprofCaptureReader *self) { - gint64 end_time = 0; + int64_t end_time = 0; - g_return_val_if_fail (self != NULL, 0); + assert (self != NULL); if (self->header.end_time != 0) { - if (self->endian != G_BYTE_ORDER) - end_time = GUINT64_SWAP_LE_BE (self->header.end_time); + if (self->endian != __BYTE_ORDER) + end_time = bswap_64 (self->header.end_time); else end_time = self->header.end_time; } - return MAX (self->end_time, end_time); + return (self->end_time > end_time) ? self->end_time : end_time; } /** @@ -1148,23 +1150,36 @@ sysprof_capture_reader_copy (SysprofCaptureReader *self) SysprofCaptureReader *copy; int fd; - g_return_val_if_fail (self != NULL, NULL); + assert (self != NULL); if (-1 == (fd = dup (self->fd))) return NULL; - copy = g_new0 (SysprofCaptureReader, 1); + copy = sysprof_malloc0 (sizeof (SysprofCaptureReader)); + if (copy == NULL) + { + close (fd); + return NULL; + } *copy = *self; copy->ref_count = 1; - copy->filename = g_strdup (self->filename); + copy->filename = sysprof_strdup (self->filename); copy->fd = fd; copy->end_time = self->end_time; copy->st_buf = self->st_buf; copy->st_buf_set = self->st_buf_set; - copy->buf = g_malloc (self->bufsz); + copy->buf = malloc (self->bufsz); + if (copy->buf == NULL) + { + close (fd); + free (copy->filename); + free (copy); + return NULL; + } + memcpy (copy->buf, self->buf, self->bufsz); return copy; @@ -1174,25 +1189,25 @@ void sysprof_capture_reader_set_stat (SysprofCaptureReader *self, const SysprofCaptureStat *st_buf) { - g_return_if_fail (self != NULL); + assert (self != NULL); if (st_buf != NULL) { self->st_buf = *st_buf; - self->st_buf_set = TRUE; + self->st_buf_set = true; } else { memset (&self->st_buf, 0, sizeof (self->st_buf)); - self->st_buf_set = FALSE; + self->st_buf_set = false; } } -gboolean +bool sysprof_capture_reader_get_stat (SysprofCaptureReader *self, SysprofCaptureStat *st_buf) { - g_return_val_if_fail (self != NULL, FALSE); + assert (self != NULL); if (st_buf != NULL) *st_buf = self->st_buf; @@ -1205,14 +1220,14 @@ sysprof_capture_reader_read_file (SysprofCaptureReader *self) { SysprofCaptureFileChunk *file_chunk; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *file_chunk)) return NULL; - file_chunk = (SysprofCaptureFileChunk *)(gpointer)&self->buf[self->pos]; + file_chunk = (SysprofCaptureFileChunk *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &file_chunk->frame); @@ -1225,7 +1240,7 @@ sysprof_capture_reader_read_file (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, file_chunk->frame.len)) return NULL; - file_chunk = (SysprofCaptureFileChunk *)(gpointer)&self->buf[self->pos]; + file_chunk = (SysprofCaptureFileChunk *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_file_chunk (self, file_chunk); @@ -1244,19 +1259,59 @@ sysprof_capture_reader_read_file (SysprofCaptureReader *self) return file_chunk; } -gchar ** +static bool +array_append (const char ***files, + size_t *n_files, + size_t *n_files_allocated, + const char *new_element) +{ + if (*n_files == *n_files_allocated) + { + const char **new_files; + + *n_files_allocated = (*n_files_allocated > 0) ? 2 * *n_files_allocated : 4; + new_files = reallocarray (*files, *n_files_allocated, sizeof (**files)); + if (new_files == NULL) + return false; + *files = new_files; + } + + (*files)[*n_files] = new_element; + *n_files = *n_files + 1; + assert (*n_files <= *n_files_allocated); + + return true; +} + +static void +array_deduplicate (const char **files, + size_t *n_files) +{ + size_t last_written, next_to_read; + + if (*n_files == 0) + return; + + for (last_written = 0, next_to_read = 1; last_written <= next_to_read && next_to_read < *n_files;) + { + if (strcmp (files[next_to_read], files[last_written]) == 0) + next_to_read++; + else + files[++last_written] = files[next_to_read++]; + } + + assert (last_written + 1 <= *n_files); + *n_files = last_written + 1; +} + +const char ** sysprof_capture_reader_list_files (SysprofCaptureReader *self) { - g_autoptr(GHashTable) files = NULL; - g_autoptr(GPtrArray) ar = NULL; + const char **files = NULL; + size_t n_files = 0, n_files_allocated = 0; SysprofCaptureFrameType type; - GHashTableIter iter; - const gchar *key; - g_assert (self != NULL); - - ar = g_ptr_array_new_with_free_func (g_free); - files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + assert (self != NULL); while (sysprof_capture_reader_peek_type (self, &type)) { @@ -1271,44 +1326,55 @@ sysprof_capture_reader_list_files (SysprofCaptureReader *self) if (!(file = sysprof_capture_reader_read_file (self))) break; - if (!g_hash_table_contains (files, file->path)) - g_hash_table_insert (files, g_strdup (file->path), NULL); + if (!array_append (&files, &n_files, &n_files_allocated, file->path)) + { + free (files); + errno = ENOMEM; + return NULL; + } } - g_hash_table_iter_init (&iter, files); - while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL)) - g_ptr_array_add (ar, g_strdup (key)); - g_ptr_array_add (ar, NULL); + /* Sort and deduplicate the files array. */ + qsort (files, n_files, sizeof (*files), (int (*)(const void *, const void *)) strcmp); + array_deduplicate (files, &n_files); - return (gchar **)g_ptr_array_free (g_steal_pointer (&ar), FALSE); + /* Add a null terminator */ + if (!array_append (&files, &n_files, &n_files_allocated, NULL)) + { + free (files); + errno = ENOMEM; + return NULL; + } + + return sysprof_steal_pointer (&files); } -gboolean +bool sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self, - const gchar *path, - gint fd) + const char *path, + int fd) { - g_assert (self != NULL); - g_assert (path != NULL); - g_assert (fd > -1); + assert (self != NULL); + assert (path != NULL); + assert (fd > -1); for (;;) { SysprofCaptureFrameType type; const SysprofCaptureFileChunk *file; - const guint8 *buf; - gsize to_write; + const uint8_t *buf; + size_t to_write; if (!sysprof_capture_reader_peek_type (self, &type)) - return FALSE; + return false; if (type != SYSPROF_CAPTURE_FRAME_FILE_CHUNK) goto skip; if (!(file = sysprof_capture_reader_read_file (self))) - return FALSE; + return false; - if (g_strcmp0 (path, file->path) != 0) + if (strcmp (path, file->path) != 0) goto skip; buf = file->data; @@ -1316,16 +1382,16 @@ sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self, while (to_write > 0) { - gssize written; + ssize_t written; written = _sysprof_write (fd, buf, to_write); if (written < 0) - return FALSE; + return false; if (written == 0 && errno != EAGAIN) - return FALSE; + return false; - g_assert (written <= (gssize)to_write); + assert (written <= (ssize_t)to_write); buf += written; to_write -= written; @@ -1334,32 +1400,32 @@ sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self, if (!file->is_last) continue; - return TRUE; + return true; skip: if (!sysprof_capture_reader_skip (self)) - return FALSE; + return false; } - g_return_val_if_reached (FALSE); + sysprof_assert_not_reached (); } -gint +int sysprof_capture_reader_get_byte_order (SysprofCaptureReader *self) { - g_return_val_if_fail (self != NULL, 0); + assert (self != NULL); return self->endian; } const SysprofCaptureFileChunk * sysprof_capture_reader_find_file (SysprofCaptureReader *self, - const gchar *path) + const char *path) { SysprofCaptureFrameType type; - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (path != NULL, NULL); + assert (self != NULL); + assert (path != NULL); while (sysprof_capture_reader_peek_type (self, &type)) { @@ -1370,7 +1436,7 @@ sysprof_capture_reader_find_file (SysprofCaptureReader *self, if (!(fc = sysprof_capture_reader_read_file (self))) break; - if (g_strcmp0 (path, fc->path) == 0) + if (strcmp (path, fc->path) == 0) return fc; continue; @@ -1388,14 +1454,14 @@ sysprof_capture_reader_read_allocation (SysprofCaptureReader *self) { SysprofCaptureAllocation *ma; - g_assert (self != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); - g_assert (self->pos <= self->bufsz); + assert (self != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self->pos <= self->bufsz); if (!sysprof_capture_reader_ensure_space_for (self, sizeof *ma)) return NULL; - ma = (SysprofCaptureAllocation *)(gpointer)&self->buf[self->pos]; + ma = (SysprofCaptureAllocation *)(void *)&self->buf[self->pos]; sysprof_capture_reader_bswap_frame (self, &ma->frame); @@ -1405,12 +1471,12 @@ sysprof_capture_reader_read_allocation (SysprofCaptureReader *self) if (ma->frame.len < sizeof *ma) return NULL; - if (self->endian != G_BYTE_ORDER) + if (self->endian != __BYTE_ORDER) { - ma->n_addrs = GUINT16_SWAP_LE_BE (ma->n_addrs); - ma->alloc_size = GUINT64_SWAP_LE_BE (ma->alloc_size); - ma->alloc_addr = GUINT64_SWAP_LE_BE (ma->alloc_addr); - ma->tid = GUINT32_SWAP_LE_BE (ma->tid); + ma->n_addrs = bswap_16 (ma->n_addrs); + ma->alloc_size = bswap_64 (ma->alloc_size); + ma->alloc_addr = bswap_64 (ma->alloc_addr); + ma->tid = bswap_32 (ma->tid); } if (ma->frame.len < (sizeof *ma + (sizeof(SysprofCaptureAddress) * ma->n_addrs))) @@ -1419,15 +1485,65 @@ sysprof_capture_reader_read_allocation (SysprofCaptureReader *self) if (!sysprof_capture_reader_ensure_space_for (self, ma->frame.len)) return NULL; - ma = (SysprofCaptureAllocation *)(gpointer)&self->buf[self->pos]; + ma = (SysprofCaptureAllocation *)(void *)&self->buf[self->pos]; - if (G_UNLIKELY (self->endian != G_BYTE_ORDER)) + if (SYSPROF_UNLIKELY (self->endian != __BYTE_ORDER)) { - for (guint i = 0; i < ma->n_addrs; i++) - ma->addrs[i] = GUINT64_SWAP_LE_BE (ma->addrs[i]); + for (unsigned int i = 0; i < ma->n_addrs; i++) + ma->addrs[i] = bswap_64 (ma->addrs[i]); } self->pos += ma->frame.len; return ma; } + +typedef struct { + const SysprofCaptureJitmap *jitmap; + const uint8_t *buf; + unsigned int i; + + void *padding1; + void *padding2; +} RealSysprofCaptureJitmapIter; + +void +sysprof_capture_jitmap_iter_init (SysprofCaptureJitmapIter *iter, + const SysprofCaptureJitmap *jitmap) +{ + RealSysprofCaptureJitmapIter *real_iter = (RealSysprofCaptureJitmapIter *) iter; + + assert (iter != NULL); + assert (jitmap != NULL); + + real_iter->jitmap = jitmap; + real_iter->buf = jitmap->data; + real_iter->i = 0; +} + +bool +sysprof_capture_jitmap_iter_next (SysprofCaptureJitmapIter *iter, + SysprofCaptureAddress *addr, + const char **name) +{ + RealSysprofCaptureJitmapIter *real_iter = (RealSysprofCaptureJitmapIter *) iter; + const char *_name; + + assert (iter != NULL); + + if (real_iter->i >= real_iter->jitmap->n_jitmaps) + return false; + + if (addr != NULL) + memcpy (addr, real_iter->buf, sizeof (*addr)); + real_iter->buf += sizeof (*addr); + + _name = (const char *) real_iter->buf; + if (name != NULL) + *name = _name; + real_iter->buf += strlen (_name) + 1; + + real_iter->i++; + + return true; +} diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h index 3c58524c..c802e0a5 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.h +++ b/src/libsysprof-capture/sysprof-capture-reader.h @@ -56,19 +56,20 @@ #pragma once +#include + #include "sysprof-capture-types.h" +#include "sysprof-macros.h" #include "sysprof-version-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS typedef struct _SysprofCaptureReader SysprofCaptureReader; SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureReader *sysprof_capture_reader_new (const gchar *filename, - GError **error); +SysprofCaptureReader *sysprof_capture_reader_new (const char *filename); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureReader *sysprof_capture_reader_new_from_fd (int fd, - GError **error); +SysprofCaptureReader *sysprof_capture_reader_new_from_fd (int fd); SYSPROF_AVAILABLE_IN_ALL SysprofCaptureReader *sysprof_capture_reader_copy (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL @@ -76,22 +77,22 @@ SysprofCaptureReader *sysprof_capture_reader_ref ( SYSPROF_AVAILABLE_IN_ALL void sysprof_capture_reader_unref (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gint sysprof_capture_reader_get_byte_order (SysprofCaptureReader *self); +int sysprof_capture_reader_get_byte_order (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -const gchar *sysprof_capture_reader_get_filename (SysprofCaptureReader *self); +const char *sysprof_capture_reader_get_filename (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -const gchar *sysprof_capture_reader_get_time (SysprofCaptureReader *self); +const char *sysprof_capture_reader_get_time (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gint64 sysprof_capture_reader_get_start_time (SysprofCaptureReader *self); +int64_t sysprof_capture_reader_get_start_time (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gint64 sysprof_capture_reader_get_end_time (SysprofCaptureReader *self); +int64_t sysprof_capture_reader_get_end_time (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_skip (SysprofCaptureReader *self); +bool sysprof_capture_reader_skip (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_peek_type (SysprofCaptureReader *self, +bool sysprof_capture_reader_peek_type (SysprofCaptureReader *self, SysprofCaptureFrameType *type); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_peek_frame (SysprofCaptureReader *self, +bool sysprof_capture_reader_peek_frame (SysprofCaptureReader *self, SysprofCaptureFrame *frame); SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureLog *sysprof_capture_reader_read_log (SysprofCaptureReader *self); @@ -112,7 +113,7 @@ const SysprofCaptureProcess *sysprof_capture_reader_read_process ( SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureSample *sysprof_capture_reader_read_sample (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -GHashTable *sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self); +const SysprofCaptureJitmap *sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureCounterDefine *sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL @@ -122,31 +123,44 @@ const SysprofCaptureFileChunk *sysprof_capture_reader_read_file ( SYSPROF_AVAILABLE_IN_3_36 const SysprofCaptureAllocation *sysprof_capture_reader_read_allocation (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_reset (SysprofCaptureReader *self); +bool sysprof_capture_reader_reset (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_splice (SysprofCaptureReader *self, - SysprofCaptureWriter *dest, - GError **error); +bool sysprof_capture_reader_splice (SysprofCaptureReader *self, + SysprofCaptureWriter *dest); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_save_as (SysprofCaptureReader *self, - const gchar *filename, - GError **error); +bool sysprof_capture_reader_save_as (SysprofCaptureReader *self, + const char *filename); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_get_stat (SysprofCaptureReader *self, +bool sysprof_capture_reader_get_stat (SysprofCaptureReader *self, SysprofCaptureStat *st_buf); SYSPROF_AVAILABLE_IN_ALL void sysprof_capture_reader_set_stat (SysprofCaptureReader *self, const SysprofCaptureStat *st_buf); SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureFileChunk *sysprof_capture_reader_find_file (SysprofCaptureReader *self, - const gchar *path); + const char *path); SYSPROF_AVAILABLE_IN_ALL -gchar **sysprof_capture_reader_list_files (SysprofCaptureReader *self); +const char **sysprof_capture_reader_list_files (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self, - const gchar *path, - gint fd); +bool sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self, + const char *path, + int fd); -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureReader, sysprof_capture_reader_unref) +typedef struct { + /*< private >*/ + void *p1; + void *p2; + unsigned int u1; + void *p3; + void *p4; +} SysprofCaptureJitmapIter; -G_END_DECLS +SYSPROF_AVAILABLE_IN_3_38 +void sysprof_capture_jitmap_iter_init (SysprofCaptureJitmapIter *iter, + const SysprofCaptureJitmap *jitmap); +SYSPROF_AVAILABLE_IN_3_38 +bool sysprof_capture_jitmap_iter_next (SysprofCaptureJitmapIter *iter, + SysprofCaptureAddress *addr, + const char **path); + +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-capture-types.h b/src/libsysprof-capture/sysprof-capture-types.h index fab5ba13..2031fc7e 100644 --- a/src/libsysprof-capture/sysprof-capture-types.h +++ b/src/libsysprof-capture/sysprof-capture-types.h @@ -56,13 +56,18 @@ #pragma once -#include +#include +#include +#include +#include +#include #include "sysprof-clock.h" +#include "sysprof-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS -#define SYSPROF_CAPTURE_MAGIC (GUINT32_TO_LE(0xFDCA975E)) +#define SYSPROF_CAPTURE_MAGIC (htole32(0xFDCA975E)) #define SYSPROF_CAPTURE_ALIGN (sizeof(SysprofCaptureAddress)) #if defined(_MSC_VER) @@ -73,14 +78,16 @@ G_BEGIN_DECLS # define SYSPROF_ALIGNED_END(_N) __attribute__((aligned ((_N)))) #endif -#define SYSPROF_CAPTURE_ADDRESS_FORMAT "0x%016" G_GINT64_MODIFIER "x" +#define SYSPROF_CAPTURE_ADDRESS_FORMAT "0x%016" PRIx64 -#if GLIB_SIZEOF_VOID_P == 8 -# define SYSPROF_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE000000000000000) -#elif GLIB_SIZEOF_VOID_P == 4 -# define SYSPROF_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE0000000) +static_assert (sizeof (void *) == sizeof (uintptr_t), + "UINTPTR_MAX can’t be used to determine sizeof(void*) at compile time"); +#if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu +# define SYSPROF_CAPTURE_JITMAP_MARK SYSPROF_UINT64_CONSTANT(0xE000000000000000) +#elif UINTPTR_MAX == 0xFFFFFFFF +# define SYSPROF_CAPTURE_JITMAP_MARK SYSPROF_UINT64_CONSTANT(0xE0000000) #else -#error Unknown GLIB_SIZEOF_VOID_P +#error Unknown UINTPTR_MAX #endif #define SYSPROF_CAPTURE_CURRENT_TIME (sysprof_clock_get_current_time()) @@ -92,25 +99,25 @@ typedef struct _SysprofCaptureWriter SysprofCaptureWriter; typedef struct _SysprofCaptureCursor SysprofCaptureCursor; typedef struct _SysprofCaptureCondition SysprofCaptureCondition; -typedef guint64 SysprofCaptureAddress; +typedef uint64_t SysprofCaptureAddress; typedef struct { /* * The number of frames indexed by SysprofCaptureFrameType */ - gsize frame_count[16]; + size_t frame_count[16]; /* * Padding for future expansion. */ - gsize padding[48]; + size_t padding[48]; } SysprofCaptureStat; typedef union { - gint64 v64; - gdouble vdbl; + int64_t v64; + double vdbl; } SysprofCaptureCounterValue; typedef enum @@ -137,28 +144,28 @@ typedef enum SYSPROF_ALIGNED_BEGIN(1) typedef struct { - guint32 magic; - guint32 version : 8; - guint32 little_endian : 1; - guint32 padding : 23; - gchar capture_time[64]; - gint64 time; - gint64 end_time; - gchar suffix[168]; + uint32_t magic; + uint32_t version : 8; + uint32_t little_endian : 1; + uint32_t padding : 23; + char capture_time[64]; + int64_t time; + int64_t end_time; + char suffix[168]; } SysprofCaptureFileHeader SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_BEGIN(1) typedef struct { - guint16 len; - gint16 cpu; - gint32 pid; - gint64 time; - guint32 type : 8; - guint32 padding1 : 24; - guint32 padding2; - guint8 data[0]; + uint16_t len; + int16_t cpu; + int32_t pid; + int64_t time; + uint32_t type : 8; + uint32_t padding1 : 24; + uint32_t padding2; + uint8_t data[0]; } SysprofCaptureFrame SYSPROF_ALIGNED_END(1); @@ -166,11 +173,11 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint64 start; - guint64 end; - guint64 offset; - guint64 inode; - gchar filename[0]; + uint64_t start; + uint64_t end; + uint64_t offset; + uint64_t inode; + char filename[0]; } SysprofCaptureMap SYSPROF_ALIGNED_END(1); @@ -178,8 +185,8 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint32 n_jitmaps; - guint8 data[0]; + uint32_t n_jitmaps; + uint8_t data[0]; } SysprofCaptureJitmap SYSPROF_ALIGNED_END(1); @@ -187,7 +194,7 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - gchar cmdline[0]; + char cmdline[0]; } SysprofCaptureProcess SYSPROF_ALIGNED_END(1); @@ -195,9 +202,9 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint32 n_addrs : 16; - guint32 padding1 : 16; - gint32 tid; + uint32_t n_addrs : 16; + uint32_t padding1 : 16; + int32_t tid; SysprofCaptureAddress addrs[0]; } SysprofCaptureSample SYSPROF_ALIGNED_END(1); @@ -206,7 +213,7 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - gint32 child_pid; + int32_t child_pid; } SysprofCaptureFork SYSPROF_ALIGNED_END(1); @@ -227,11 +234,11 @@ SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_BEGIN(1) typedef struct { - gchar category[32]; - gchar name[32]; - gchar description[52]; - guint32 id : 24; - guint32 type : 8; + char category[32]; + char name[32]; + char description[52]; + uint32_t id : 24; + uint32_t type : 8; SysprofCaptureCounterValue value; } SysprofCaptureCounter SYSPROF_ALIGNED_END(1); @@ -240,9 +247,9 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint32 n_counters : 16; - guint32 padding1 : 16; - guint32 padding2; + uint32_t n_counters : 16; + uint32_t padding1 : 16; + uint32_t padding2; SysprofCaptureCounter counters[0]; } SysprofCaptureCounterDefine SYSPROF_ALIGNED_END(1); @@ -255,7 +262,7 @@ typedef struct * bytes. So this makes a nice 2-cacheline aligned size which is * useful when the number of counters is rather small. */ - guint32 ids[8]; + uint32_t ids[8]; SysprofCaptureCounterValue values[8]; } SysprofCaptureCounterValues SYSPROF_ALIGNED_END(1); @@ -264,9 +271,9 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint32 n_values : 16; - guint32 padding1 : 16; - guint32 padding2; + uint32_t n_values : 16; + uint32_t padding1 : 16; + uint32_t padding2; SysprofCaptureCounterValues values[0]; } SysprofCaptureCounterSet SYSPROF_ALIGNED_END(1); @@ -275,10 +282,10 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - gint64 duration; - gchar group[24]; - gchar name[40]; - gchar message[0]; + int64_t duration; + char group[24]; + char name[40]; + char message[0]; } SysprofCaptureMark SYSPROF_ALIGNED_END(1); @@ -286,8 +293,8 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - gchar id[40]; - gchar metadata[0]; + char id[40]; + char metadata[0]; } SysprofCaptureMetadata SYSPROF_ALIGNED_END(1); @@ -295,11 +302,11 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint32 severity : 16; - guint32 padding1 : 16; - guint32 padding2 : 32; - gchar domain[32]; - gchar message[0]; + uint32_t severity : 16; + uint32_t padding1 : 16; + uint32_t padding2 : 32; + char domain[32]; + char message[0]; } SysprofCaptureLog SYSPROF_ALIGNED_END(1); @@ -307,11 +314,11 @@ SYSPROF_ALIGNED_BEGIN(1) typedef struct { SysprofCaptureFrame frame; - guint32 is_last : 1; - guint32 padding1 : 15; - guint32 len : 16; - gchar path[256]; - guint8 data[0]; + uint32_t is_last : 1; + uint32_t padding1 : 15; + uint32_t len : 16; + char path[256]; + uint8_t data[0]; } SysprofCaptureFileChunk SYSPROF_ALIGNED_END(1); @@ -320,37 +327,37 @@ typedef struct { SysprofCaptureFrame frame; SysprofCaptureAddress alloc_addr; - gint64 alloc_size; - gint32 tid; - guint32 n_addrs : 16; - guint32 padding1 : 16; + int64_t alloc_size; + int32_t tid; + uint32_t n_addrs : 16; + uint32_t padding1 : 16; SysprofCaptureAddress addrs[0]; } SysprofCaptureAllocation SYSPROF_ALIGNED_END(1); -G_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256); -G_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24); -G_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56); -G_STATIC_ASSERT (sizeof (SysprofCaptureJitmap) == 28); -G_STATIC_ASSERT (sizeof (SysprofCaptureProcess) == 24); -G_STATIC_ASSERT (sizeof (SysprofCaptureSample) == 32); -G_STATIC_ASSERT (sizeof (SysprofCaptureFork) == 28); -G_STATIC_ASSERT (sizeof (SysprofCaptureExit) == 24); -G_STATIC_ASSERT (sizeof (SysprofCaptureTimestamp) == 24); -G_STATIC_ASSERT (sizeof (SysprofCaptureCounter) == 128); -G_STATIC_ASSERT (sizeof (SysprofCaptureCounterValues) == 96); -G_STATIC_ASSERT (sizeof (SysprofCaptureCounterDefine) == 32); -G_STATIC_ASSERT (sizeof (SysprofCaptureCounterSet) == 32); -G_STATIC_ASSERT (sizeof (SysprofCaptureMark) == 96); -G_STATIC_ASSERT (sizeof (SysprofCaptureMetadata) == 64); -G_STATIC_ASSERT (sizeof (SysprofCaptureLog) == 64); -G_STATIC_ASSERT (sizeof (SysprofCaptureFileChunk) == 284); -G_STATIC_ASSERT (sizeof (SysprofCaptureAllocation) == 48); +static_assert (sizeof (SysprofCaptureFileHeader) == 256, "SysprofCaptureFileHeader changed size"); +static_assert (sizeof (SysprofCaptureFrame) == 24, "SysprofCaptureFrame changed size"); +static_assert (sizeof (SysprofCaptureMap) == 56, "SysprofCaptureMap changed size"); +static_assert (sizeof (SysprofCaptureJitmap) == 28, "SysprofCaptureJitmap changed size"); +static_assert (sizeof (SysprofCaptureProcess) == 24, "SysprofCaptureProcess changed size"); +static_assert (sizeof (SysprofCaptureSample) == 32, "SysprofCaptureSample changed size"); +static_assert (sizeof (SysprofCaptureFork) == 28, "SysprofCaptureFork changed size"); +static_assert (sizeof (SysprofCaptureExit) == 24, "SysprofCaptureExit changed size"); +static_assert (sizeof (SysprofCaptureTimestamp) == 24, "SysprofCaptureTimestamp changed size"); +static_assert (sizeof (SysprofCaptureCounter) == 128, "SysprofCaptureCounter changed size"); +static_assert (sizeof (SysprofCaptureCounterValues) == 96, "SysprofCaptureCounterValues changed size"); +static_assert (sizeof (SysprofCaptureCounterDefine) == 32, "SysprofCaptureCounterDefine changed size"); +static_assert (sizeof (SysprofCaptureCounterSet) == 32, "SysprofCaptureCounterSet changed size"); +static_assert (sizeof (SysprofCaptureMark) == 96, "SysprofCaptureMark changed size"); +static_assert (sizeof (SysprofCaptureMetadata) == 64, "SysprofCaptureMetadata changed size"); +static_assert (sizeof (SysprofCaptureLog) == 64, "SysprofCaptureLog changed size"); +static_assert (sizeof (SysprofCaptureFileChunk) == 284, "SysprofCaptureFileChunk changed size"); +static_assert (sizeof (SysprofCaptureAllocation) == 48, "SysprofCaptureAllocation changed size"); -G_STATIC_ASSERT ((G_STRUCT_OFFSET (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0); -G_STATIC_ASSERT ((G_STRUCT_OFFSET (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0); +static_assert ((offsetof (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureAllocation.addrs is not aligned"); +static_assert ((offsetof (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureSample.addrs is not aligned"); -static inline gint +static inline int sysprof_capture_address_compare (SysprofCaptureAddress a, SysprofCaptureAddress b) { @@ -362,4 +369,17 @@ sysprof_capture_address_compare (SysprofCaptureAddress a, return 0; } -G_END_DECLS +/** + * SysprofBacktraceFunc: + * @addrs: (inout) (array length=n_addrs): an array to place addresses + * into the capture frame + * @n_addrs: the length of @addrs + * @user_data: (scope call): closure data for the callback + * + * Returns: the number of addresses filled in @addrs + */ +typedef int (*SysprofBacktraceFunc) (SysprofCaptureAddress *addrs, + unsigned int n_addrs, + void *user_data); + +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-capture-util-private.h b/src/libsysprof-capture/sysprof-capture-util-private.h index 5350a178..1b1d93e9 100644 --- a/src/libsysprof-capture/sysprof-capture-util-private.h +++ b/src/libsysprof-capture/sysprof-capture-util-private.h @@ -56,14 +56,24 @@ #pragma once -#include - #ifdef __linux__ # include #endif +#include +#include #include +static inline void * +sysprof_malloc0 (size_t size) +{ + void *ptr = malloc (size); + if (ptr == NULL) + return NULL; + memset (ptr, 0, size); + return ptr; +} + #ifdef __linux__ # define _sysprof_getpagesize() getpagesize() # define _sysprof_pread(a,b,c,d) pread(a,b,c,d) @@ -84,10 +94,17 @@ ssize_t _sysprof_pwrite (int fd, ssize_t _sysprof_write (int fd, const void *buf, size_t count); -gint32 _sysprof_getpid (void); +int32_t _sysprof_getpid (void); ssize_t _sysprof_sendfile (int out_fd, int in_fd, off_t *offset, size_t count); - +#endif + +#ifdef HAVE_STRLCPY +# define _sysprof_strlcpy(d,s,ds) strlcpy(d,s,ds) +#else +size_t _sysprof_strlcpy (char *dest, + const char *src, + size_t dest_size); #endif diff --git a/src/libsysprof-capture/sysprof-capture-util.c b/src/libsysprof-capture/sysprof-capture-util.c index 58336e7f..0bbea06a 100644 --- a/src/libsysprof-capture/sysprof-capture-util.c +++ b/src/libsysprof-capture/sysprof-capture-util.c @@ -54,24 +54,23 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-capture-util" - #include "config.h" +#include #include -#include #include -#ifdef G_OS_WIN32 +#ifdef _WIN32 # include # define WIN32_LEAN_AND_MEAN # include #endif #include "sysprof-capture-util-private.h" +#include "sysprof-macros.h" -#ifdef G_OS_WIN32 -static G_LOCK_DEFINE (_sysprof_io_sync); +#ifdef _WIN32 +static void *_sysprof_io_sync_lock = SRWLOCK_INIT; #endif size_t @@ -79,9 +78,9 @@ size_t { static size_t pgsz = 0; - if G_UNLIKELY (pgsz == 0) + if SYSPROF_UNLIKELY (pgsz == 0) { -#ifdef G_OS_WIN32 +#ifdef _WIN32 SYSTEM_INFO system_info; GetSystemInfo (&system_info); pgsz = system_info.dwPageSize; @@ -99,14 +98,14 @@ ssize_t size_t count, off_t offset) { -#ifdef G_OS_WIN32 +#ifdef _WIN32 ssize_t ret = -1; - G_LOCK (_sysprof_io_sync); + AcquireSRWLockExclusive (_sysprof_io_sync_lock); errno = 0; if (lseek (fd, offset, SEEK_SET) != -1) ret = read (fd, buf, count); - G_UNLOCK (_sysprof_io_sync); + ReleaseSRWLockExclusive (_sysprof_io_sync_lock); return ret; #else @@ -121,14 +120,14 @@ ssize_t size_t count, off_t offset) { -#ifdef G_OS_WIN32 +#ifdef _WIN32 ssize_t ret = -1; - G_LOCK (_sysprof_io_sync); + AcquireSRWLockExclusive (_sysprof_io_sync_lock); errno = 0; if (lseek (fd, offset, SEEK_SET) != -1) ret = write (fd, buf, count); - G_UNLOCK (_sysprof_io_sync); + ReleaseSRWLockExclusive (_sysprof_io_sync_lock); return ret; #else @@ -142,13 +141,13 @@ ssize_t const void *buf, size_t count) { -#ifdef G_OS_WIN32 +#ifdef _WIN32 ssize_t ret = -1; - G_LOCK (_sysprof_io_sync); + AcquireSRWLockExclusive (_sysprof_io_sync_lock); errno = 0; ret = write (fd, buf, count); - G_UNLOCK (_sysprof_io_sync); + ReleaseSRWLockExclusive (_sysprof_io_sync_lock); return ret; #else @@ -157,10 +156,10 @@ ssize_t #endif } -gint32 +int32_t (_sysprof_getpid) (void) { -#ifdef G_OS_WIN32 +#ifdef _WIN32 return _getpid (); #else return getpid (); @@ -205,14 +204,14 @@ ssize_t if (n_read <= 0) return -1; - g_assert (count >= n_read); + assert (count >= n_read); count -= n_read; rpos += n_read; while (wpos < rpos) { - g_assert (off < sizeof buf); + assert (off < sizeof buf); errno = 0; n_written = write (out_fd, &buf[off], rpos - wpos); @@ -226,7 +225,7 @@ ssize_t } } - g_assert (count == 0); + assert (count == 0); if (offset != NULL) *offset = rpos; @@ -234,3 +233,23 @@ ssize_t errno = 0; return total; } + +size_t +(_sysprof_strlcpy) (char *dest, + const char *src, + size_t dest_size) +{ + size_t i = 0; + + if (dest_size > 0) + { + for (; i < dest_size - 1 && src[i] != '\0'; i++) + dest[i] = src[i]; + dest[i] = '\0'; + } + + for (; src[i] != '\0'; i++) + ; + + return i; +} diff --git a/src/libsysprof-capture/sysprof-capture-writer-cat.c b/src/libsysprof-capture/sysprof-capture-writer-cat.c index 0e473f40..66171b92 100644 --- a/src/libsysprof-capture/sysprof-capture-writer-cat.c +++ b/src/libsysprof-capture/sysprof-capture-writer-cat.c @@ -54,21 +54,31 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-cat" - #include "config.h" -#include +#include +#include +#include +#include #include -#include #include +#include "sysprof-capture.h" +#include "sysprof-macros-internal.h" + typedef struct { - guint64 src; - guint64 dst; + uint64_t src; + uint64_t dst; } TranslateItem; +typedef struct +{ + TranslateItem *items; + size_t n_items; + size_t n_items_allocated; +} TranslateTable; + enum { TRANSLATE_ADDR, TRANSLATE_CTR, @@ -76,15 +86,19 @@ enum { }; static void -translate_table_clear (GArray **tables, - guint table) +translate_table_clear (TranslateTable *tables, + unsigned int table) { - g_clear_pointer (&tables[table], g_array_unref); + TranslateTable *table_ptr = &tables[table]; + + sysprof_clear_pointer (&table_ptr->items, free); + table_ptr->n_items = 0; + table_ptr->n_items_allocated = 0; } -static gint -compare_by_src (gconstpointer a, - gconstpointer b) +static int +compare_by_src (const void *a, + const void *b) { const TranslateItem *itema = a; const TranslateItem *itemb = b; @@ -98,32 +112,41 @@ compare_by_src (gconstpointer a, } static void -translate_table_sort (GArray **tables, - guint table) +translate_table_sort (TranslateTable *tables, + unsigned int table) { - if (tables[table]) - g_array_sort (tables[table], compare_by_src); + TranslateTable *table_ptr = &tables[table]; + + if (table_ptr->items) + qsort (table_ptr->items, table_ptr->n_items, sizeof (*table_ptr->items), compare_by_src); } static void -translate_table_add (GArray **tables, - guint table, - guint64 src, - guint64 dst) +translate_table_add (TranslateTable *tables, + unsigned int table, + uint64_t src, + uint64_t dst) { + TranslateTable *table_ptr = &tables[table]; const TranslateItem item = { src, dst }; - if (tables[table] == NULL) - tables[table] = g_array_new (FALSE, FALSE, sizeof (TranslateItem)); + if (table_ptr->n_items == table_ptr->n_items_allocated) + { + table_ptr->n_items_allocated = (table_ptr->n_items_allocated > 0) ? table_ptr->n_items_allocated * 2 : 4; + table_ptr->items = reallocarray (table_ptr->items, table_ptr->n_items_allocated, sizeof (*table_ptr->items)); + assert (table_ptr->items != NULL); + } - g_array_append_val (tables[table], item); + table_ptr->items[table_ptr->n_items++] = item; + assert (table_ptr->n_items <= table_ptr->n_items_allocated); } -static guint64 -translate_table_translate (GArray **tables, - guint table, - guint64 src) +static uint64_t +translate_table_translate (TranslateTable *tables, + unsigned int table, + uint64_t src) { + TranslateTable *table_ptr = &tables[table]; const TranslateItem *item; TranslateItem key = { src, 0 }; @@ -133,31 +156,30 @@ translate_table_translate (GArray **tables, return src; } - if (tables[table] == NULL) + if (table_ptr->items == NULL) return src; item = bsearch (&key, - tables[table]->data, - tables[table]->len, - sizeof (TranslateItem), + table_ptr->items, + table_ptr->n_items, + sizeof (*table_ptr->items), compare_by_src); return item != NULL ? item->dst : src; } -gboolean -sysprof_capture_writer_cat (SysprofCaptureWriter *self, - SysprofCaptureReader *reader, - GError **error) +bool +sysprof_capture_writer_cat (SysprofCaptureWriter *self, + SysprofCaptureReader *reader) { - GArray *tables[N_TRANSLATE] = { NULL }; + TranslateTable tables[N_TRANSLATE] = { 0, }; SysprofCaptureFrameType type; - gint64 start_time; - gint64 first_start_time = G_MAXINT64; - gint64 end_time = -1; + int64_t start_time; + int64_t first_start_time = INT64_MAX; + int64_t end_time = -1; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (reader != NULL, FALSE); + assert (self != NULL); + assert (reader != NULL); sysprof_capture_reader_reset (reader); @@ -174,10 +196,10 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, */ while (sysprof_capture_reader_peek_type (reader, &type)) { - g_autoptr(GHashTable) jitmap = NULL; - GHashTableIter iter; - const gchar *name; - guint64 addr; + const SysprofCaptureJitmap *jitmap; + SysprofCaptureJitmapIter iter; + SysprofCaptureAddress addr; + const char *name; if (type != SYSPROF_CAPTURE_FRAME_JITMAP) { @@ -189,10 +211,10 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, if (!(jitmap = sysprof_capture_reader_read_jitmap (reader))) goto panic; - g_hash_table_iter_init (&iter, jitmap); - while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&name)) + sysprof_capture_jitmap_iter_init (&iter, jitmap); + while (sysprof_capture_jitmap_iter_next (&iter, &addr, &name)) { - guint64 replace = sysprof_capture_writer_add_jitmap (self, name); + uint64_t replace = sysprof_capture_writer_add_jitmap (self, name); /* We need to keep a table of replacement addresses so that * we can translate the samples into the destination address * space that we synthesized for the address identifier. @@ -364,7 +386,7 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, frame->frame.pid, frame->id, frame->metadata, - frame->frame.len - G_STRUCT_OFFSET (SysprofCaptureMetadata, metadata)); + frame->frame.len - offsetof (SysprofCaptureMetadata, metadata)); break; } @@ -378,7 +400,7 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, { SysprofCaptureAddress addrs[frame->n_addrs]; - for (guint z = 0; z < frame->n_addrs; z++) + for (unsigned int z = 0; z < frame->n_addrs; z++) addrs[z] = translate_table_translate (tables, TRANSLATE_ADDR, frame->addrs[z]); sysprof_capture_writer_add_sample (self, @@ -401,27 +423,30 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, goto panic; { - g_autoptr(GArray) counter = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounter)); + SysprofCaptureCounter *counters = calloc (frame->n_counters, sizeof (*counters)); + size_t n_counters = 0; + if (counters == NULL) + goto panic; - for (guint z = 0; z < frame->n_counters; z++) + for (unsigned int z = 0; z < frame->n_counters; z++) { SysprofCaptureCounter c = frame->counters[z]; - guint src = c.id; + unsigned int src = c.id; c.id = sysprof_capture_writer_request_counter (self, 1); if (c.id != src) translate_table_add (tables, TRANSLATE_CTR, src, c.id); - g_array_append_val (counter, c); + counters[n_counters++] = c; } sysprof_capture_writer_define_counters (self, frame->frame.time, frame->frame.cpu, frame->frame.pid, - (gpointer)counter->data, - counter->len); + counters, + n_counters); translate_table_sort (tables, TRANSLATE_CTR); } @@ -437,35 +462,46 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, goto panic; { - g_autoptr(GArray) ids = g_array_new (FALSE, FALSE, sizeof (guint)); - g_autoptr(GArray) values = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounterValue)); + unsigned int *ids = NULL; + SysprofCaptureCounterValue *values = NULL; + size_t n_elements = 0; + size_t n_elements_allocated = 0; - for (guint z = 0; z < frame->n_values; z++) + for (unsigned int z = 0; z < frame->n_values; z++) { const SysprofCaptureCounterValues *v = &frame->values[z]; - for (guint y = 0; y < G_N_ELEMENTS (v->ids); y++) + for (unsigned int y = 0; y < SYSPROF_N_ELEMENTS (v->ids); y++) { if (v->ids[y]) { - guint dst = translate_table_translate (tables, TRANSLATE_CTR, v->ids[y]); + unsigned int dst = translate_table_translate (tables, TRANSLATE_CTR, v->ids[y]); SysprofCaptureCounterValue value = v->values[y]; - g_array_append_val (ids, dst); - g_array_append_val (values, value); + if (n_elements == n_elements_allocated) + { + n_elements_allocated = (n_elements_allocated > 0) ? n_elements_allocated * 2 : 4; + ids = reallocarray (ids, n_elements_allocated, sizeof (*ids)); + values = reallocarray (values, n_elements_allocated, sizeof (*values)); + if (ids == NULL || values == NULL) + goto panic; + } + + ids[n_elements] = dst; + values[n_elements] = value; + n_elements++; + assert (n_elements <= n_elements_allocated); } } } - g_assert (ids->len == values->len); - sysprof_capture_writer_set_counters (self, frame->frame.time, frame->frame.cpu, frame->frame.pid, - (const guint *)(gpointer)ids->data, - (const SysprofCaptureCounterValue *)(gpointer)values->data, - ids->len); + ids, + values, + n_elements); } break; @@ -512,16 +548,12 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self, translate_table_clear (tables, TRANSLATE_ADDR); translate_table_clear (tables, TRANSLATE_CTR); - return TRUE; + return true; panic: - g_set_error (error, - G_FILE_ERROR, - G_FILE_ERROR_FAILED, - "Failed to write data"); - translate_table_clear (tables, TRANSLATE_ADDR); translate_table_clear (tables, TRANSLATE_CTR); - return FALSE; + errno = EIO; + return false; } diff --git a/src/libsysprof-capture/sysprof-capture-writer.c b/src/libsysprof-capture/sysprof-capture-writer.c index 8e4c5a61..f890da98 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.c +++ b/src/libsysprof-capture/sysprof-capture-writer.c @@ -54,17 +54,17 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-capture-writer" - #include "config.h" #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif +#include +#include #include #include -#include +#include #include #include #include @@ -74,19 +74,21 @@ #include "sysprof-capture-reader.h" #include "sysprof-capture-util-private.h" #include "sysprof-capture-writer.h" +#include "sysprof-macros-internal.h" +#include "sysprof-macros.h" #define DEFAULT_BUFFER_SIZE (_sysprof_getpagesize() * 64L) -#define INVALID_ADDRESS (G_GUINT64_CONSTANT(0)) +#define INVALID_ADDRESS (SYSPROF_UINT64_CONSTANT(0)) #define MAX_COUNTERS ((1 << 24) - 1) #define MAX_UNWIND_DEPTH 64 typedef struct { /* A pinter into the string buffer */ - const gchar *str; + const char *str; /* The unique address for the string */ - guint64 addr; + uint64_t addr; } SysprofCaptureJitmapBucket; struct _SysprofCaptureWriter @@ -98,7 +100,7 @@ struct _SysprofCaptureWriter * * This is paired with a closed hash table for deduplication. */ - gchar addr_buf[4096*4]; + char addr_buf[4096*4]; /* Our hashtable for deduplication. */ SysprofCaptureJitmapBucket addr_hash[512]; @@ -107,38 +109,35 @@ struct _SysprofCaptureWriter * alinged for the write buffer. This improves the performance of large * writes to the target file-descriptor. */ - volatile gint ref_count; + volatile int ref_count; /* * Our address sequence counter. The value that comes from * monotonically increasing this is OR'd with JITMAP_MARK to denote * the address name should come from the JIT map. */ - gsize addr_seq; + size_t addr_seq; /* Our position in addr_buf. */ - gsize addr_buf_pos; + size_t addr_buf_pos; /* * The number of hash table items in @addr_hash. This is an * optimization so that we can avoid calculating the number of strings * when flushing out the jitmap. */ - guint addr_hash_size; + unsigned int addr_hash_size; /* Capture file handle */ int fd; /* Our write buffer for fd */ - guint8 *buf; - gsize pos; - gsize len; - - /* GSource for periodic flush */ - GSource *periodic_flush; + uint8_t *buf; + size_t pos; + size_t len; /* counter id sequence */ - gint next_counter_id; + int next_counter_id; /* Statistics while recording */ SysprofCaptureStat stat; @@ -146,13 +145,13 @@ struct _SysprofCaptureWriter static inline void sysprof_capture_writer_frame_init (SysprofCaptureFrame *frame_, - gint len, - gint cpu, - gint32 pid, - gint64 time_, + int len, + int cpu, + int32_t pid, + int64_t time_, SysprofCaptureFrameType type) { - g_assert (frame_ != NULL); + assert (frame_ != NULL); frame_->len = len; frame_->cpu = cpu; @@ -168,8 +167,6 @@ sysprof_capture_writer_finalize (SysprofCaptureWriter *self) { if (self != NULL) { - g_clear_pointer (&self->periodic_flush, g_source_destroy); - sysprof_capture_writer_flush (self); if (self->fd != -1) @@ -178,18 +175,18 @@ sysprof_capture_writer_finalize (SysprofCaptureWriter *self) self->fd = -1; } - g_free (self->buf); - g_free (self); + free (self->buf); + free (self); } } SysprofCaptureWriter * sysprof_capture_writer_ref (SysprofCaptureWriter *self) { - g_assert (self != NULL); - g_assert (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - g_atomic_int_inc (&self->ref_count); + __atomic_fetch_add (&self->ref_count, 1, __ATOMIC_SEQ_CST); return self; } @@ -197,26 +194,26 @@ sysprof_capture_writer_ref (SysprofCaptureWriter *self) void sysprof_capture_writer_unref (SysprofCaptureWriter *self) { - g_assert (self != NULL); - g_assert (self->ref_count > 0); + assert (self != NULL); + assert (self->ref_count > 0); - if (g_atomic_int_dec_and_test (&self->ref_count)) + if (__atomic_fetch_sub (&self->ref_count, 1, __ATOMIC_SEQ_CST) == 1) sysprof_capture_writer_finalize (self); } -static gboolean +static bool sysprof_capture_writer_flush_data (SysprofCaptureWriter *self) { - const guint8 *buf; - gssize written; - gsize to_write; + const uint8_t *buf; + ssize_t written; + size_t to_write; - g_assert (self != NULL); - g_assert (self->pos <= self->len); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self != NULL); + assert (self->pos <= self->len); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); if (self->pos == 0) - return TRUE; + return true; buf = self->buf; to_write = self->pos; @@ -225,12 +222,12 @@ sysprof_capture_writer_flush_data (SysprofCaptureWriter *self) { written = _sysprof_write (self->fd, buf, to_write); if (written < 0) - return FALSE; + return false; if (written == 0 && errno != EAGAIN) - return FALSE; + return false; - g_assert (written <= (gssize)to_write); + assert (written <= (ssize_t)to_write); buf += written; to_write -= written; @@ -238,69 +235,69 @@ sysprof_capture_writer_flush_data (SysprofCaptureWriter *self) self->pos = 0; - return TRUE; + return true; } static inline void -sysprof_capture_writer_realign (gsize *pos) +sysprof_capture_writer_realign (size_t *pos) { *pos = (*pos + SYSPROF_CAPTURE_ALIGN - 1) & ~(SYSPROF_CAPTURE_ALIGN - 1); } -static inline gboolean +static inline bool sysprof_capture_writer_ensure_space_for (SysprofCaptureWriter *self, - gsize len) + size_t len) { /* Check for max frame size */ - if (len > G_MAXUSHORT) - return FALSE; + if (len > USHRT_MAX) + return false; if ((self->len - self->pos) < len) { if (!sysprof_capture_writer_flush_data (self)) - return FALSE; + return false; } - return TRUE; + return true; } -static inline gpointer +static inline void * sysprof_capture_writer_allocate (SysprofCaptureWriter *self, - gsize *len) + size_t *len) { - gpointer p; + void *p; - g_assert (self != NULL); - g_assert (len != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self != NULL); + assert (len != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); sysprof_capture_writer_realign (len); if (!sysprof_capture_writer_ensure_space_for (self, *len)) return NULL; - p = (gpointer)&self->buf[self->pos]; + p = (void *)&self->buf[self->pos]; self->pos += *len; - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); return p; } -static gboolean +static bool sysprof_capture_writer_flush_jitmap (SysprofCaptureWriter *self) { SysprofCaptureJitmap jitmap; - gssize r; - gsize len; + ssize_t r; + size_t len; - g_assert (self != NULL); + assert (self != NULL); if (self->addr_hash_size == 0) - return TRUE; + return true; - g_assert (self->addr_buf_pos > 0); + assert (self->addr_buf_pos > 0); len = sizeof jitmap + self->addr_buf_pos; @@ -315,11 +312,11 @@ sysprof_capture_writer_flush_jitmap (SysprofCaptureWriter *self) jitmap.n_jitmaps = self->addr_hash_size; if (sizeof jitmap != _sysprof_write (self->fd, &jitmap, sizeof jitmap)) - return FALSE; + return false; r = _sysprof_write (self->fd, self->addr_buf, len - sizeof jitmap); - if (r < 0 || (gsize)r != (len - sizeof jitmap)) - return FALSE; + if (r < 0 || (size_t)r != (len - sizeof jitmap)) + return false; self->addr_buf_pos = 0; self->addr_hash_size = 0; @@ -327,34 +324,47 @@ sysprof_capture_writer_flush_jitmap (SysprofCaptureWriter *self) self->stat.frame_count[SYSPROF_CAPTURE_FRAME_JITMAP]++; - return TRUE; + return true; } -static gboolean +/* djb hash */ +static unsigned int +str_hash (const char *str) +{ + const uint8_t *p; + uint32_t h = 5381; + + for (p = (const uint8_t *) str; *p != '\0'; p++) + h = (h << 5) + h + *p; + + return h; +} + +static bool sysprof_capture_writer_lookup_jitmap (SysprofCaptureWriter *self, - const gchar *name, + const char *name, SysprofCaptureAddress *addr) { - guint hash; - guint i; + unsigned int hash; + unsigned int i; - g_assert (self != NULL); - g_assert (name != NULL); - g_assert (addr != NULL); + assert (self != NULL); + assert (name != NULL); + assert (addr != NULL); - hash = g_str_hash (name) % G_N_ELEMENTS (self->addr_hash); + hash = str_hash (name) % SYSPROF_N_ELEMENTS (self->addr_hash); - for (i = hash; i < G_N_ELEMENTS (self->addr_hash); i++) + for (i = hash; i < SYSPROF_N_ELEMENTS (self->addr_hash); i++) { SysprofCaptureJitmapBucket *bucket = &self->addr_hash[i]; if (bucket->str == NULL) - return FALSE; + return false; if (strcmp (bucket->str, name) == 0) { *addr = bucket->addr; - return TRUE; + return true; } } @@ -363,52 +373,52 @@ sysprof_capture_writer_lookup_jitmap (SysprofCaptureWriter *self, SysprofCaptureJitmapBucket *bucket = &self->addr_hash[i]; if (bucket->str == NULL) - return FALSE; + return false; if (strcmp (bucket->str, name) == 0) { *addr = bucket->addr; - return TRUE; + return true; } } - return FALSE; + return false; } static SysprofCaptureAddress sysprof_capture_writer_insert_jitmap (SysprofCaptureWriter *self, - const gchar *str) + const char *str) { SysprofCaptureAddress addr; - gchar *dst; - gsize len; - guint hash; - guint i; + char *dst; + size_t len; + unsigned int hash; + unsigned int i; - g_assert (self != NULL); - g_assert (str != NULL); - g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + assert (self != NULL); + assert (str != NULL); + assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); len = sizeof addr + strlen (str) + 1; - if ((self->addr_hash_size == G_N_ELEMENTS (self->addr_hash)) || + if ((self->addr_hash_size == SYSPROF_N_ELEMENTS (self->addr_hash)) || ((sizeof self->addr_buf - self->addr_buf_pos) < len)) { if (!sysprof_capture_writer_flush_jitmap (self)) return INVALID_ADDRESS; - g_assert (self->addr_hash_size == 0); - g_assert (self->addr_buf_pos == 0); + assert (self->addr_hash_size == 0); + assert (self->addr_buf_pos == 0); } - g_assert (self->addr_hash_size < G_N_ELEMENTS (self->addr_hash)); - g_assert (len > sizeof addr); + assert (self->addr_hash_size < SYSPROF_N_ELEMENTS (self->addr_hash)); + assert (len > sizeof addr); /* Allocate the next unique address */ addr = SYSPROF_CAPTURE_JITMAP_MARK | ++self->addr_seq; /* Copy the address into the buffer */ - dst = (gchar *)&self->addr_buf[self->addr_buf_pos]; + dst = (char *)&self->addr_buf[self->addr_buf_pos]; memcpy (dst, &addr, sizeof addr); /* @@ -420,17 +430,17 @@ sysprof_capture_writer_insert_jitmap (SysprofCaptureWriter *self, /* Advance our string cache position */ self->addr_buf_pos += len; - g_assert (self->addr_buf_pos <= sizeof self->addr_buf); + assert (self->addr_buf_pos <= sizeof self->addr_buf); /* Now place the address into the hashtable */ - hash = g_str_hash (str) % G_N_ELEMENTS (self->addr_hash); + hash = str_hash (str) % SYSPROF_N_ELEMENTS (self->addr_hash); /* Start from the current hash bucket and go forward */ - for (i = hash; i < G_N_ELEMENTS (self->addr_hash); i++) + for (i = hash; i < SYSPROF_N_ELEMENTS (self->addr_hash); i++) { SysprofCaptureJitmapBucket *bucket = &self->addr_hash[i]; - if (G_LIKELY (bucket->str == NULL)) + if (SYSPROF_LIKELY (bucket->str == NULL)) { bucket->str = dst; bucket->addr = addr; @@ -444,7 +454,7 @@ sysprof_capture_writer_insert_jitmap (SysprofCaptureWriter *self, { SysprofCaptureJitmapBucket *bucket = &self->addr_hash[i]; - if (G_LIKELY (bucket->str == NULL)) + if (SYSPROF_LIKELY (bucket->str == NULL)) { bucket->str = dst; bucket->addr = addr; @@ -453,20 +463,20 @@ sysprof_capture_writer_insert_jitmap (SysprofCaptureWriter *self, } } - g_assert_not_reached (); + sysprof_assert_not_reached (); return INVALID_ADDRESS; } SysprofCaptureWriter * -sysprof_capture_writer_new_from_fd (int fd, - gsize buffer_size) +sysprof_capture_writer_new_from_fd (int fd, + size_t buffer_size) { - g_autofree gchar *nowstr = NULL; - g_autoptr(GDateTime) now = NULL; + time_t now; + char now_str[sizeof ("2020-06-30T14:34:00Z")]; SysprofCaptureWriter *self; SysprofCaptureFileHeader *header; - gsize header_len = sizeof(*header); + size_t header_len = sizeof(*header); if (fd < 0) return NULL; @@ -474,31 +484,35 @@ sysprof_capture_writer_new_from_fd (int fd, if (buffer_size == 0) buffer_size = DEFAULT_BUFFER_SIZE; - g_assert (fd != -1); - g_assert (buffer_size % _sysprof_getpagesize() == 0); + assert (fd != -1); + assert (buffer_size % _sysprof_getpagesize() == 0); /* This is only useful on files, memfd, etc */ if (ftruncate (fd, 0) != 0) { /* Do Nothing */ } - self = g_new0 (SysprofCaptureWriter, 1); + self = sysprof_malloc0 (sizeof (SysprofCaptureWriter)); + if (self == NULL) + return NULL; + self->ref_count = 1; self->fd = fd; - self->buf = (guint8 *)g_malloc0 (buffer_size); + self->buf = (uint8_t *) sysprof_malloc0 (buffer_size); + if (self->buf == NULL) + { + free (self); + return NULL; + } self->len = buffer_size; self->next_counter_id = 1; - now = g_date_time_new_now_local (); - -#if GLIB_CHECK_VERSION(2, 62, 0) - nowstr = g_date_time_format_iso8601 (now); -#else - { - GTimeVal tv; - - g_date_time_to_timeval (now, &tv); - nowstr = g_time_val_to_iso8601 (&tv); - } -#endif + /* Format the time as ISO 8601, in UTC */ + time (&now); + if (strftime (now_str, sizeof (now_str), "%FT%TZ", gmtime (&now)) == 0) + { + free (self->buf); + free (self); + return NULL; + } header = sysprof_capture_writer_allocate (self, &header_len); @@ -510,13 +524,13 @@ sysprof_capture_writer_new_from_fd (int fd, header->magic = SYSPROF_CAPTURE_MAGIC; header->version = 1; -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - header->little_endian = TRUE; +#if __BYTE_ORDER == __LITTLE_ENDIAN + header->little_endian = true; #else - header->little_endian = FALSE; + header->little_endian = false; #endif header->padding = 0; - g_strlcpy (header->capture_time, nowstr, sizeof header->capture_time); + _sysprof_strlcpy (header->capture_time, now_str, sizeof header->capture_time); header->time = SYSPROF_CAPTURE_CURRENT_TIME; header->end_time = 0; memset (header->suffix, 0, sizeof header->suffix); @@ -527,25 +541,25 @@ sysprof_capture_writer_new_from_fd (int fd, return NULL; } - g_assert (self->pos == 0); - g_assert (self->len > 0); - g_assert (self->len % _sysprof_getpagesize() == 0); - g_assert (self->buf != NULL); - g_assert (self->addr_hash_size == 0); - g_assert (self->fd != -1); + assert (self->pos == 0); + assert (self->len > 0); + assert (self->len % _sysprof_getpagesize() == 0); + assert (self->buf != NULL); + assert (self->addr_hash_size == 0); + assert (self->fd != -1); return self; } SysprofCaptureWriter * -sysprof_capture_writer_new (const gchar *filename, - gsize buffer_size) +sysprof_capture_writer_new (const char *filename, + size_t buffer_size) { SysprofCaptureWriter *self; int fd; - g_assert (filename != NULL); - g_assert (buffer_size % _sysprof_getpagesize() == 0); + assert (filename != NULL); + assert (buffer_size % _sysprof_getpagesize() == 0); if ((-1 == (fd = open (filename, O_CREAT | O_RDWR, 0640))) || (-1 == ftruncate (fd, 0L))) @@ -559,31 +573,31 @@ sysprof_capture_writer_new (const gchar *filename, return self; } -gboolean +bool sysprof_capture_writer_add_map (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - guint64 start, - guint64 end, - guint64 offset, - guint64 inode, - const gchar *filename) + int64_t time, + int cpu, + int32_t pid, + uint64_t start, + uint64_t end, + uint64_t offset, + uint64_t inode, + const char *filename) { SysprofCaptureMap *ev; - gsize len; + size_t len; if (filename == NULL) filename = ""; - g_assert (self != NULL); - g_assert (filename != NULL); + assert (self != NULL); + assert (filename != NULL); len = sizeof *ev + strlen (filename) + 1; ev = (SysprofCaptureMap *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -596,31 +610,31 @@ sysprof_capture_writer_add_map (SysprofCaptureWriter *self, ev->offset = offset; ev->inode = inode; - g_strlcpy (ev->filename, filename, len - sizeof *ev); + _sysprof_strlcpy (ev->filename, filename, len - sizeof *ev); ev->filename[len - sizeof *ev - 1] = '\0'; self->stat.frame_count[SYSPROF_CAPTURE_FRAME_MAP]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - guint64 duration, - const gchar *group, - const gchar *name, - const gchar *message) + int64_t time, + int cpu, + int32_t pid, + uint64_t duration, + const char *group, + const char *name, + const char *message) { SysprofCaptureMark *ev; - gsize message_len; - gsize len; + size_t message_len; + size_t len; - g_assert (self != NULL); - g_assert (name != NULL); - g_assert (group != NULL); + assert (self != NULL); + assert (name != NULL); + assert (group != NULL); if (message == NULL) message = ""; @@ -629,7 +643,7 @@ sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, len = sizeof *ev + message_len; ev = (SysprofCaptureMark *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -639,29 +653,29 @@ sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, SYSPROF_CAPTURE_FRAME_MARK); ev->duration = duration; - g_strlcpy (ev->group, group, sizeof ev->group); - g_strlcpy (ev->name, name, sizeof ev->name); + _sysprof_strlcpy (ev->group, group, sizeof ev->group); + _sysprof_strlcpy (ev->name, name, sizeof ev->name); memcpy (ev->message, message, message_len); self->stat.frame_count[SYSPROF_CAPTURE_FRAME_MARK]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *id, - const gchar *metadata, - gssize metadata_len) + int64_t time, + int cpu, + int32_t pid, + const char *id, + const char *metadata, + ssize_t metadata_len) { SysprofCaptureMetadata *ev; - gsize len; + size_t len; - g_assert (self != NULL); - g_assert (id != NULL); + assert (self != NULL); + assert (id != NULL); if (metadata == NULL) { @@ -675,7 +689,7 @@ sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, len = sizeof *ev + metadata_len + 1; ev = (SysprofCaptureMetadata *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -684,26 +698,26 @@ sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, time, SYSPROF_CAPTURE_FRAME_METADATA); - g_strlcpy (ev->id, id, sizeof ev->id); + _sysprof_strlcpy (ev->id, id, sizeof ev->id); memcpy (ev->metadata, metadata, metadata_len); ev->metadata[metadata_len] = 0; self->stat.frame_count[SYSPROF_CAPTURE_FRAME_METADATA]++; - return TRUE; + return true; } SysprofCaptureAddress sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, - const gchar *name) + const char *name) { SysprofCaptureAddress addr = INVALID_ADDRESS; if (name == NULL) name = ""; - g_assert (self != NULL); - g_assert (name != NULL); + assert (self != NULL); + assert (name != NULL); if (!sysprof_capture_writer_lookup_jitmap (self, name, &addr)) addr = sysprof_capture_writer_insert_jitmap (self, name); @@ -711,27 +725,27 @@ sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, return addr; } -gboolean +bool sysprof_capture_writer_add_process (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *cmdline) + int64_t time, + int cpu, + int32_t pid, + const char *cmdline) { SysprofCaptureProcess *ev; - gsize len; + size_t len; if (cmdline == NULL) cmdline = ""; - g_assert (self != NULL); - g_assert (cmdline != NULL); + assert (self != NULL); + assert (cmdline != NULL); len = sizeof *ev + strlen (cmdline) + 1; ev = (SysprofCaptureProcess *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -740,33 +754,33 @@ sysprof_capture_writer_add_process (SysprofCaptureWriter *self, time, SYSPROF_CAPTURE_FRAME_PROCESS); - g_strlcpy (ev->cmdline, cmdline, len - sizeof *ev); + _sysprof_strlcpy (ev->cmdline, cmdline, len - sizeof *ev); ev->cmdline[len - sizeof *ev - 1] = '\0'; self->stat.frame_count[SYSPROF_CAPTURE_FRAME_PROCESS]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_sample (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 tid, + int64_t time, + int cpu, + int32_t pid, + int32_t tid, const SysprofCaptureAddress *addrs, - guint n_addrs) + unsigned int n_addrs) { SysprofCaptureSample *ev; - gsize len; + size_t len; - g_assert (self != NULL); + assert (self != NULL); len = sizeof *ev + (n_addrs * sizeof (SysprofCaptureAddress)); ev = (SysprofCaptureSample *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -781,24 +795,24 @@ sysprof_capture_writer_add_sample (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_SAMPLE]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_fork (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 child_pid) + int64_t time, + int cpu, + int32_t pid, + int32_t child_pid) { SysprofCaptureFork *ev; - gsize len = sizeof *ev; + size_t len = sizeof *ev; - g_assert (self != NULL); + assert (self != NULL); ev = (SysprofCaptureFork *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -810,23 +824,23 @@ sysprof_capture_writer_add_fork (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_FORK]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_exit (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid) + int64_t time, + int cpu, + int32_t pid) { SysprofCaptureExit *ev; - gsize len = sizeof *ev; + size_t len = sizeof *ev; - g_assert (self != NULL); + assert (self != NULL); ev = (SysprofCaptureExit *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -837,23 +851,23 @@ sysprof_capture_writer_add_exit (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_EXIT]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_timestamp (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid) + int64_t time, + int cpu, + int32_t pid) { SysprofCaptureTimestamp *ev; - gsize len = sizeof *ev; + size_t len = sizeof *ev; - g_assert (self != NULL); + assert (self != NULL); ev = (SysprofCaptureTimestamp *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -864,16 +878,16 @@ sysprof_capture_writer_add_timestamp (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_TIMESTAMP]++; - return TRUE; + return true; } -static gboolean +static bool sysprof_capture_writer_flush_end_time (SysprofCaptureWriter *self) { - gint64 end_time = SYSPROF_CAPTURE_CURRENT_TIME; + int64_t end_time = SYSPROF_CAPTURE_CURRENT_TIME; ssize_t ret; - g_assert (self != NULL); + assert (self != NULL); /* This field is opportunistic, so a failure is okay. */ @@ -881,18 +895,18 @@ again: ret = _sysprof_pwrite (self->fd, &end_time, sizeof (end_time), - G_STRUCT_OFFSET (SysprofCaptureFileHeader, end_time)); + offsetof (SysprofCaptureFileHeader, end_time)); if (ret < 0 && errno == EAGAIN) goto again; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_flush (SysprofCaptureWriter *self) { - g_assert (self != NULL); + assert (self != NULL); return sysprof_capture_writer_flush_jitmap (self) && sysprof_capture_writer_flush_data (self) && @@ -903,28 +917,30 @@ sysprof_capture_writer_flush (SysprofCaptureWriter *self) * sysprof_capture_writer_save_as: * @self: A #SysprofCaptureWriter * @filename: the file to save the capture as - * @error: a location for a #GError or %NULL. * * Saves the captured data as the file @filename. * * This is primarily useful if the writer was created with a memory-backed * file-descriptor such as a memfd or tmpfs file on Linux. * - * Returns: %TRUE if successful, otherwise %FALSE and @error is set. + * `errno` is set on error, to any of the errors returned by `open()`, + * sysprof_capture_writer_flush(), `lseek()` or `sendfile()`. + * + * Returns: %TRUE if successful, otherwise %FALSE and `errno` is set. */ -gboolean -sysprof_capture_writer_save_as (SysprofCaptureWriter *self, - const gchar *filename, - GError **error) +bool +sysprof_capture_writer_save_as (SysprofCaptureWriter *self, + const char *filename) { - gsize to_write; + size_t to_write; off_t in_off; off_t pos; int fd = -1; + int errsv; - g_assert (self != NULL); - g_assert (self->fd != -1); - g_assert (filename != NULL); + assert (self != NULL); + assert (self->fd != -1); + assert (filename != NULL); if (-1 == (fd = open (filename, O_CREAT | O_RDWR, 0640))) goto handle_errno; @@ -940,7 +956,7 @@ sysprof_capture_writer_save_as (SysprofCaptureWriter *self, while (to_write > 0) { - gssize written; + ssize_t written; written = _sysprof_sendfile (fd, self->fd, &in_off, pos); @@ -950,35 +966,33 @@ sysprof_capture_writer_save_as (SysprofCaptureWriter *self, if (written == 0 && errno != EAGAIN) goto handle_errno; - g_assert (written <= (gssize)to_write); + assert (written <= (ssize_t)to_write); to_write -= written; } close (fd); - return TRUE; + return true; handle_errno: - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); + errsv = errno; if (fd != -1) { close (fd); - g_unlink (filename); + unlink (filename); } - return FALSE; + errno = errsv; + + return false; } /** * _sysprof_capture_writer_splice_from_fd: * @self: An #SysprofCaptureWriter * @fd: the fd to read from. - * @error: A location for a #GError, or %NULL. * * This is internal API for SysprofCaptureWriter and SysprofCaptureReader to * communicate when splicing a reader into a writer. @@ -988,30 +1002,29 @@ handle_errno: * * This will not advance the position of @fd. * - * Returns: %TRUE if successful; otherwise %FALSE and @error is set. + * `errno` is set on error, to any of the errors returned by `fstat()` or + * `sendfile()`, or `EBADMSG` if the file is corrupt. + * + * Returns: %TRUE if successful; otherwise %FALSE and `errno` is set. */ -gboolean -_sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, - int fd, - GError **error) +bool +_sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, + int fd) { struct stat stbuf; off_t in_off; - gsize to_write; + size_t to_write; - g_assert (self != NULL); - g_assert (self->fd != -1); + assert (self != NULL); + assert (self->fd != -1); if (-1 == fstat (fd, &stbuf)) goto handle_errno; if (stbuf.st_size < 256) { - g_set_error (error, - G_FILE_ERROR, - G_FILE_ERROR_INVAL, - "Cannot splice, possibly corrupt file."); - return FALSE; + errno = EBADMSG; + return false; } in_off = 256; @@ -1019,7 +1032,7 @@ _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, while (to_write > 0) { - gssize written; + ssize_t written; written = _sysprof_sendfile (self->fd, fd, &in_off, to_write); @@ -1029,47 +1042,46 @@ _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, if (written == 0 && errno != EAGAIN) goto handle_errno; - g_assert (written <= (gssize)to_write); + assert (written <= (ssize_t)to_write); to_write -= written; } - return TRUE; + return true; handle_errno: - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - - return FALSE; + /* errno is propagated */ + return false; } /** * sysprof_capture_writer_splice: * @self: An #SysprofCaptureWriter * @dest: An #SysprofCaptureWriter - * @error: A location for a #GError, or %NULL. * * This function will copy the capture @self into the capture @dest. This * tries to be semi-efficient by using sendfile() to copy the contents between * the captures. @self and @dest will be flushed before the contents are copied * into the @dest file-descriptor. * - * Returns: %TRUE if successful, otherwise %FALSE and and @error is set. + * `errno` is set on error, to any of the errors returned by + * sysprof_capture_writer_flush(), `lseek()` or + * _sysprof_capture_writer_splice_from_fd(). + * + * Returns: %TRUE if successful, otherwise %FALSE and and `errno` is set. */ -gboolean -sysprof_capture_writer_splice (SysprofCaptureWriter *self, - SysprofCaptureWriter *dest, - GError **error) +bool +sysprof_capture_writer_splice (SysprofCaptureWriter *self, + SysprofCaptureWriter *dest) { - gboolean ret; + bool ret; off_t pos; + int errsv; - g_assert (self != NULL); - g_assert (self->fd != -1); - g_assert (dest != NULL); - g_assert (dest->fd != -1); + assert (self != NULL); + assert (self->fd != -1); + assert (dest != NULL); + assert (dest->fd != -1); /* Flush before writing anything to ensure consistency */ if (!sysprof_capture_writer_flush (self) || !sysprof_capture_writer_flush (dest)) @@ -1080,30 +1092,25 @@ sysprof_capture_writer_splice (SysprofCaptureWriter *self, goto handle_errno; /* Perform the splice */ - ret = _sysprof_capture_writer_splice_from_fd (dest, self->fd, error); + ret = _sysprof_capture_writer_splice_from_fd (dest, self->fd); + errsv = errno; /* Now reset or file-descriptor position (it should be the same */ if (pos != lseek (self->fd, pos, SEEK_SET)) - { - ret = FALSE; - goto handle_errno; - } + goto handle_errno; + if (!ret) + errno = errsv; return ret; handle_errno: - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - - return FALSE; + /* errno is propagated */ + return false; } /** * sysprof_capture_writer_create_reader: * @self: A #SysprofCaptureWriter - * @error: a location for a #GError, or %NULL * * Creates a new reader for the writer. * @@ -1112,24 +1119,24 @@ handle_errno: * also consuming from the reader, you could get transient failures unless you * synchronize the operations. * + * `errno` is set on error, to any of the errors returned by + * sysprof_capture_writer_flush(), `dup()` or + * sysprof_capture_reader_new_from_fd(). + * * Returns: (transfer full): A #SysprofCaptureReader. */ SysprofCaptureReader * -sysprof_capture_writer_create_reader (SysprofCaptureWriter *self, - GError **error) +sysprof_capture_writer_create_reader (SysprofCaptureWriter *self) { SysprofCaptureReader *ret; int copy; - g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (self->fd != -1, NULL); + assert (self != NULL); + assert (self->fd != -1); if (!sysprof_capture_writer_flush (self)) { - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); + /* errno is propagated */ return NULL; } @@ -1138,12 +1145,20 @@ sysprof_capture_writer_create_reader (SysprofCaptureWriter *self, * uses positioned reads. */ if (-1 == (copy = dup (self->fd))) - return NULL; + { + /* errno is propagated */ + return NULL; + } - if ((ret = sysprof_capture_reader_new_from_fd (copy, error))) - sysprof_capture_reader_set_stat (ret, &self->stat); + if (!(ret = sysprof_capture_reader_new_from_fd (copy))) + { + /* errno is propagated */ + return NULL; + } - return g_steal_pointer (&ret); + sysprof_capture_reader_set_stat (ret, &self->stat); + + return sysprof_steal_pointer (&ret); } /** @@ -1158,35 +1173,35 @@ void sysprof_capture_writer_stat (SysprofCaptureWriter *self, SysprofCaptureStat *stat) { - g_return_if_fail (self != NULL); - g_return_if_fail (stat != NULL); + assert (self != NULL); + assert (stat != NULL); *stat = self->stat; } -gboolean +bool sysprof_capture_writer_define_counters (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, + int64_t time, + int cpu, + int32_t pid, const SysprofCaptureCounter *counters, - guint n_counters) + unsigned int n_counters) { SysprofCaptureCounterDefine *def; - gsize len; - guint i; + size_t len; + unsigned int i; - g_assert (self != NULL); - g_assert (counters != NULL); + assert (self != NULL); + assert (counters != NULL); if (n_counters == 0) - return TRUE; + return true; len = sizeof *def + (sizeof *counters * n_counters); def = (SysprofCaptureCounterDefine *)sysprof_capture_writer_allocate (self, &len); if (!def) - return FALSE; + return false; sysprof_capture_writer_frame_init (&def->frame, len, @@ -1200,53 +1215,49 @@ sysprof_capture_writer_define_counters (SysprofCaptureWriter *self, for (i = 0; i < n_counters; i++) { - if (counters[i].id >= self->next_counter_id) - { - g_warning ("Counter %u has not been registered.", counters[i].id); - continue; - } - + /* Has the counter been registered? */ + assert (counters[i].id < self->next_counter_id); def->counters[i] = counters[i]; } self->stat.frame_count[SYSPROF_CAPTURE_FRAME_CTRDEF]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const guint *counters_ids, + int64_t time, + int cpu, + int32_t pid, + const unsigned int *counters_ids, const SysprofCaptureCounterValue *values, - guint n_counters) + unsigned int n_counters) { SysprofCaptureCounterSet *set; - gsize len; - guint n_groups; - guint group; - guint field; - guint i; + size_t len; + unsigned int n_groups; + unsigned int group; + unsigned int field; + unsigned int i; - g_assert (self != NULL); - g_assert (counters_ids != NULL || n_counters == 0); - g_assert (values != NULL || !n_counters); + assert (self != NULL); + assert (counters_ids != NULL || n_counters == 0); + assert (values != NULL || !n_counters); if (n_counters == 0) - return TRUE; + return true; /* Determine how many value groups we need */ - n_groups = n_counters / G_N_ELEMENTS (set->values[0].values); - if ((n_groups * G_N_ELEMENTS (set->values[0].values)) != n_counters) + n_groups = n_counters / SYSPROF_N_ELEMENTS (set->values[0].values); + if ((n_groups * SYSPROF_N_ELEMENTS (set->values[0].values)) != n_counters) n_groups++; len = sizeof *set + (n_groups * sizeof (SysprofCaptureCounterValues)); set = (SysprofCaptureCounterSet *)sysprof_capture_writer_allocate (self, &len); if (!set) - return FALSE; + return false; memset (set, 0, len); @@ -1267,7 +1278,7 @@ sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, field++; - if (field == G_N_ELEMENTS (set->values[0].values)) + if (field == SYSPROF_N_ELEMENTS (set->values[0].values)) { field = 0; group++; @@ -1276,7 +1287,7 @@ sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_CTRSET]++; - return TRUE; + return true; } /** @@ -1292,13 +1303,13 @@ sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, * * Returns: The next series of counter values or zero on failure. */ -guint +unsigned int sysprof_capture_writer_request_counter (SysprofCaptureWriter *self, - guint n_counters) + unsigned int n_counters) { - gint ret; + int ret; - g_assert (self != NULL); + assert (self != NULL); if (MAX_COUNTERS - n_counters < self->next_counter_id) return 0; @@ -1309,20 +1320,20 @@ sysprof_capture_writer_request_counter (SysprofCaptureWriter *self, return ret; } -gboolean +bool _sysprof_capture_writer_set_time_range (SysprofCaptureWriter *self, - gint64 start_time, - gint64 end_time) + int64_t start_time, + int64_t end_time) { ssize_t ret; - g_assert (self != NULL); + assert (self != NULL); do_start: ret = _sysprof_pwrite (self->fd, &start_time, sizeof (start_time), - G_STRUCT_OFFSET (SysprofCaptureFileHeader, time)); + offsetof (SysprofCaptureFileHeader, time)); if (ret < 0 && errno == EAGAIN) goto do_start; @@ -1331,21 +1342,21 @@ do_end: ret = _sysprof_pwrite (self->fd, &end_time, sizeof (end_time), - G_STRUCT_OFFSET (SysprofCaptureFileHeader, end_time)); + offsetof (SysprofCaptureFileHeader, end_time)); if (ret < 0 && errno == EAGAIN) goto do_end; - return TRUE; + return true; } SysprofCaptureWriter * -sysprof_capture_writer_new_from_env (gsize buffer_size) +sysprof_capture_writer_new_from_env (size_t buffer_size) { - const gchar *fdstr; + const char *fdstr; int fd; - if (!(fdstr = g_getenv ("SYSPROF_TRACE_FD"))) + if (!(fdstr = getenv ("SYSPROF_TRACE_FD"))) return NULL; /* Make sure the clock is initialized */ @@ -1361,28 +1372,28 @@ sysprof_capture_writer_new_from_env (gsize buffer_size) return sysprof_capture_writer_new_from_fd (dup (fd), buffer_size); } -gsize +size_t sysprof_capture_writer_get_buffer_size (SysprofCaptureWriter *self) { - g_return_val_if_fail (self != NULL, 0); + assert (self != NULL); return self->len; } -gboolean +bool sysprof_capture_writer_add_log (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - GLogLevelFlags severity, - const gchar *domain, - const gchar *message) + int64_t time, + int cpu, + int32_t pid, + int severity, + const char *domain, + const char *message) { SysprofCaptureLog *ev; - gsize message_len; - gsize len; + size_t message_len; + size_t len; - g_assert (self != NULL); + assert (self != NULL); if (domain == NULL) domain = ""; @@ -1394,7 +1405,7 @@ sysprof_capture_writer_add_log (SysprofCaptureWriter *self, len = sizeof *ev + message_len; ev = (SysprofCaptureLog *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -1406,33 +1417,33 @@ sysprof_capture_writer_add_log (SysprofCaptureWriter *self, ev->severity = severity & 0xFFFF; ev->padding1 = 0; ev->padding2 = 0; - g_strlcpy (ev->domain, domain, sizeof ev->domain); + _sysprof_strlcpy (ev->domain, domain, sizeof ev->domain); memcpy (ev->message, message, message_len); self->stat.frame_count[SYSPROF_CAPTURE_FRAME_LOG]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_file (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *path, - gboolean is_last, - const guint8 *data, - gsize data_len) + int64_t time, + int cpu, + int32_t pid, + const char *path, + bool is_last, + const uint8_t *data, + size_t data_len) { SysprofCaptureFileChunk *ev; - gsize len; + size_t len; - g_assert (self != NULL); + assert (self != NULL); len = sizeof *ev + data_len; ev = (SysprofCaptureFileChunk *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -1444,30 +1455,30 @@ sysprof_capture_writer_add_file (SysprofCaptureWriter *self, ev->padding1 = 0; ev->is_last = !!is_last; ev->len = data_len; - g_strlcpy (ev->path, path, sizeof ev->path); + _sysprof_strlcpy (ev->path, path, sizeof ev->path); memcpy (ev->data, data, data_len); self->stat.frame_count[SYSPROF_CAPTURE_FRAME_FILE_CHUNK]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *path, - gint fd) + int64_t time, + int cpu, + int32_t pid, + const char *path, + int fd) { - guint8 data[(4096*4L) - sizeof(SysprofCaptureFileChunk)]; + uint8_t data[(4096*4L) - sizeof(SysprofCaptureFileChunk)]; - g_assert (self != NULL); + assert (self != NULL); for (;;) { - gboolean is_last; - gssize n_read; + bool is_last; + ssize_t n_read; again: n_read = read (fd, data, sizeof data); @@ -1477,73 +1488,37 @@ sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self, is_last = n_read == 0; if (!sysprof_capture_writer_add_file (self, time, cpu, pid, path, is_last, data, n_read)) - return FALSE; + return false; if (is_last) break; } - return TRUE; + return true; } -static gboolean -sysprof_capture_writer_auto_flush_cb (SysprofCaptureWriter *self) -{ - g_assert (self != NULL); - - sysprof_capture_writer_flush (self); - - return G_SOURCE_CONTINUE; -} - -void -sysprof_capture_writer_set_flush_delay (SysprofCaptureWriter *self, - GMainContext *main_context, - guint timeout_seconds) -{ - GSource *source; - - g_return_if_fail (self != NULL); - - g_clear_pointer (&self->periodic_flush, g_source_destroy); - - if (timeout_seconds == 0) - return; - - source = g_timeout_source_new_seconds (timeout_seconds); - g_source_set_name (source, "[sysprof-capture-writer-flush]"); - g_source_set_priority (source, G_PRIORITY_LOW + 100); - g_source_set_callback (source, - (GSourceFunc) sysprof_capture_writer_auto_flush_cb, - self, NULL); - - self->periodic_flush = g_steal_pointer (&source); - - g_source_attach (self->periodic_flush, main_context); -} - -gboolean +bool sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 tid, + int64_t time, + int cpu, + int32_t pid, + int32_t tid, SysprofCaptureAddress alloc_addr, - gint64 alloc_size, + int64_t alloc_size, SysprofBacktraceFunc backtrace_func, - gpointer backtrace_data) + void *backtrace_data) { SysprofCaptureAllocation *ev; - gsize len; - guint n_addrs; + size_t len; + unsigned int n_addrs; - g_assert (self != NULL); - g_assert (backtrace_func != NULL); + assert (self != NULL); + assert (backtrace_func != NULL); len = sizeof *ev + (MAX_UNWIND_DEPTH * sizeof (SysprofCaptureAddress)); ev = (SysprofCaptureAllocation *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -1565,7 +1540,7 @@ sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self, if (ev->n_addrs < MAX_UNWIND_DEPTH) { - gsize diff = (sizeof (SysprofCaptureAddress) * (MAX_UNWIND_DEPTH - ev->n_addrs)); + size_t diff = (sizeof (SysprofCaptureAddress) * (MAX_UNWIND_DEPTH - ev->n_addrs)); ev->frame.len -= diff; self->pos -= diff; @@ -1573,24 +1548,24 @@ sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_ALLOCATION]++; - return TRUE; + return true; } -gboolean +bool sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 tid, + int64_t time, + int cpu, + int32_t pid, + int32_t tid, SysprofCaptureAddress alloc_addr, - gint64 alloc_size, + int64_t alloc_size, const SysprofCaptureAddress *addrs, - guint n_addrs) + unsigned int n_addrs) { SysprofCaptureAllocation *ev; - gsize len; + size_t len; - g_assert (self != NULL); + assert (self != NULL); if (n_addrs > 0xFFF) n_addrs = 0xFFF; @@ -1598,7 +1573,7 @@ sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self, len = sizeof *ev + (n_addrs * sizeof (SysprofCaptureAddress)); ev = (SysprofCaptureAllocation *)sysprof_capture_writer_allocate (self, &len); if (!ev) - return FALSE; + return false; sysprof_capture_writer_frame_init (&ev->frame, len, @@ -1617,32 +1592,32 @@ sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self, self->stat.frame_count[SYSPROF_CAPTURE_FRAME_ALLOCATION]++; - return TRUE; + return true; } -gboolean +bool _sysprof_capture_writer_add_raw (SysprofCaptureWriter *self, const SysprofCaptureFrame *fr) { - gpointer begin; - gsize len; + void *begin; + size_t len; - g_assert (self != NULL); - g_assert ((fr->len & 0x7) == 0); - g_assert (fr->type < SYSPROF_CAPTURE_FRAME_LAST); + assert (self != NULL); + assert ((fr->len & 0x7) == 0); + assert (fr->type < SYSPROF_CAPTURE_FRAME_LAST); len = fr->len; if (!(begin = sysprof_capture_writer_allocate (self, &len))) - return FALSE; + return false; - g_assert (fr->len == len); - g_assert (fr->type < 16); + assert (fr->len == len); + assert (fr->type < 16); memcpy (begin, fr, fr->len); - if (fr->type < G_N_ELEMENTS (self->stat.frame_count)) + if (fr->type < SYSPROF_N_ELEMENTS (self->stat.frame_count)) self->stat.frame_count[fr->type]++; - return TRUE; + return true; } diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h index 6e490253..e92007df 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.h +++ b/src/libsysprof-capture/sysprof-capture-writer.h @@ -56,36 +56,27 @@ #pragma once +#include +#include +#include + #include "sysprof-capture-types.h" #include "sysprof-version-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS typedef struct _SysprofCaptureWriter SysprofCaptureWriter; -/** - * SysprofBacktraceFunc: - * @addrs: (inout) (array length=n_addrs): an array to place addresses - * into the capture frame - * @n_addrs: the length of @addrs - * @user_data: (scope call): closure data for the callback - * - * Returns: the number of addresses filled in @addrs - */ -typedef gint (*SysprofBacktraceFunc) (SysprofCaptureAddress *addrs, - guint n_addrs, - gpointer user_data); - SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureWriter *sysprof_capture_writer_new_from_env (gsize buffer_size); +SysprofCaptureWriter *sysprof_capture_writer_new_from_env (size_t buffer_size); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureWriter *sysprof_capture_writer_new (const gchar *filename, - gsize buffer_size); +SysprofCaptureWriter *sysprof_capture_writer_new (const char *filename, + size_t buffer_size); SYSPROF_AVAILABLE_IN_ALL SysprofCaptureWriter *sysprof_capture_writer_new_from_fd (int fd, - gsize buffer_size); + size_t buffer_size); SYSPROF_AVAILABLE_IN_ALL -gsize sysprof_capture_writer_get_buffer_size (SysprofCaptureWriter *self); +size_t sysprof_capture_writer_get_buffer_size (SysprofCaptureWriter *self); SYSPROF_AVAILABLE_IN_ALL SysprofCaptureWriter *sysprof_capture_writer_ref (SysprofCaptureWriter *self); SYSPROF_AVAILABLE_IN_ALL @@ -94,161 +85,149 @@ SYSPROF_AVAILABLE_IN_ALL void sysprof_capture_writer_stat (SysprofCaptureWriter *self, SysprofCaptureStat *stat); SYSPROF_AVAILABLE_IN_ALL -void sysprof_capture_writer_set_flush_delay (SysprofCaptureWriter *self, - GMainContext *main_context, - guint timeout_seconds); +bool sysprof_capture_writer_add_file (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const char *path, + bool is_last, + const uint8_t *data, + size_t data_len); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_file (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *path, - gboolean is_last, - const guint8 *data, - gsize data_len); +bool sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const char *path, + int fd); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *path, - gint fd); +bool sysprof_capture_writer_add_map (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + uint64_t start, + uint64_t end, + uint64_t offset, + uint64_t inode, + const char *filename); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_map (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - guint64 start, - guint64 end, - guint64 offset, - guint64 inode, - const gchar *filename); +bool sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + uint64_t duration, + const char *group, + const char *name, + const char *message); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - guint64 duration, - const gchar *group, - const gchar *name, - const gchar *message); +bool sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const char *id, + const char *metadata, + ssize_t metadata_len); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *id, - const gchar *metadata, - gssize metadata_len); +uint64_t sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, + const char *name); SYSPROF_AVAILABLE_IN_ALL -guint64 sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, - const gchar *name); +bool sysprof_capture_writer_add_process (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const char *cmdline); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_process (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const gchar *cmdline); -SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_sample (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 tid, +bool sysprof_capture_writer_add_sample (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + int32_t tid, const SysprofCaptureAddress *addrs, - guint n_addrs); + unsigned int n_addrs); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_fork (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 child_pid); +bool sysprof_capture_writer_add_fork (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + int32_t child_pid); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_exit (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid); +bool sysprof_capture_writer_add_exit (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_timestamp (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid); +bool sysprof_capture_writer_add_timestamp (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_define_counters (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, +bool sysprof_capture_writer_define_counters (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, const SysprofCaptureCounter *counters, - guint n_counters); + unsigned int n_counters); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - const guint *counters_ids, +bool sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + const unsigned int *counters_ids, const SysprofCaptureCounterValue *values, - guint n_counters); + unsigned int n_counters); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_add_log (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - GLogLevelFlags severity, - const gchar *domain, - const gchar *message); +bool sysprof_capture_writer_add_log (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + int severity, + const char *domain, + const char *message); SYSPROF_AVAILABLE_IN_3_36 -gboolean sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 tid, +bool sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + int32_t tid, SysprofCaptureAddress alloc_addr, - gint64 alloc_size, + int64_t alloc_size, SysprofBacktraceFunc backtrace_func, - gpointer backtrace_data); + void *backtrace_data); SYSPROF_AVAILABLE_IN_3_36 -gboolean sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self, - gint64 time, - gint cpu, - gint32 pid, - gint32 tid, +bool sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self, + int64_t time, + int cpu, + int32_t pid, + int32_t tid, SysprofCaptureAddress alloc_addr, - gint64 alloc_size, + int64_t alloc_size, const SysprofCaptureAddress *addrs, - guint n_addrs); + unsigned int n_addrs); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_flush (SysprofCaptureWriter *self); +bool sysprof_capture_writer_flush (SysprofCaptureWriter *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_save_as (SysprofCaptureWriter *self, - const gchar *filename, - GError **error); +bool sysprof_capture_writer_save_as (SysprofCaptureWriter *self, + const char *filename); SYSPROF_AVAILABLE_IN_ALL -guint sysprof_capture_writer_request_counter (SysprofCaptureWriter *self, - guint n_counters); +unsigned int sysprof_capture_writer_request_counter (SysprofCaptureWriter *self, + unsigned int n_counters); SYSPROF_AVAILABLE_IN_ALL -SysprofCaptureReader *sysprof_capture_writer_create_reader (SysprofCaptureWriter *self, - GError **error); +SysprofCaptureReader *sysprof_capture_writer_create_reader (SysprofCaptureWriter *self); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_splice (SysprofCaptureWriter *self, - SysprofCaptureWriter *dest, - GError **error); +bool sysprof_capture_writer_splice (SysprofCaptureWriter *self, + SysprofCaptureWriter *dest); SYSPROF_AVAILABLE_IN_ALL -gboolean sysprof_capture_writer_cat (SysprofCaptureWriter *self, - SysprofCaptureReader *reader, - GError **error); -G_GNUC_INTERNAL -gboolean _sysprof_capture_writer_add_raw (SysprofCaptureWriter *self, +bool sysprof_capture_writer_cat (SysprofCaptureWriter *self, + SysprofCaptureReader *reader); +SYSPROF_INTERNAL +bool _sysprof_capture_writer_add_raw (SysprofCaptureWriter *self, const SysprofCaptureFrame *frame); -G_GNUC_INTERNAL -gboolean _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, - int fd, - GError **error) G_GNUC_INTERNAL; -G_GNUC_INTERNAL -gboolean _sysprof_capture_writer_set_time_range (SysprofCaptureWriter *self, - gint64 start_time, - gint64 end_time) G_GNUC_INTERNAL; +SYSPROF_INTERNAL +bool _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, + int fd) SYSPROF_INTERNAL; +SYSPROF_INTERNAL +bool _sysprof_capture_writer_set_time_range (SysprofCaptureWriter *self, + int64_t start_time, + int64_t end_time) SYSPROF_INTERNAL; - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref) - -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-capture.h b/src/libsysprof-capture/sysprof-capture.h index 59b68b91..ac2f1c25 100644 --- a/src/libsysprof-capture/sysprof-capture.h +++ b/src/libsysprof-capture/sysprof-capture.h @@ -56,10 +56,6 @@ #pragma once -#include - -G_BEGIN_DECLS - #define SYSPROF_CAPTURE_INSIDE # include "sysprof-address.h" @@ -74,5 +70,3 @@ G_BEGIN_DECLS # include "sysprof-version-macros.h" #undef SYSPROF_CAPTURE_INSIDE - -G_END_DECLS diff --git a/src/libsysprof-capture/sysprof-clock.c b/src/libsysprof-capture/sysprof-clock.c index 066605c3..cbaafa1c 100644 --- a/src/libsysprof-capture/sysprof-clock.c +++ b/src/libsysprof-capture/sysprof-clock.c @@ -54,18 +54,20 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-clock" - #include "config.h" -#include "sysprof-clock.h" +#include +#include -gint sysprof_clock = -1; +#include "sysprof-clock.h" +#include "sysprof-macros-internal.h" + +int sysprof_clock = -1; void sysprof_clock_init (void) { - static const gint clock_ids[] = { + static const int clock_ids[] = { CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW, #ifdef __linux__ @@ -78,7 +80,7 @@ sysprof_clock_init (void) if (sysprof_clock != -1) return; - for (guint i = 0; i < G_N_ELEMENTS (clock_ids); i++) + for (unsigned int i = 0; i < SYSPROF_N_ELEMENTS (clock_ids); i++) { struct timespec ts; int clock_id = clock_ids [i]; @@ -90,5 +92,5 @@ sysprof_clock_init (void) } } - g_assert_not_reached (); + sysprof_assert_not_reached (); } diff --git a/src/libsysprof-capture/sysprof-clock.h b/src/libsysprof-capture/sysprof-clock.h index ac101a33..c127c09d 100644 --- a/src/libsysprof-capture/sysprof-clock.h +++ b/src/libsysprof-capture/sysprof-clock.h @@ -56,18 +56,19 @@ #pragma once -#include +#include #include +#include "sysprof-macros.h" #include "sysprof-version-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS -typedef gint SysprofClock; -typedef gint64 SysprofTimeStamp; -typedef gint32 SysprofTimeSysprofan; +typedef int SysprofClock; +typedef int64_t SysprofTimeStamp; +typedef int32_t SysprofTimeSysprofan; -#define SYSPROF_NSEC_PER_SEC G_GINT64_CONSTANT(1000000000) +#define SYSPROF_NSEC_PER_SEC SYSPROF_INT64_CONSTANT(1000000000) SYSPROF_AVAILABLE_IN_ALL SysprofClock sysprof_clock; @@ -78,7 +79,7 @@ sysprof_clock_get_current_time (void) struct timespec ts; SysprofClock clock = sysprof_clock; - if G_UNLIKELY (clock == -1) + if SYSPROF_UNLIKELY (clock == -1) clock = CLOCK_MONOTONIC; clock_gettime (clock, &ts); @@ -94,4 +95,4 @@ sysprof_clock_get_relative_time (SysprofTimeStamp epoch) SYSPROF_AVAILABLE_IN_ALL void sysprof_clock_init (void); -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-collector.c b/src/libsysprof-capture/sysprof-collector.c index 3c96065f..d95aee8c 100644 --- a/src/libsysprof-capture/sysprof-collector.c +++ b/src/libsysprof-capture/sysprof-collector.c @@ -54,56 +54,70 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-collector" - #ifndef _GNU_SOURCE # define _GNU_SOURCE #endif -#include -#include -#include +#include +#include +#include +#include #ifdef __linux__ # include #endif +#include +#include +#include #include #include +#include #include +#include #include #include "mapped-ring-buffer.h" -#include "sysprof-capture-writer.h" +#include "sysprof-capture-util-private.h" #include "sysprof-collector.h" +#include "sysprof-macros-internal.h" #define MAX_UNWIND_DEPTH 128 #define CREATRING "CreatRing\0" #define CREATRING_LEN 10 +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +#ifndef MSG_CMSG_CLOEXEC +#define MSG_CMSG_CLOEXEC 0 +#endif + typedef struct { MappedRingBuffer *buffer; - gboolean is_shared; + bool is_shared; int tid; int pid; } SysprofCollector; -#define COLLECTOR_INVALID ((gpointer)&invalid) +#define COLLECTOR_INVALID ((void *)&invalid) static MappedRingBuffer *request_writer (void); -static void sysprof_collector_free (gpointer data); +static void sysprof_collector_free (void *data); static const SysprofCollector *sysprof_collector_get (void); -static G_LOCK_DEFINE (control_fd); -static GPrivate collector_key = G_PRIVATE_INIT (sysprof_collector_free); -static GPrivate single_trace_key = G_PRIVATE_INIT (NULL); +static pthread_mutex_t control_fd_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_key_t collector_key; /* initialised in sysprof_collector_init() */ +static pthread_key_t single_trace_key; /* initialised in sysprof_collector_init() */ +static pthread_once_t collector_init = PTHREAD_ONCE_INIT; static SysprofCollector *shared_collector; static SysprofCollector invalid; -static inline gboolean +static inline bool use_single_trace (void) { - return GPOINTER_TO_INT (g_private_get (&single_trace_key)); + return (bool) pthread_getspecific (single_trace_key); } static inline int @@ -116,60 +130,218 @@ _do_getcpu (void) #endif } -static inline gsize -realign (gsize size) +static inline size_t +realign (size_t size) { return (size + SYSPROF_CAPTURE_ALIGN - 1) & ~(SYSPROF_CAPTURE_ALIGN - 1); } +static bool +set_fd_blocking (int fd) +{ +#ifdef F_GETFL + long fcntl_flags; + fcntl_flags = fcntl (peer_fd, F_GETFL); + + if (fcntl_flags == -1) + return false; + +#ifdef O_NONBLOCK + fcntl_flags &= ~O_NONBLOCK; +#else + fcntl_flags &= ~O_NDELAY; +#endif + + if (fcntl (peer_fd, F_SETFL, fcntl_flags) == -1) + return false; + + return true; +#else + return false; +#endif +} + +static bool +block_on_poll (int fd, + int condition) +{ + struct pollfd poll_fd; + + poll_fd.fd = fd; + poll_fd.events = condition; + + return (TEMP_FAILURE_RETRY (poll (&poll_fd, 1, -1)) == 1); +} + +static ssize_t +send_blocking (int fd, + const uint8_t *buffer, + size_t buffer_len) +{ + ssize_t res; + + while ((res = TEMP_FAILURE_RETRY (send (fd, buffer, buffer_len, MSG_NOSIGNAL))) < 0) + { + int errsv = errno; + + if (errsv == EWOULDBLOCK || + errsv == EAGAIN) + { + if (!block_on_poll (fd, POLLOUT)) + return -1; + } + else + { + return -1; + } + } + + return res; +} + +static bool +send_all_blocking (int fd, + const uint8_t *buffer, + size_t buffer_len, + size_t *bytes_written) +{ + size_t _bytes_written; + + _bytes_written = 0; + while (_bytes_written < buffer_len) + { + ssize_t res = send_blocking (fd, buffer + _bytes_written, buffer_len - _bytes_written); + if (res == -1) + { + if (bytes_written != NULL) + *bytes_written = _bytes_written; + return false; + } + assert (res > 0); + + _bytes_written += res; + } + + if (bytes_written != NULL) + *bytes_written = _bytes_written; + return true; +} + +static int +receive_fd_blocking (int peer_fd) +{ + ssize_t res; + struct msghdr msg; + struct iovec one_vector; + char one_byte; + uint8_t cmsg_buffer[CMSG_SPACE (sizeof (int))]; + struct cmsghdr *cmsg; + const int *fds = NULL; + size_t n_fds = 0; + + one_vector.iov_base = &one_byte; + one_vector.iov_len = 1; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &one_vector; + msg.msg_iovlen = 1; + msg.msg_flags = MSG_CMSG_CLOEXEC; + msg.msg_control = &cmsg_buffer; + msg.msg_controllen = sizeof (cmsg_buffer); + + while ((res = TEMP_FAILURE_RETRY (recvmsg (peer_fd, &msg, msg.msg_flags))) < 0) + { + int errsv = errno; + + if (errsv == EWOULDBLOCK || + errsv == EAGAIN) + { + if (!block_on_poll (peer_fd, POLLIN)) + return -1; + } + else + { + return -1; + } + } + + /* Decode the returned control message */ + cmsg = CMSG_FIRSTHDR (&msg); + if (cmsg == NULL) + return -1; + + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + return -1; + + /* non-integer number of FDs */ + if ((cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) % 4 != 0) + return -1; + + fds = (const int *) CMSG_DATA (cmsg); + n_fds = (cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) / sizeof (*fds); + + /* only expecting one FD */ + if (n_fds != 1) + goto close_fds_err; + + for (size_t i = 0; i < n_fds; i++) + { + if (fds[i] < 0) + goto close_fds_err; + } + + /* only expecting one control message */ + cmsg = CMSG_NXTHDR (&msg, cmsg); + if (cmsg != NULL) + goto close_fds_err; + + return fds[0]; + +close_fds_err: + for (size_t i = 0; i < n_fds; i++) + close (fds[i]); + + return -1; +} + +/* Called with @control_fd_lock held. */ static MappedRingBuffer * request_writer (void) { - static GUnixConnection *conn; + static int peer_fd = -1; MappedRingBuffer *buffer = NULL; - if (conn == NULL) + if (peer_fd == -1) { - const gchar *fdstr = g_getenv ("SYSPROF_CONTROL_FD"); - int peer_fd = -1; + const char *fdstr = getenv ("SYSPROF_CONTROL_FD"); if (fdstr != NULL) peer_fd = atoi (fdstr); - g_unsetenv ("SYSPROF_CONTROL_FD"); + unsetenv ("SYSPROF_CONTROL_FD"); if (peer_fd > 0) { - g_autoptr(GSocket) sock = NULL; + (void) set_fd_blocking (peer_fd); - g_unix_set_fd_nonblocking (peer_fd, FALSE, NULL); - - if ((sock = g_socket_new_from_fd (peer_fd, NULL))) - { - g_autoptr(GSocketConnection) scon = NULL; - - g_socket_set_blocking (sock, TRUE); - - if ((scon = g_socket_connection_factory_create_connection (sock)) && - G_IS_UNIX_CONNECTION (scon)) - conn = g_object_ref (G_UNIX_CONNECTION (scon)); - } +#ifdef SO_NOSIGPIPE + { + int opt_value = 1; + (void) setsockopt (peer_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt_value, sizeof (opt_value)); + } +#endif } } - if (conn != NULL) + if (peer_fd >= 0) { - GOutputStream *out_stream; - gsize len; - - out_stream = g_io_stream_get_output_stream (G_IO_STREAM (conn)); - - if (g_output_stream_write_all (G_OUTPUT_STREAM (out_stream), CREATRING, CREATRING_LEN, &len, NULL, NULL) && - len == CREATRING_LEN) + if (send_all_blocking (peer_fd, (const uint8_t *) CREATRING, CREATRING_LEN, NULL)) { - gint ring_fd = g_unix_connection_receive_fd (conn, NULL, NULL); + int ring_fd = receive_fd_blocking (peer_fd); - if (ring_fd > -1) + if (ring_fd >= 0) { buffer = mapped_ring_buffer_new_writer (ring_fd); close (ring_fd); @@ -177,7 +349,7 @@ request_writer (void) } } - return g_steal_pointer (&buffer); + return sysprof_steal_pointer (&buffer); } static void @@ -185,7 +357,7 @@ write_final_frame (MappedRingBuffer *ring) { SysprofCaptureFrame *fr; - g_assert (ring != NULL); + assert (ring != NULL); if ((fr = mapped_ring_buffer_allocate (ring, sizeof *fr))) { @@ -199,13 +371,13 @@ write_final_frame (MappedRingBuffer *ring) } static void -sysprof_collector_free (gpointer data) +sysprof_collector_free (void *data) { SysprofCollector *collector = data; if (collector != NULL && collector != COLLECTOR_INVALID) { - MappedRingBuffer *buffer = g_steal_pointer (&collector->buffer); + MappedRingBuffer *buffer = sysprof_steal_pointer (&collector->buffer); if (buffer != NULL) { @@ -213,33 +385,41 @@ sysprof_collector_free (gpointer data) mapped_ring_buffer_unref (buffer); } - g_free (collector); + free (collector); } } static const SysprofCollector * sysprof_collector_get (void) { - const SysprofCollector *collector = g_private_get (&collector_key); + const SysprofCollector *collector; + + sysprof_collector_init (); + collector = pthread_getspecific (collector_key); /* We might have gotten here recursively */ - if G_UNLIKELY (collector == COLLECTOR_INVALID) + if SYSPROF_UNLIKELY (collector == COLLECTOR_INVALID) return COLLECTOR_INVALID; - if G_LIKELY (collector != NULL) + if SYSPROF_LIKELY (collector != NULL) return collector; if (use_single_trace () && shared_collector != COLLECTOR_INVALID) return shared_collector; { - SysprofCollector *self; + SysprofCollector *self, *old_collector; - g_private_replace (&collector_key, COLLECTOR_INVALID); + /* First set the collector to invalid so anything recursive + * here fails instead of becoming re-entrant. + */ + pthread_setspecific (collector_key, COLLECTOR_INVALID); - G_LOCK (control_fd); + /* Now we can malloc without ending up here again */ + self = sysprof_malloc0 (sizeof (SysprofCollector)); + if (self == NULL) + return COLLECTOR_INVALID; - self = g_new0 (SysprofCollector, 1); self->pid = getpid (); #ifdef __linux__ self->tid = syscall (__NR_gettid, 0); @@ -247,66 +427,91 @@ sysprof_collector_get (void) self->tid = self->pid; #endif - if (g_getenv ("SYSPROF_CONTROL_FD") != NULL) + pthread_mutex_lock (&control_fd_lock); + + if (getenv ("SYSPROF_CONTROL_FD") != NULL) self->buffer = request_writer (); - if (self->is_shared) - shared_collector = self; - else - g_private_replace (&collector_key, self); + /* Update the stored collector */ + old_collector = pthread_getspecific (collector_key); - G_UNLOCK (control_fd); + if (self->is_shared) + { + if (pthread_setspecific (collector_key, COLLECTOR_INVALID) != 0) + goto fail; + sysprof_collector_free (old_collector); + shared_collector = self; + } + else + { + if (pthread_setspecific (collector_key, self) != 0) + goto fail; + sysprof_collector_free (old_collector); + } + + pthread_mutex_unlock (&control_fd_lock); return self; + +fail: + pthread_mutex_unlock (&control_fd_lock); + sysprof_collector_free (self); + + return COLLECTOR_INVALID; } } +static void +collector_init_cb (void) +{ + if (SYSPROF_UNLIKELY (pthread_key_create (&collector_key, sysprof_collector_free) != 0)) + abort (); + if (SYSPROF_UNLIKELY (pthread_key_create (&single_trace_key, NULL) != 0)) + abort (); + + sysprof_clock_init (); +} + void sysprof_collector_init (void) { - static gsize once_init; - - if (g_once_init_enter (&once_init)) - { - sysprof_clock_init (); - (void)sysprof_collector_get (); - g_once_init_leave (&once_init, TRUE); - } + if SYSPROF_UNLIKELY (pthread_once (&collector_init, collector_init_cb) != 0) + abort (); } #define COLLECTOR_BEGIN \ - G_STMT_START { \ + do { \ const SysprofCollector *collector = sysprof_collector_get (); \ - if G_LIKELY (collector->buffer) \ + if SYSPROF_LIKELY (collector->buffer) \ { \ - if G_UNLIKELY (collector->is_shared) \ - G_LOCK (control_fd); \ + if SYSPROF_UNLIKELY (collector->is_shared) \ + pthread_mutex_lock (&control_fd_lock); \ \ { #define COLLECTOR_END \ } \ \ - if G_UNLIKELY (collector->is_shared) \ - G_UNLOCK (control_fd); \ + if SYSPROF_UNLIKELY (collector->is_shared) \ + pthread_mutex_unlock (&control_fd_lock); \ } \ - } G_STMT_END + } while (0) void sysprof_collector_allocate (SysprofCaptureAddress alloc_addr, - gint64 alloc_size, + int64_t alloc_size, SysprofBacktraceFunc backtrace_func, - gpointer backtrace_data) + void *backtrace_data) { COLLECTOR_BEGIN { SysprofCaptureAllocation *ev; - gsize len; + size_t len; len = sizeof *ev + (sizeof (SysprofCaptureAllocation) * MAX_UNWIND_DEPTH); if ((ev = mapped_ring_buffer_allocate (collector->buffer, len))) { - gint n_addrs; + int n_addrs; /* First take a backtrace, so that backtrace_func() can overwrite * a little bit of data *BEFORE* ev->addrs as stratch space. This @@ -321,7 +526,7 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr, else n_addrs = 0; - ev->n_addrs = CLAMP (n_addrs, 0, MAX_UNWIND_DEPTH); + ev->n_addrs = ((n_addrs < 0) ? 0 : (n_addrs > MAX_UNWIND_DEPTH) ? MAX_UNWIND_DEPTH : n_addrs); ev->frame.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs; ev->frame.type = SYSPROF_CAPTURE_FRAME_ALLOCATION; ev->frame.cpu = _do_getcpu (); @@ -339,18 +544,18 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr, } void -sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, - gpointer backtrace_data) +sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, + void *backtrace_data) { COLLECTOR_BEGIN { SysprofCaptureSample *ev; - gsize len; + size_t len; len = sizeof *ev + (sizeof (SysprofCaptureSample) * MAX_UNWIND_DEPTH); if ((ev = mapped_ring_buffer_allocate (collector->buffer, len))) { - gint n_addrs; + int n_addrs; /* See comment from sysprof_collector_allocate(). */ if (backtrace_func) @@ -358,7 +563,7 @@ sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, else n_addrs = 0; - ev->n_addrs = CLAMP (n_addrs, 0, MAX_UNWIND_DEPTH); + ev->n_addrs = ((n_addrs < 0) ? 0 : (n_addrs > MAX_UNWIND_DEPTH) ? MAX_UNWIND_DEPTH : n_addrs); ev->frame.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs; ev->frame.type = SYSPROF_CAPTURE_FRAME_SAMPLE; ev->frame.cpu = _do_getcpu (); @@ -374,16 +579,16 @@ sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, } void -sysprof_collector_mark (gint64 time, - gint64 duration, - const gchar *group, - const gchar *mark, - const gchar *message) +sysprof_collector_mark (int64_t time, + int64_t duration, + const char *group, + const char *mark, + const char *message) { COLLECTOR_BEGIN { SysprofCaptureMark *ev; - gsize len; - gsize sl; + size_t len; + size_t sl; if (group == NULL) group = ""; @@ -405,8 +610,8 @@ sysprof_collector_mark (gint64 time, ev->frame.pid = collector->pid; ev->frame.time = time; ev->duration = duration; - g_strlcpy (ev->group, group, sizeof ev->group); - g_strlcpy (ev->name, mark, sizeof ev->name); + _sysprof_strlcpy (ev->group, group, sizeof ev->group); + _sysprof_strlcpy (ev->name, mark, sizeof ev->name); memcpy (ev->message, message, sl); ev->message[sl] = 0; @@ -417,14 +622,14 @@ sysprof_collector_mark (gint64 time, } void -sysprof_collector_log (GLogLevelFlags severity, - const gchar *domain, - const gchar *message) +sysprof_collector_log (int severity, + const char *domain, + const char *message) { COLLECTOR_BEGIN { SysprofCaptureLog *ev; - gsize len; - gsize sl; + size_t len; + size_t sl; if (domain == NULL) domain = ""; @@ -445,7 +650,7 @@ sysprof_collector_log (GLogLevelFlags severity, ev->severity = severity & 0xFFFF; ev->padding1 = 0; ev->padding2 = 0; - g_strlcpy (ev->domain, domain, sizeof ev->domain); + _sysprof_strlcpy (ev->domain, domain, sizeof ev->domain); memcpy (ev->message, message, sl); ev->message[sl] = 0; @@ -456,20 +661,20 @@ sysprof_collector_log (GLogLevelFlags severity, } void -sysprof_collector_log_printf (GLogLevelFlags severity, - const gchar *domain, - const gchar *format, +sysprof_collector_log_printf (int severity, + const char *domain, + const char *format, ...) { COLLECTOR_BEGIN { - g_autofree gchar *formatted = NULL; + char formatted[2048]; SysprofCaptureLog *ev; va_list args; - gsize len; - gsize sl; + size_t len; + size_t sl; va_start (args, format); - formatted = g_strdup_vprintf (format, args); + vsnprintf (formatted, sizeof (formatted), format, args); va_end (args); if (domain == NULL) @@ -488,7 +693,7 @@ sysprof_collector_log_printf (GLogLevelFlags severity, ev->severity = severity & 0xFFFF; ev->padding1 = 0; ev->padding2 = 0; - g_strlcpy (ev->domain, domain, sizeof ev->domain); + _sysprof_strlcpy (ev->domain, domain, sizeof ev->domain); memcpy (ev->message, formatted, sl); ev->message[sl] = 0; diff --git a/src/libsysprof-capture/sysprof-collector.h b/src/libsysprof-capture/sysprof-collector.h index 68ac6882..b91a5a7c 100644 --- a/src/libsysprof-capture/sysprof-collector.h +++ b/src/libsysprof-capture/sysprof-collector.h @@ -57,34 +57,34 @@ #pragma once #include "sysprof-capture-types.h" -#include "sysprof-capture-writer.h" +#include "sysprof-macros.h" -G_BEGIN_DECLS +SYSPROF_BEGIN_DECLS SYSPROF_AVAILABLE_IN_3_36 void sysprof_collector_init (void); SYSPROF_AVAILABLE_IN_3_36 void sysprof_collector_allocate (SysprofCaptureAddress alloc_addr, - gint64 alloc_size, + int64_t alloc_size, SysprofBacktraceFunc backtrace_func, - gpointer backtrace_data); + void *backtrace_data); SYSPROF_AVAILABLE_IN_3_36 void sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, - gpointer backtrace_data); + void *backtrace_data); SYSPROF_AVAILABLE_IN_3_36 -void sysprof_collector_mark (gint64 time, - gint64 duration, - const gchar *group, - const gchar *mark, - const gchar *message); +void sysprof_collector_mark (int64_t time, + int64_t duration, + const char *group, + const char *mark, + const char *message); SYSPROF_AVAILABLE_IN_3_36 -void sysprof_collector_log (GLogLevelFlags severity, - const gchar *domain, - const gchar *message); +void sysprof_collector_log (int severity, + const char *domain, + const char *message); SYSPROF_AVAILABLE_IN_3_38 -void sysprof_collector_log_printf (GLogLevelFlags severity, - const gchar *domain, - const gchar *format, - ...) G_GNUC_PRINTF (3, 4); +void sysprof_collector_log_printf (int severity, + const char *domain, + const char *format, + ...) SYSPROF_PRINTF (3, 4); -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-macros-internal.h b/src/libsysprof-capture/sysprof-macros-internal.h new file mode 100644 index 00000000..cf814dad --- /dev/null +++ b/src/libsysprof-capture/sysprof-macros-internal.h @@ -0,0 +1,77 @@ +/* sysprof-macros.h + * + * Copyright 2020 Endless OS Foundation + * + * Author: + * - Philip Withnall + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Subject to the terms and conditions of this license, each copyright holder + * and contributor hereby grants to those receiving rights under this license + * a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + * irrevocable (except for failure to satisfy the conditions of this license) + * patent license to make, have made, use, offer to sell, sell, import, and + * otherwise transfer this software, where such license applies only to those + * patent claims, already acquired or hereafter acquired, licensable by such + * copyright holder or contributor that are necessarily infringed by: + * + * (a) their Contribution(s) (the licensed copyrights of copyright holders + * and non-copyrightable additions of contributors, in source or binary + * form) alone; or + * + * (b) combination of their Contribution(s) with the work of authorship to + * which such Contribution(s) was added by such copyright holder or + * contributor, if, at the time the Contribution is added, such addition + * causes such combination to be necessarily infringed. The patent license + * shall not apply to any other combinations which include the + * Contribution. + * + * Except as expressly stated above, no rights or licenses from any copyright + * holder or contributor is granted under this license, whether expressly, by + * implication, estoppel or otherwise. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ + +#pragma once + +#define sysprof_assert_not_reached() assert (false) + +#define SYSPROF_N_ELEMENTS(a) (sizeof (a) / sizeof (*a)) + +#define sysprof_steal_pointer(pp) __extension__ ({__typeof(*(pp)) _p = *(pp); *(pp) = NULL; _p;}) + +#define sysprof_clear_pointer(pp, destroy) \ + do { \ + __typeof((pp)) _pp = (pp); \ + __typeof(*(pp)) _p = *_pp; \ + *_pp = NULL; \ + if (_p != NULL) \ + (destroy) (_p); \ + } while (0) + +#define sysprof_strdup(s) ((s) ? strdup(s) : NULL) diff --git a/src/libsysprof-capture/sysprof-macros.h b/src/libsysprof-capture/sysprof-macros.h new file mode 100644 index 00000000..be2afc1c --- /dev/null +++ b/src/libsysprof-capture/sysprof-macros.h @@ -0,0 +1,98 @@ +/* sysprof-macros.h + * + * Copyright 2020 Endless OS Foundation + * + * Author: + * - Philip Withnall + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Subject to the terms and conditions of this license, each copyright holder + * and contributor hereby grants to those receiving rights under this license + * a perpetual, worldwide, non-exclusive, no-charge, royalty-free, + * irrevocable (except for failure to satisfy the conditions of this license) + * patent license to make, have made, use, offer to sell, sell, import, and + * otherwise transfer this software, where such license applies only to those + * patent claims, already acquired or hereafter acquired, licensable by such + * copyright holder or contributor that are necessarily infringed by: + * + * (a) their Contribution(s) (the licensed copyrights of copyright holders + * and non-copyrightable additions of contributors, in source or binary + * form) alone; or + * + * (b) combination of their Contribution(s) with the work of authorship to + * which such Contribution(s) was added by such copyright holder or + * contributor, if, at the time the Contribution is added, such addition + * causes such combination to be necessarily infringed. The patent license + * shall not apply to any other combinations which include the + * Contribution. + * + * Except as expressly stated above, no rights or licenses from any copyright + * holder or contributor is granted under this license, whether expressly, by + * implication, estoppel or otherwise. + * + * DISCLAIMER + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * SPDX-License-Identifier: BSD-2-Clause-Patent + */ + +#pragma once + +#include + +#if INT_MAX == LONG_MAX +#define SYSPROF_INT64_CONSTANT(x) x##ULL +#define SYSPROF_UINT64_CONSTANT(x) x##LL +#else +#define SYSPROF_INT64_CONSTANT(x) x##UL +#define SYSPROF_UINT64_CONSTANT(x) x##L +#endif + +#ifdef __cplusplus +#define SYSPROF_BEGIN_DECLS extern "C" { +#define SYSPROF_END_DECLS } +#else +#define SYSPROF_BEGIN_DECLS +#define SYSPROF_END_DECLS +#endif + +#if defined (__GNUC__) +#define SYSPROF_INTERNAL __attribute__((visibility("hidden"))) +#else +#define SYSPROF_INTERNAL +#endif + +#if defined(__GNUC__) +#define SYSPROF_LIKELY(expr) (__builtin_expect (!!(expr), 1)) +#define SYSPROF_UNLIKELY(expr) (__builtin_expect (!!(expr), 0)) +#else +#define SYSPROF_LIKELY(expr) (expr) +#define SYSPROF_UNLIKELY(expr) (expr) +#endif + +#if defined(__GNUC__) +#define SYSPROF_PRINTF(format_idx, arg_idx) __attribute__((format(printf, format_idx, arg_idx))) +#else +#define SYSPROF_PRINTF(format_idx, arg_idx) +#endif diff --git a/src/libsysprof-capture/sysprof-platform.c b/src/libsysprof-capture/sysprof-platform.c index 99c9a55c..a80ab890 100644 --- a/src/libsysprof-capture/sysprof-platform.c +++ b/src/libsysprof-capture/sysprof-platform.c @@ -54,18 +54,36 @@ * SPDX-License-Identifier: BSD-2-Clause-Patent */ -#define G_LOG_DOMAIN "sysprof-platform" - #include "config.h" -#include -#include +#include #include #include #include "sysprof-capture-util-private.h" #include "sysprof-platform.h" +#ifndef __NR_memfd_create +static const char * +get_tmpdir (void) +{ + const char *tmpdir = NULL; + + if (tmpdir == NULL || *tmpdir == '\0') + tmpdir = getenv ("TMPDIR"); + +#ifdef P_tmpdir + if (tmpdir == NULL || *tmpdir == '\0') + tmpdir = P_tmpdir; +#endif + + if (tmpdir == NULL || *tmpdir == '\0') + tmpdir = "/tmp"; + + return tmpdir; +} +#endif /* !__NR_memfd_create */ + /** * sysprof_memfd_create: * @name: (nullable): A descriptive name for the memfd or %NULL @@ -77,15 +95,17 @@ * Returns: An fd if successful; otherwise -1 and errno is set. */ int -sysprof_memfd_create (const gchar *name) +sysprof_memfd_create (const char *name) { #ifdef __NR_memfd_create if (name == NULL) name = "[sysprof]"; return syscall (__NR_memfd_create, name, 0); #else - gchar *name_used = NULL; int fd; + const char *tmpdir; + char *template = NULL; + size_t template_len = 0; /* * TODO: It would be nice to ensure tmpfs @@ -95,14 +115,28 @@ sysprof_memfd_create (const gchar *name) * that the tmpfile we open is on tmpfs so that we get anonymous backed * pages after unlinking. */ - fd = g_file_open_tmp (NULL, &name_used, NULL); - if (name_used != NULL) + tmpdir = get_tmpdir (); + template_len = strlen (tmpdir) + 1 + strlen ("sysprof-XXXXXX") + 1; + template = sysprof_malloc0 (template_len); + if (template == NULL) { - g_unlink (name_used); - g_free (name_used); + errno = ENOMEM; + return -1; } + snprintf (template, template_len, "%s/sysprof-XXXXXX", tmpdir); + + fd = TEMP_FAILURE_RETRY (mkostemp (template, O_BINARY | O_CLOEXEC)); + if (fd < 0) + { + free (template); + return -1; + } + + unlink (template); + free (template); + return fd; #endif } @@ -116,7 +150,7 @@ sysprof_memfd_create (const gchar *name) * * Since: 3.36 */ -gsize +size_t sysprof_getpagesize (void) { return _sysprof_getpagesize (); diff --git a/src/libsysprof-capture/sysprof-platform.h b/src/libsysprof-capture/sysprof-platform.h index 6dbe4ff2..44c3e964 100644 --- a/src/libsysprof-capture/sysprof-platform.h +++ b/src/libsysprof-capture/sysprof-platform.h @@ -56,13 +56,17 @@ #pragma once -#include "sysprof-version-macros.h" +#include +#include -G_BEGIN_DECLS +#include "sysprof-version-macros.h" +#include "sysprof-macros.h" + +SYSPROF_BEGIN_DECLS SYSPROF_AVAILABLE_IN_ALL -int sysprof_memfd_create (const gchar *desc); +int sysprof_memfd_create (const char *desc); SYSPROF_AVAILABLE_IN_3_36 -gsize sysprof_getpagesize (void); +size_t sysprof_getpagesize (void); -G_END_DECLS +SYSPROF_END_DECLS diff --git a/src/libsysprof-capture/sysprof-version-macros.h b/src/libsysprof-capture/sysprof-version-macros.h index 8fa1df6f..43930127 100644 --- a/src/libsysprof-capture/sysprof-version-macros.h +++ b/src/libsysprof-capture/sysprof-version-macros.h @@ -56,42 +56,54 @@ #pragma once -#include - #include "sysprof-version.h" #ifndef _SYSPROF_EXTERN #define _SYSPROF_EXTERN extern #endif +#if defined(__GNUC__) || defined (__clang__) +#define _SYSPROF_DEPRECATED __attribute__((__deprecated__)) +#define _SYSPROF_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead"))) +#define _SYSPROF_UNAVAILABLE(maj,min) __attribute__((__deprecated__("Not available before " #maj "." #min))) +#elif defined(_MSC_VER) +#define _SYSPROF_DEPRECATED __declspec(deprecated) +#define _SYSPROF_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead")) +#define _SYSPROF_UNAVAILABLE(maj,min) __declspec(deprecated("is not available before " #maj "." #min)) +#else +#define _SYSPROF_DEPRECATED +#define _SYSPROF_DEPRECATED_FOR(f) +#define _SYSPROF_UNAVAILABLE(maj,min) +#endif + #ifdef SYSPROF_DISABLE_DEPRECATION_WARNINGS #define SYSPROF_DEPRECATED _SYSPROF_EXTERN #define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN #define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN #else -#define SYSPROF_DEPRECATED G_DEPRECATED _SYSPROF_EXTERN -#define SYSPROF_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _SYSPROF_EXTERN -#define SYSPROF_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _SYSPROF_EXTERN +#define SYSPROF_DEPRECATED _SYSPROF_DEPRECATED _SYSPROF_EXTERN +#define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN +#define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN #endif -#define SYSPROF_VERSION_3_34 (G_ENCODE_VERSION (3, 34)) -#define SYSPROF_VERSION_3_36 (G_ENCODE_VERSION (3, 36)) -#define SYSPROF_VERSION_3_38 (G_ENCODE_VERSION (3, 38)) +#define SYSPROF_VERSION_3_34 (SYSPROF_ENCODE_VERSION (3, 34, 0)) +#define SYSPROF_VERSION_3_36 (SYSPROF_ENCODE_VERSION (3, 36, 0)) +#define SYSPROF_VERSION_3_38 (SYSPROF_ENCODE_VERSION (3, 38, 0)) #if (SYSPROF_MINOR_VERSION == 99) -# define SYSPROF_VERSION_CUR_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0)) +# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0, 0)) #elif (SYSPROF_MINOR_VERSION % 2) -# define SYSPROF_VERSION_CUR_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION + 1)) +# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION + 1, 0)) #else -# define SYSPROF_VERSION_CUR_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION)) +# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION, 0)) #endif #if (SYSPROF_MINOR_VERSION == 99) -# define SYSPROF_VERSION_PREV_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0)) +# define SYSPROF_VERSION_PREV_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0, 0)) #elif (SYSPROF_MINOR_VERSION % 2) -# define SYSPROF_VERSION_PREV_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 1)) +# define SYSPROF_VERSION_PREV_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 1, 0)) #else -# define SYSPROF_VERSION_PREV_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 2)) +# define SYSPROF_VERSION_PREV_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 2, 0)) #endif /** diff --git a/src/libsysprof-ui/sysprof-battery-aid.c b/src/libsysprof-ui/sysprof-battery-aid.c index ab44a281..8bef1979 100644 --- a/src/libsysprof-ui/sysprof-battery-aid.c +++ b/src/libsysprof-ui/sysprof-battery-aid.c @@ -81,7 +81,7 @@ sysprof_battery_aid_prepare (SysprofAid *self, #endif } -static gboolean +static bool collect_battery_counters (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-callgraph-aid.c b/src/libsysprof-ui/sysprof-callgraph-aid.c index 5b0ebb07..f12be766 100644 --- a/src/libsysprof-ui/sysprof-callgraph-aid.c +++ b/src/libsysprof-ui/sysprof-callgraph-aid.c @@ -114,7 +114,7 @@ sysprof_callgraph_aid_prepare (SysprofAid *self, #endif } -static gboolean +static bool discover_samples_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-counters-aid.c b/src/libsysprof-ui/sysprof-counters-aid.c index 2324569e..c1d855bb 100644 --- a/src/libsysprof-ui/sysprof-counters-aid.c +++ b/src/libsysprof-ui/sysprof-counters-aid.c @@ -123,7 +123,7 @@ build_title (const SysprofCaptureCounter *ctr) return g_string_free (str, FALSE); } -static gboolean +static bool collect_counters (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-cpu-aid.c b/src/libsysprof-ui/sysprof-cpu-aid.c index 39029576..56094888 100644 --- a/src/libsysprof-ui/sysprof-cpu-aid.c +++ b/src/libsysprof-ui/sysprof-cpu-aid.c @@ -85,7 +85,7 @@ sysprof_cpu_aid_prepare (SysprofAid *self, #endif } -static gboolean +static bool collect_info (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-depth-visualizer.c b/src/libsysprof-ui/sysprof-depth-visualizer.c index 118489d7..a3a4df5f 100644 --- a/src/libsysprof-ui/sysprof-depth-visualizer.c +++ b/src/libsysprof-ui/sysprof-depth-visualizer.c @@ -62,7 +62,7 @@ state_free (State *st) g_slice_free (State, st); } -static gboolean +static bool discover_max_n_addr (const SysprofCaptureFrame *frame, gpointer user_data) { @@ -78,7 +78,7 @@ discover_max_n_addr (const SysprofCaptureFrame *frame, return TRUE; } -static gboolean +static bool build_point_cache_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-details-page.c b/src/libsysprof-ui/sysprof-details-page.c index 3f9fcbda..0c41ec46 100644 --- a/src/libsysprof-ui/sysprof-details-page.c +++ b/src/libsysprof-ui/sysprof-details-page.c @@ -135,7 +135,7 @@ update_cpu_info_cb (GObject *object, gtk_label_set_label (self->cpu_label, str); } -static gboolean +static bool cpu_info_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-diskstat-aid.c b/src/libsysprof-ui/sysprof-diskstat-aid.c index aff40ecd..c87cb3e7 100644 --- a/src/libsysprof-ui/sysprof-diskstat-aid.c +++ b/src/libsysprof-ui/sysprof-diskstat-aid.c @@ -80,7 +80,7 @@ sysprof_diskstat_aid_prepare (SysprofAid *self, sysprof_profiler_add_source (profiler, source); } -static gboolean +static bool collect_diskstat_counters (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-display.c b/src/libsysprof-ui/sysprof-display.c index e9886d5a..6be5faf1 100644 --- a/src/libsysprof-ui/sysprof-display.c +++ b/src/libsysprof-ui/sysprof-display.c @@ -143,7 +143,7 @@ sysprof_display_profiler_stopped_cb (SysprofDisplay *self, g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(GError) error = NULL; - if (!(reader = sysprof_capture_writer_create_reader (writer, &error))) + if (!(reader = sysprof_capture_writer_create_reader_with_error (writer, &error))) { g_warning ("Failed to create capture creader: %s\n", error->message); gtk_stack_set_visible_child (priv->stack, GTK_WIDGET (priv->failed_view)); @@ -1071,7 +1071,7 @@ sysprof_display_open (SysprofDisplay *self, g_set_object (&priv->file, file); - if (!(reader = sysprof_capture_reader_new (path, &error))) + if (!(reader = sysprof_capture_reader_new_with_error (path, &error))) { GtkWidget *dialog; GtkWidget *window; @@ -1229,7 +1229,7 @@ sysprof_display_save (SysprofDisplay *self) g_autofree gchar *path = g_file_get_path (file); g_autoptr(GError) error = NULL; - if (!sysprof_capture_reader_save_as (priv->reader, path, &error)) + if (!sysprof_capture_reader_save_as_with_error (priv->reader, path, &error)) { GtkWidget *msg; diff --git a/src/libsysprof-ui/sysprof-duplex-visualizer.c b/src/libsysprof-ui/sysprof-duplex-visualizer.c index 82bdca03..1901258a 100644 --- a/src/libsysprof-ui/sysprof-duplex-visualizer.c +++ b/src/libsysprof-ui/sysprof-duplex-visualizer.c @@ -73,7 +73,7 @@ typedef struct G_DEFINE_TYPE (SysprofDuplexVisualizer, sysprof_duplex_visualizer, SYSPROF_TYPE_VISUALIZER) -static gboolean +static bool collect_ranges_cb (const SysprofCaptureFrame *frame, gpointer data) { @@ -126,7 +126,7 @@ collect_ranges_cb (const SysprofCaptureFrame *frame, return TRUE; } -static gboolean +static bool collect_values_cb (const SysprofCaptureFrame *frame, gpointer data) { diff --git a/src/libsysprof-ui/sysprof-line-visualizer.c b/src/libsysprof-ui/sysprof-line-visualizer.c index 188b2e1f..5075a4f9 100644 --- a/src/libsysprof-ui/sysprof-line-visualizer.c +++ b/src/libsysprof-ui/sysprof-line-visualizer.c @@ -613,7 +613,7 @@ calc_y_int64 (gint64 lower, return (gdouble)(value - lower) / (gdouble)(upper - lower); } -static gboolean +static bool sysprof_line_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame, gpointer user_data) { @@ -655,7 +655,7 @@ sysprof_line_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame, return TRUE; } -static gboolean +static bool sysprof_line_visualizer_load_data_range_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-log-model.c b/src/libsysprof-ui/sysprof-log-model.c index 276ea063..8d67254f 100644 --- a/src/libsysprof-ui/sysprof-log-model.c +++ b/src/libsysprof-ui/sysprof-log-model.c @@ -289,7 +289,7 @@ sysprof_log_model_init (SysprofLogModel *self) self->items = g_array_new (FALSE, FALSE, sizeof (Item)); } -static gboolean +static bool cursor_foreach_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-logs-aid.c b/src/libsysprof-ui/sysprof-logs-aid.c index 466eab3e..8807cbe5 100644 --- a/src/libsysprof-ui/sysprof-logs-aid.c +++ b/src/libsysprof-ui/sysprof-logs-aid.c @@ -80,7 +80,7 @@ sysprof_logs_aid_new (void) return g_object_new (SYSPROF_TYPE_LOGS_AID, NULL); } -static gboolean +static bool find_marks_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-marks-aid.c b/src/libsysprof-ui/sysprof-marks-aid.c index a8f79b48..66b2c258 100644 --- a/src/libsysprof-ui/sysprof-marks-aid.c +++ b/src/libsysprof-ui/sysprof-marks-aid.c @@ -84,7 +84,7 @@ sysprof_marks_aid_new (void) return g_object_new (SYSPROF_TYPE_MARKS_AID, NULL); } -static gboolean +static bool find_marks_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-marks-model.c b/src/libsysprof-ui/sysprof-marks-model.c index fa5772af..08000641 100644 --- a/src/libsysprof-ui/sysprof-marks-model.c +++ b/src/libsysprof-ui/sysprof-marks-model.c @@ -301,7 +301,7 @@ sysprof_marks_model_init (SysprofMarksModel *self) self->items = g_array_new (FALSE, FALSE, sizeof (Item)); } -static gboolean +static bool cursor_foreach_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-memprof-aid.c b/src/libsysprof-ui/sysprof-memprof-aid.c index 6299b54f..21325177 100644 --- a/src/libsysprof-ui/sysprof-memprof-aid.c +++ b/src/libsysprof-ui/sysprof-memprof-aid.c @@ -87,7 +87,7 @@ sysprof_memprof_aid_prepare (SysprofAid *self, #endif } -static gboolean +static bool discover_samples_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-netdev-aid.c b/src/libsysprof-ui/sysprof-netdev-aid.c index f4a75a7a..c6970fd2 100644 --- a/src/libsysprof-ui/sysprof-netdev-aid.c +++ b/src/libsysprof-ui/sysprof-netdev-aid.c @@ -79,7 +79,7 @@ sysprof_netdev_aid_prepare (SysprofAid *self, sysprof_profiler_add_source (profiler, source); } -static gboolean +static bool collect_netdev_counters (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-procs-visualizer.c b/src/libsysprof-ui/sysprof-procs-visualizer.c index b4d34d29..c82007e5 100644 --- a/src/libsysprof-ui/sysprof-procs-visualizer.c +++ b/src/libsysprof-ui/sysprof-procs-visualizer.c @@ -65,7 +65,7 @@ discovery_ref (Discovery *d) return d; } -static gboolean +static bool discover_max_cb (const SysprofCaptureFrame *frame, gpointer user_data) { @@ -85,7 +85,7 @@ discover_max_cb (const SysprofCaptureFrame *frame, return TRUE; } -static gboolean +static bool calc_points_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-rapl-aid.c b/src/libsysprof-ui/sysprof-rapl-aid.c index 9da61d56..c5d11e61 100644 --- a/src/libsysprof-ui/sysprof-rapl-aid.c +++ b/src/libsysprof-ui/sysprof-rapl-aid.c @@ -69,7 +69,7 @@ sysprof_rapl_aid_new (void) return g_object_new (SYSPROF_TYPE_RAPL_AID, NULL); } -static gboolean +static bool collect_info (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-time-visualizer.c b/src/libsysprof-ui/sysprof-time-visualizer.c index cb1d01a7..01d32f23 100644 --- a/src/libsysprof-ui/sysprof-time-visualizer.c +++ b/src/libsysprof-ui/sysprof-time-visualizer.c @@ -382,7 +382,7 @@ calc_x (gint64 lower, return (gdouble)(value - lower) / (gdouble)(upper - lower); } -static gboolean +static bool sysprof_time_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame, gpointer user_data) { diff --git a/src/libsysprof-ui/sysprof-visualizers-frame.c b/src/libsysprof-ui/sysprof-visualizers-frame.c index 95b990ca..96da31b9 100644 --- a/src/libsysprof-ui/sysprof-visualizers-frame.c +++ b/src/libsysprof-ui/sysprof-visualizers-frame.c @@ -608,7 +608,7 @@ compare_gint64 (const gint64 *a, return 0; } -static gboolean +static bool index_frame_times_frame_cb (const SysprofCaptureFrame *frame, gpointer user_data) { 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 6611a0dc..cc5f96ff 100644 --- a/src/libsysprof/meson.build +++ b/src/libsysprof/meson.build @@ -37,6 +37,7 @@ libsysprof_public_sources = [ libsysprof_public_headers = [ 'sysprof-battery-source.h', 'sysprof-callgraph-profile.h', + 'sysprof-capture-autocleanups.h', 'sysprof-capture-gobject.h', 'sysprof-capture-symbol-resolver.h', 'sysprof-control-source.h', @@ -71,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/preload/meson.build b/src/libsysprof/preload/meson.build index dd237a3a..a1a6e603 100644 --- a/src/libsysprof/preload/meson.build +++ b/src/libsysprof/preload/meson.build @@ -1,6 +1,7 @@ libdl_dep = cc.find_library('dl', required: false) preload_deps = [ + dependency('glib-2.0'), libsysprof_capture_dep, libdl_dep, ] @@ -14,7 +15,7 @@ libsysprof_memory_preload = shared_library('sysprof-memory-@0@'.format(libsyspro ['sysprof-memory-collector.c'], dependencies: preload_deps, install: true, - install_dir: get_option('libexecdir'), + install_dir: get_option('libdir'), ) libsysprof_speedtrack_preload = shared_library('sysprof-speedtrack-@0@'.format(libsysprof_api_version), diff --git a/src/libsysprof/preload/sysprof-memory-collector.c b/src/libsysprof/preload/sysprof-memory-collector.c index 30591c88..72cf0515 100644 --- a/src/libsysprof/preload/sysprof-memory-collector.c +++ b/src/libsysprof/preload/sysprof-memory-collector.c @@ -23,6 +23,7 @@ #include "config.h" #include +#include #include #include #include @@ -119,8 +120,6 @@ scratch_calloc (size_t nmemb, static void scratch_free (void *ptr) { - if ((char *)ptr >= scratch.buf && (char *)ptr < scratch.buf + scratch.off) - return; } static void @@ -198,8 +197,12 @@ realloc (void *ptr, void free (void *ptr) { - real_free (ptr); - track_free (ptr); + if G_LIKELY (ptr < (void *)scratch.buf || + ptr >= (void *)&scratch.buf[sizeof scratch.buf]) + { + real_free (ptr); + track_free (ptr); + } } void * diff --git a/src/libsysprof/preload/sysprof-speedtrack-collector.c b/src/libsysprof/preload/sysprof-speedtrack-collector.c index 6b2b08c0..223dea91 100644 --- a/src/libsysprof/preload/sysprof-speedtrack-collector.c +++ b/src/libsysprof/preload/sysprof-speedtrack-collector.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/src/libsysprof/sysprof-capture-autocleanups.h b/src/libsysprof/sysprof-capture-autocleanups.h new file mode 100644 index 00000000..d640b7ee --- /dev/null +++ b/src/libsysprof/sysprof-capture-autocleanups.h @@ -0,0 +1,41 @@ +/* sysprof-capture-gobject.h + * + * Copyright 2020 Endless Mobile, Inc. + * + * Author: + * - Philip Withnall + * + * 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-capture.h" + +G_BEGIN_DECLS + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureCondition, sysprof_capture_condition_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureCursor, sysprof_capture_cursor_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureReader, sysprof_capture_reader_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref) + +G_END_DECLS diff --git a/src/libsysprof/sysprof-capture-gobject.c b/src/libsysprof/sysprof-capture-gobject.c index dbd7cf2a..4e6f660d 100644 --- a/src/libsysprof/sysprof-capture-gobject.c +++ b/src/libsysprof/sysprof-capture-gobject.c @@ -20,10 +20,73 @@ #include "config.h" -#include "sysprof-capture-gobject.h" - +#include #include +#include "sysprof-capture-gobject.h" + G_DEFINE_BOXED_TYPE (SysprofCaptureReader, sysprof_capture_reader, (GBoxedCopyFunc)sysprof_capture_reader_ref, (GBoxedFreeFunc)sysprof_capture_reader_unref) G_DEFINE_BOXED_TYPE (SysprofCaptureWriter, sysprof_capture_writer, (GBoxedCopyFunc)sysprof_capture_writer_ref, (GBoxedFreeFunc)sysprof_capture_writer_unref) G_DEFINE_BOXED_TYPE (SysprofCaptureCursor, sysprof_capture_cursor, (GBoxedCopyFunc)sysprof_capture_cursor_ref, (GBoxedFreeFunc)sysprof_capture_cursor_unref) + +SysprofCaptureReader * +sysprof_capture_reader_new_with_error (const char *filename, + GError **error) +{ + SysprofCaptureReader *ret; + + if (!(ret = sysprof_capture_reader_new (filename))) + g_set_error_literal (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + g_strerror (errno)); + + return ret; +} + +SysprofCaptureReader * +sysprof_capture_reader_new_from_fd_with_error (int fd, + GError **error) +{ + SysprofCaptureReader *ret; + + if (!(ret = sysprof_capture_reader_new_from_fd (fd))) + g_set_error_literal (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + g_strerror (errno)); + + return ret; +} + +SysprofCaptureReader * +sysprof_capture_writer_create_reader_with_error (SysprofCaptureWriter *self, + GError **error) +{ + SysprofCaptureReader *ret; + + if (!(ret = sysprof_capture_writer_create_reader (self))) + g_set_error_literal (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + g_strerror (errno)); + + return ret; +} + +bool +sysprof_capture_reader_save_as_with_error (SysprofCaptureReader *self, + const char *filename, + GError **error) +{ + if (!sysprof_capture_reader_save_as (self, filename)) + { + g_set_error_literal (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + g_strerror (errno)); + return false; + } + + return true; +} diff --git a/src/libsysprof/sysprof-capture-gobject.h b/src/libsysprof/sysprof-capture-gobject.h index 80a2f4c2..ca6fbe23 100644 --- a/src/libsysprof/sysprof-capture-gobject.h +++ b/src/libsysprof/sysprof-capture-gobject.h @@ -41,4 +41,18 @@ GType sysprof_capture_writer_get_type (void); SYSPROF_AVAILABLE_IN_ALL GType sysprof_capture_cursor_get_type (void); +SYSPROF_AVAILABLE_IN_3_38 +SysprofCaptureReader *sysprof_capture_reader_new_with_error (const char *filename, + GError **error); +SYSPROF_AVAILABLE_IN_3_38 +SysprofCaptureReader *sysprof_capture_reader_new_from_fd_with_error (int fd, + GError **error); +SYSPROF_AVAILABLE_IN_3_38 +SysprofCaptureReader *sysprof_capture_writer_create_reader_with_error (SysprofCaptureWriter *self, + GError **error); +SYSPROF_AVAILABLE_IN_3_38 +bool sysprof_capture_reader_save_as_with_error (SysprofCaptureReader *self, + const char *filename, + GError **error); + G_END_DECLS diff --git a/src/libsysprof/sysprof-control-source.c b/src/libsysprof/sysprof-control-source.c index 4ccdc482..e39ebde8 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" @@ -122,10 +123,10 @@ sysprof_control_source_init (SysprofControlSource *self) g_array_set_clear_func (self->source_ids, remove_source_id); } -static gboolean -event_frame_cb (gconstpointer data, - gsize *length, - gpointer user_data) +static bool +event_frame_cb (const void *data, + size_t *length, + void *user_data) { const SysprofCaptureFrame *fr = data; RingData *rd = user_data; diff --git a/src/libsysprof/sysprof-jitmap-symbol-resolver.c b/src/libsysprof/sysprof-jitmap-symbol-resolver.c index ef63e8fe..2015eb50 100644 --- a/src/libsysprof/sysprof-jitmap-symbol-resolver.c +++ b/src/libsysprof/sysprof-jitmap-symbol-resolver.c @@ -74,8 +74,8 @@ sysprof_jitmap_symbol_resolver_load (SysprofSymbolResolver *resolver, while (sysprof_capture_reader_peek_type (reader, &type)) { - g_autoptr(GHashTable) jitmap = NULL; - GHashTableIter iter; + const SysprofCaptureJitmap *jitmap; + SysprofCaptureJitmapIter iter; SysprofCaptureAddress addr; const gchar *str; @@ -89,8 +89,8 @@ sysprof_jitmap_symbol_resolver_load (SysprofSymbolResolver *resolver, if (!(jitmap = sysprof_capture_reader_read_jitmap (reader))) return; - g_hash_table_iter_init (&iter, jitmap); - while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str)) + sysprof_capture_jitmap_iter_init (&iter, jitmap); + while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str)) g_hash_table_insert (self->jitmap, GSIZE_TO_POINTER (addr), g_strdup (str)); } } diff --git a/src/libsysprof/sysprof-kernel-symbol.h b/src/libsysprof/sysprof-kernel-symbol.h index 7ef72f01..27c4790a 100644 --- a/src/libsysprof/sysprof-kernel-symbol.h +++ b/src/libsysprof/sysprof-kernel-symbol.h @@ -24,6 +24,8 @@ # error "Only can be included directly." #endif +#include + #include "sysprof-capture-types.h" G_BEGIN_DECLS diff --git a/src/libsysprof/sysprof-local-profiler.c b/src/libsysprof/sysprof-local-profiler.c index 37f7e9e5..9aecaa7b 100644 --- a/src/libsysprof/sysprof-local-profiler.c +++ b/src/libsysprof/sysprof-local-profiler.c @@ -34,6 +34,7 @@ #include "sysprof-local-profiler.h" #include "sysprof-platform.h" +#include "sysprof-capture-autocleanups.h" #include "sysprof-control-source.h" #include "sysprof-gjs-source.h" #include "sysprof-hostinfo-source.h" @@ -197,7 +198,8 @@ sysprof_local_profiler_finish_stopping (SysprofLocalProfiler *self) g_assert (priv->is_stopping == TRUE); g_assert (priv->stopping->len == 0); - reader = sysprof_capture_writer_create_reader (priv->writer, 0); + reader = sysprof_capture_writer_create_reader (priv->writer); + g_assert (reader != NULL); for (guint i = 0; i < priv->sources->len; i++) { @@ -982,9 +984,9 @@ profiler_iface_init (SysprofProfilerInterface *iface) iface->stopped = sysprof_local_profiler_real_stopped; } -static gboolean +static bool find_profiler_meta_cb (const SysprofCaptureFrame *frame, - gpointer user_data) + void *user_data) { const SysprofCaptureMetadata *meta = (const SysprofCaptureMetadata *)frame; GKeyFile **keyfile = user_data; @@ -1005,7 +1007,7 @@ find_profiler_meta_cb (const SysprofCaptureFrame *frame, return *keyfile == NULL; } - return TRUE; + return true; } SysprofProfiler * diff --git a/src/libsysprof/sysprof-map-lookaside.c b/src/libsysprof/sysprof-map-lookaside.c index b1532e2b..277e7f66 100644 --- a/src/libsysprof/sysprof-map-lookaside.c +++ b/src/libsysprof/sysprof-map-lookaside.c @@ -20,6 +20,8 @@ #include "config.h" +#include + #include "sysprof-map-lookaside.h" struct _SysprofMapLookaside diff --git a/src/libsysprof/sysprof-map-lookaside.h b/src/libsysprof/sysprof-map-lookaside.h index e517a600..ef068562 100644 --- a/src/libsysprof/sysprof-map-lookaside.h +++ b/src/libsysprof/sysprof-map-lookaside.h @@ -20,6 +20,8 @@ #pragma once +#include + #include "sysprof-capture-types.h" G_BEGIN_DECLS diff --git a/src/libsysprof/sysprof-memprof-profile.c b/src/libsysprof/sysprof-memprof-profile.c index a8f5c487..30984106 100644 --- a/src/libsysprof/sysprof-memprof-profile.c +++ b/src/libsysprof/sysprof-memprof-profile.c @@ -24,6 +24,7 @@ #include +#include "sysprof-capture-autocleanups.h" #include "sysprof-capture-symbol-resolver.h" #include "sysprof-elf-symbol-resolver.h" #include "sysprof-kernel-symbol-resolver.h" @@ -250,9 +251,9 @@ create_cursor (SysprofCaptureReader *reader) return cursor; } -static gboolean +static bool all_allocs_foreach_cb (const SysprofCaptureFrame *frame, - gpointer user_data) + void *user_data) { Generate *g = user_data; @@ -272,12 +273,12 @@ all_allocs_foreach_cb (const SysprofCaptureFrame *frame, (gchar *)g_string_chunk_insert_const (g->symbols, cmdline)); } - return TRUE; + return true; } /* Short-circuit if we don't care about this frame */ if (!sysprof_selection_contains (g->selection, frame->time)) - return TRUE; + return true; if (frame->type == SYSPROF_CAPTURE_FRAME_ALLOCATION) { @@ -360,7 +361,7 @@ all_allocs_foreach_cb (const SysprofCaptureFrame *frame, } } - return TRUE; + return true; } static gint diff --git a/src/libsysprof/sysprof-proxy-source.c b/src/libsysprof/sysprof-proxy-source.c index 967ae232..61e6d59b 100644 --- a/src/libsysprof/sysprof-proxy-source.c +++ b/src/libsysprof/sysprof-proxy-source.c @@ -450,12 +450,11 @@ sysprof_proxy_source_cat (SysprofProxySource *self, g_assert (SYSPROF_IS_PROXY_SOURCE (self)); g_assert (reader != NULL); - if (self->writer != NULL) + if (self->writer != NULL && + !sysprof_capture_writer_cat (self->writer, reader)) { - g_autoptr(GError) error = NULL; - - if (!sysprof_capture_writer_cat (self->writer, reader, &error)) - g_warning ("Failed to join reader: %s\n", error->message); + int errsv = errno; + g_warning ("Failed to join reader: %s", g_strerror (errsv)); } } @@ -464,14 +463,16 @@ sysprof_proxy_source_complete_monitor (SysprofProxySource *self, Monitor *monitor) { g_autoptr(SysprofCaptureReader) reader = NULL; - g_autoptr(GError) error = NULL; g_assert (SYSPROF_IS_PROXY_SOURCE (self)); g_assert (monitor != NULL); g_assert (monitor->self == self); - if (!(reader = sysprof_capture_reader_new_from_fd (steal_fd (&monitor->fd), &error))) - g_warning ("Failed to load reader from peer FD: %s", error->message); + if (!(reader = sysprof_capture_reader_new_from_fd (steal_fd (&monitor->fd)))) + { + int errsv = errno; + g_warning ("Failed to load reader from peer FD: %s", g_strerror (errsv)); + } else sysprof_proxy_source_cat (self, reader); } diff --git a/src/libsysprof/sysprof-source.h b/src/libsysprof/sysprof-source.h index 62e2f53c..412aa765 100644 --- a/src/libsysprof/sysprof-source.h +++ b/src/libsysprof/sysprof-source.h @@ -24,6 +24,7 @@ # error "Only can be included directly." #endif +#include #include #include diff --git a/src/libsysprof/sysprof-tracefd-source.c b/src/libsysprof/sysprof-tracefd-source.c index af5e90e2..72c9fb05 100644 --- a/src/libsysprof/sysprof-tracefd-source.c +++ b/src/libsysprof/sysprof-tracefd-source.c @@ -25,6 +25,7 @@ #include #include +#include "sysprof-capture-autocleanups.h" #include "sysprof-platform.h" #include "sysprof-tracefd-source.h" @@ -258,8 +259,9 @@ sysprof_tracefd_source_stop (SysprofSource *source) { g_autoptr(SysprofCaptureReader) reader = NULL; - if ((reader = sysprof_capture_reader_new_from_fd (priv->tracefd, 0))) - sysprof_capture_writer_cat (priv->writer, reader, NULL); + /* FIXME: Error handling is ignored here */ + if ((reader = sysprof_capture_reader_new_from_fd (priv->tracefd))) + sysprof_capture_writer_cat (priv->writer, reader); priv->tracefd = -1; } diff --git a/src/libsysprof/sysprof.h b/src/libsysprof/sysprof.h index c682f2f9..5abe64b6 100644 --- a/src/libsysprof/sysprof.h +++ b/src/libsysprof/sysprof.h @@ -18,6 +18,7 @@ #pragma once +#include #include G_BEGIN_DECLS @@ -26,6 +27,7 @@ G_BEGIN_DECLS # include "sysprof-battery-source.h" # include "sysprof-callgraph-profile.h" +# include "sysprof-capture-autocleanups.h" # include "sysprof-capture-gobject.h" # include "sysprof-capture-symbol-resolver.h" # include "sysprof-control-source.h" diff --git a/src/tests/allocs-by-size.c b/src/tests/allocs-by-size.c index 6260d4b4..4f80414b 100644 --- a/src/tests/allocs-by-size.c +++ b/src/tests/allocs-by-size.c @@ -134,9 +134,10 @@ main (gint argc, bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - if (!(reader = sysprof_capture_reader_new (filename, &error))) + if (!(reader = sysprof_capture_reader_new (filename))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return EXIT_FAILURE; } diff --git a/src/tests/allocs-within-mark.c b/src/tests/allocs-within-mark.c index 10d12287..9e2bfaab 100644 --- a/src/tests/allocs-within-mark.c +++ b/src/tests/allocs-within-mark.c @@ -205,9 +205,10 @@ main (gint argc, bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - if (!(reader = sysprof_capture_reader_new (filename, &error))) + if (!(reader = sysprof_capture_reader_new (filename))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return EXIT_FAILURE; } diff --git a/src/tests/cross-thread-frees.c b/src/tests/cross-thread-frees.c index cd973b79..6279e214 100644 --- a/src/tests/cross-thread-frees.c +++ b/src/tests/cross-thread-frees.c @@ -20,6 +20,7 @@ #include "config.h" +#include #include #include #include @@ -115,7 +116,6 @@ main (gint argc, { SysprofCaptureReader *reader; const gchar *filename = argv[1]; - g_autoptr(GError) error = NULL; if (argc < 2) { @@ -123,9 +123,10 @@ main (gint argc, return EXIT_FAILURE; } - if (!(reader = sysprof_capture_reader_new (filename, &error))) + if (!(reader = sysprof_capture_reader_new (filename))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return EXIT_FAILURE; } diff --git a/src/tests/find-temp-allocs.c b/src/tests/find-temp-allocs.c index 4a8e300d..f4d35331 100644 --- a/src/tests/find-temp-allocs.c +++ b/src/tests/find-temp-allocs.c @@ -20,6 +20,7 @@ #include "config.h" +#include #include static struct { @@ -140,7 +141,6 @@ main (gint argc, { SysprofCaptureReader *reader; const gchar *filename = argv[1]; - g_autoptr(GError) error = NULL; if (argc < 2) { @@ -148,9 +148,10 @@ main (gint argc, return EXIT_FAILURE; } - if (!(reader = sysprof_capture_reader_new (filename, &error))) + if (!(reader = sysprof_capture_reader_new (filename))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return EXIT_FAILURE; } diff --git a/src/tests/memory-stack-stash.c b/src/tests/memory-stack-stash.c index 7b6675c6..7562c677 100644 --- a/src/tests/memory-stack-stash.c +++ b/src/tests/memory-stack-stash.c @@ -77,9 +77,10 @@ main (gint argc, bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); - if (!(reader = sysprof_capture_reader_new (filename, &error))) + if (!(reader = sysprof_capture_reader_new (filename))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return EXIT_FAILURE; } diff --git a/src/tests/meson.build b/src/tests/meson.build index f2825f60..1a450aef 100644 --- a/src/tests/meson.build +++ b/src/tests/meson.build @@ -12,24 +12,29 @@ test_cflags = [ '-DSYSPROF_COMPILATION=1', ] +test_capture_deps = [ + dependency('glib-2.0'), + libsysprof_capture_dep, +] + test_capture = executable('test-capture', 'test-capture.c', c_args: test_cflags, - dependencies: [libsysprof_capture_dep], + dependencies: test_capture_deps, ) test_capture_cursor = executable('test-capture-cursor', 'test-capture-cursor.c', c_args: test_cflags, - dependencies: [libsysprof_capture_dep], + dependencies: test_capture_deps, ) test_mapped_ring_buffer = executable('test-mapped-ring-buffer', 'test-mapped-ring-buffer.c', c_args: test_cflags, - dependencies: [libsysprof_capture_dep], + dependencies: test_capture_deps, ) find_temp_allocs = executable('find-temp-allocs', 'find-temp-allocs.c', c_args: test_cflags, - dependencies: [libsysprof_capture_dep], + dependencies: test_capture_deps, ) test('test-capture', test_capture, env: test_env) diff --git a/src/tests/show-page-usage.c b/src/tests/show-page-usage.c index 536f7bce..9eb22ec5 100644 --- a/src/tests/show-page-usage.c +++ b/src/tests/show-page-usage.c @@ -21,6 +21,7 @@ #include "config.h" #include +#include #include #include #include @@ -167,7 +168,6 @@ main (gint argc, SysprofCaptureReader *reader; const gchar *filename = argv[1]; g_autoptr(SysprofProfile) memprof = NULL; - g_autoptr(GError) error = NULL; if (argc < 2) { @@ -177,9 +177,10 @@ main (gint argc, main_loop = g_main_loop_new (NULL, FALSE); - if (!(reader = sysprof_capture_reader_new (filename, &error))) + if (!(reader = sysprof_capture_reader_new (filename))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return EXIT_FAILURE; } diff --git a/src/tests/test-addr-decode.c b/src/tests/test-addr-decode.c index 66ca209b..dae7769e 100644 --- a/src/tests/test-addr-decode.c +++ b/src/tests/test-addr-decode.c @@ -1,4 +1,5 @@ #include +#include #include #include "sysprof-platform.h" @@ -10,7 +11,6 @@ main (gint argc, { g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(SysprofSymbolResolver) resolver = NULL; - g_autoptr(GError) error = NULL; SysprofCaptureFrameType type; if (argc != 2) @@ -19,9 +19,10 @@ main (gint argc, return 1; } - if (!(reader = sysprof_capture_reader_new (argv[1], &error))) + if (!(reader = sysprof_capture_reader_new (argv[1]))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return 1; } diff --git a/src/tests/test-addr-map.c b/src/tests/test-addr-map.c index 47a2d829..918ba7ae 100644 --- a/src/tests/test-addr-map.c +++ b/src/tests/test-addr-map.c @@ -1,4 +1,5 @@ #include +#include #include #include "sysprof-platform.h" @@ -91,9 +92,10 @@ main (gint argc, return 1; } - if (!(reader = sysprof_capture_reader_new (argv[1], &error))) + if (!(reader = sysprof_capture_reader_new (argv[1]))) { - g_printerr ("%s\n", error->message); + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); return 1; } diff --git a/src/tests/test-capture-cursor.c b/src/tests/test-capture-cursor.c index 0781fc07..9dc2e6c6 100644 --- a/src/tests/test-capture-cursor.c +++ b/src/tests/test-capture-cursor.c @@ -18,16 +18,17 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +#include #include #include -static gboolean +static bool increment (const SysprofCaptureFrame *frame, - gpointer user_data) + void *user_data) { gint *count= user_data; (*count)++; - return TRUE; + return true; } static void @@ -36,20 +37,18 @@ test_cursor_basic (void) SysprofCaptureReader *reader; SysprofCaptureWriter *writer; SysprofCaptureCursor *cursor; - GError *error = NULL; gint64 t = SYSPROF_CAPTURE_CURRENT_TIME; guint i; gint r; gint count = 0; writer = sysprof_capture_writer_new ("capture-cursor-file", 0); - g_assert (writer != NULL); + g_assert_nonnull (writer); sysprof_capture_writer_flush (writer); - reader = sysprof_capture_reader_new ("capture-cursor-file", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("capture-cursor-file"); + g_assert_nonnull (reader); for (i = 0; i < 100; i++) { diff --git a/src/tests/test-capture-view.c b/src/tests/test-capture-view.c index 1dca19aa..9768ca18 100644 --- a/src/tests/test-capture-view.c +++ b/src/tests/test-capture-view.c @@ -37,7 +37,7 @@ main (gint argc, return 1; } - if (!(reader = sysprof_capture_reader_new (argv[1], &error))) + if (!(reader = sysprof_capture_reader_new_with_error (argv[1], &error))) { g_printerr ("Failed to load reader: %s\n", error->message); return 1; diff --git a/src/tests/test-capture.c b/src/tests/test-capture.c index 64d6f2cc..bfa56950 100644 --- a/src/tests/test-capture.c +++ b/src/tests/test-capture.c @@ -21,6 +21,7 @@ #include "config.h" #include +#include #include #include #include @@ -31,15 +32,16 @@ #include "sysprof-capture-util-private.h" static void -copy_into (GHashTable *src, - GHashTable *dst) +copy_into (const SysprofCaptureJitmap *src, + GHashTable *dst) { - GHashTableIter iter; - gpointer k, v; + SysprofCaptureJitmapIter iter; + SysprofCaptureAddress addr; + const char *name; - g_hash_table_iter_init (&iter, src); - while (g_hash_table_iter_next (&iter, &k, &v)) - g_hash_table_insert (dst, k, g_strdup ((gchar *)v)); + sysprof_capture_jitmap_iter_init (&iter, src); + while (sysprof_capture_jitmap_iter_next (&iter, &addr, &name)) + g_hash_table_insert (dst, GSIZE_TO_POINTER (addr), g_strdup (name)); } static void @@ -59,9 +61,8 @@ test_reader_basic (void) sysprof_capture_writer_flush (writer); - reader = sysprof_capture_reader_new ("capture-file", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("capture-file"); + g_assert_nonnull (reader); for (i = 0; i < 100; i++) { @@ -317,19 +318,19 @@ test_reader_basic (void) for (;;) { SysprofCaptureFrameType type = -1; - g_autoptr(GHashTable) ret = NULL; + const SysprofCaptureJitmap *jitmap; if (sysprof_capture_reader_peek_type (reader, &type)) g_assert_cmpint (type, ==, SYSPROF_CAPTURE_FRAME_JITMAP); else break; - ret = sysprof_capture_reader_read_jitmap (reader); - g_assert (ret != NULL); + jitmap = sysprof_capture_reader_read_jitmap (reader); + g_assert_nonnull (jitmap); - i += g_hash_table_size (ret); + i += jitmap->n_jitmaps; - copy_into (ret, jmap); + copy_into (jitmap, jmap); } g_assert_cmpint (1000, ==, i); @@ -398,9 +399,8 @@ test_reader_basic (void) g_assert_not_reached (); } - r = sysprof_capture_writer_save_as (writer, "capture-file.bak", &error); - g_assert_no_error (error); - g_assert (r); + r = sysprof_capture_writer_save_as (writer, "capture-file.bak"); + g_assert_true (r); g_assert (g_file_test ("capture-file.bak", G_FILE_TEST_IS_REGULAR)); /* make sure contents are equal */ @@ -428,9 +428,8 @@ test_reader_basic (void) g_clear_pointer (&writer, sysprof_capture_writer_unref); g_clear_pointer (&reader, sysprof_capture_reader_unref); - reader = sysprof_capture_reader_new ("capture-file.bak", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("capture-file.bak"); + g_assert_nonnull (reader); for (i = 0; i < 2; i++) { @@ -462,7 +461,6 @@ test_writer_splice (void) SysprofCaptureWriter *writer2; SysprofCaptureReader *reader; SysprofCaptureFrameType type; - GError *error = NULL; guint i; gint r; @@ -472,16 +470,14 @@ test_writer_splice (void) for (i = 0; i < 1000; i++) sysprof_capture_writer_add_timestamp (writer1, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1); - r = sysprof_capture_writer_splice (writer1, writer2, &error); - g_assert_no_error (error); - g_assert (r == TRUE); + r = sysprof_capture_writer_splice (writer1, writer2); + g_assert_true (r); g_clear_pointer (&writer1, sysprof_capture_writer_unref); g_clear_pointer (&writer2, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("writer2.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("writer2.syscap"); + g_assert_nonnull (reader); for (i = 0; i < 1000; i++) { @@ -509,7 +505,6 @@ test_reader_splice (void) SysprofCaptureWriter *writer2; SysprofCaptureReader *reader; SysprofCaptureFrameType type; - GError *error = NULL; guint i; guint count; gint r; @@ -525,9 +520,8 @@ test_reader_splice (void) g_clear_pointer (&writer1, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("writer1.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("writer1.syscap"); + g_assert_nonnull (reader); /* advance to the end of the reader to non-start boundary for fd */ @@ -544,14 +538,14 @@ test_reader_splice (void) r = sysprof_capture_reader_peek_type (reader, &type); g_assert_cmpint (r, ==, FALSE); - r = sysprof_capture_reader_splice (reader, writer2, &error); - g_assert_no_error (error); - g_assert_cmpint (r, ==, TRUE); + r = sysprof_capture_reader_splice (reader, writer2); + g_assert_true (r); g_clear_pointer (&reader, sysprof_capture_reader_unref); g_clear_pointer (&writer2, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("writer2.syscap", 0); + reader = sysprof_capture_reader_new ("writer2.syscap"); + g_assert_nonnull (reader); for (i = 0; i < 1000; i++) { @@ -568,19 +562,16 @@ test_reader_splice (void) g_clear_pointer (&reader, sysprof_capture_reader_unref); - reader = sysprof_capture_reader_new ("writer2.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("writer2.syscap"); + g_assert_nonnull (reader); - r = sysprof_capture_reader_save_as (reader, "writer3.syscap", &error); - g_assert_no_error (error); - g_assert_cmpint (r, ==, TRUE); + r = sysprof_capture_reader_save_as (reader, "writer3.syscap"); + g_assert_true (r); g_clear_pointer (&reader, sysprof_capture_reader_unref); - reader = sysprof_capture_reader_new ("writer3.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("writer3.syscap"); + g_assert_nonnull (reader); count = 0; while (sysprof_capture_reader_skip (reader)) @@ -601,7 +592,6 @@ test_reader_writer_log (void) SysprofCaptureReader *reader; const SysprofCaptureLog *log; SysprofCaptureFrameType type; - GError *error = NULL; gint r; writer = sysprof_capture_writer_new ("log1.syscap", 0); @@ -612,9 +602,8 @@ test_reader_writer_log (void) g_clear_pointer (&writer, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("log1.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("log1.syscap"); + g_assert_nonnull (reader); log = sysprof_capture_reader_read_log (reader); g_assert_nonnull (log); @@ -655,7 +644,6 @@ test_reader_writer_mark (void) SysprofCaptureReader *reader; const SysprofCaptureMark *mark; SysprofCaptureFrameType type; - GError *error = NULL; gint r; writer = sysprof_capture_writer_new ("mark1.syscap", 0); @@ -665,9 +653,8 @@ test_reader_writer_mark (void) g_clear_pointer (&writer, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("mark1.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("mark1.syscap"); + g_assert_nonnull (reader); mark = sysprof_capture_reader_read_mark (reader); g_assert_nonnull (mark); @@ -702,7 +689,6 @@ test_reader_writer_metadata (void) SysprofCaptureReader *reader; const SysprofCaptureMetadata *metadata; SysprofCaptureFrameType type; - GError *error = NULL; gint r; writer = sysprof_capture_writer_new ("metadata1.syscap", 0); @@ -715,9 +701,8 @@ test_reader_writer_metadata (void) g_clear_pointer (&writer, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("metadata1.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("metadata1.syscap"); + g_assert_nonnull (reader); metadata = sysprof_capture_reader_read_metadata (reader); g_assert_nonnull (metadata); @@ -746,11 +731,10 @@ test_reader_writer_file (void) { g_autofree gchar *data = NULL; GByteArray *buf = g_byte_array_new (); - g_auto(GStrv) files = NULL; + g_autofree const gchar **files = NULL; SysprofCaptureWriter *writer; SysprofCaptureReader *reader; SysprofCaptureFrameType type; - GError *error = NULL; gsize data_len; guint count = 0; gint fd; @@ -773,9 +757,8 @@ test_reader_writer_file (void) g_clear_pointer (&writer, sysprof_capture_writer_unref); - reader = sysprof_capture_reader_new ("file1.syscap", &error); - g_assert_no_error (error); - g_assert (reader != NULL); + reader = sysprof_capture_reader_new ("file1.syscap"); + g_assert_nonnull (reader); while (count < 2) { @@ -829,7 +812,6 @@ test_reader_writer_cat_jitmap (void) SysprofCaptureWriter *res; SysprofCaptureReader *reader; const SysprofCaptureSample *sample; - GError *error = NULL; SysprofCaptureAddress addrs[20]; gboolean r; @@ -865,28 +847,23 @@ test_reader_writer_cat_jitmap (void) addrs, G_N_ELEMENTS (addrs)); - reader = sysprof_capture_writer_create_reader (writer1, &error); - g_assert_no_error (error); + reader = sysprof_capture_writer_create_reader (writer1); g_assert_nonnull (reader); - r = sysprof_capture_writer_cat (res, reader, &error); - g_assert_no_error (error); + r = sysprof_capture_writer_cat (res, reader); g_assert_true (r); sysprof_capture_writer_unref (writer1); sysprof_capture_reader_unref (reader); - reader = sysprof_capture_writer_create_reader (writer2, &error); - g_assert_no_error (error); + reader = sysprof_capture_writer_create_reader (writer2); g_assert_nonnull (reader); - r = sysprof_capture_writer_cat (res, reader, &error); - g_assert_no_error (error); + r = sysprof_capture_writer_cat (res, reader); g_assert_true (r); sysprof_capture_writer_unref (writer2); sysprof_capture_reader_unref (reader); - reader = sysprof_capture_writer_create_reader (res, &error); - g_assert_no_error (error); + reader = sysprof_capture_writer_create_reader (res); g_assert_nonnull (reader); - g_hash_table_unref (sysprof_capture_reader_read_jitmap (reader)); + sysprof_capture_reader_read_jitmap (reader); sample = sysprof_capture_reader_read_sample (reader); g_assert_cmpint (sample->frame.pid, ==, getpid ()); g_assert_cmpint (sample->n_addrs, ==, G_N_ELEMENTS (addrs)); @@ -905,7 +882,6 @@ test_writer_memory_alloc_free (void) { SysprofCaptureWriter *writer; SysprofCaptureReader *reader; - GError *error = NULL; SysprofCaptureAddress addrs[20] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, @@ -930,8 +906,7 @@ test_writer_memory_alloc_free (void) sysprof_capture_writer_flush (writer); - reader = sysprof_capture_writer_create_reader (writer, &error); - g_assert_no_error (error); + reader = sysprof_capture_writer_create_reader (writer); g_assert_nonnull (reader); for (guint i = 0; i < 20; i++) diff --git a/src/tests/test-mapped-ring-buffer.c b/src/tests/test-mapped-ring-buffer.c index 5c6c0144..707c0dcb 100644 --- a/src/tests/test-mapped-ring-buffer.c +++ b/src/tests/test-mapped-ring-buffer.c @@ -1,13 +1,14 @@ #include "mapped-ring-buffer.h" +#include #include static gsize real_count; -static gboolean -drain_nth_cb (gconstpointer data, - gsize *len, - gpointer user_data) +static bool +drain_nth_cb (const void *data, + size_t *len, + void *user_data) { const gint64 *v64 = data; g_assert_cmpint (*len, >=, 8); @@ -16,10 +17,10 @@ drain_nth_cb (gconstpointer data, return G_SOURCE_CONTINUE; } -static gboolean -drain_count_cb (gconstpointer data, - gsize *len, - gpointer user_data) +static bool +drain_count_cb (const void *data, + size_t *len, + void *user_data) { const gint64 *v64 = data; g_assert_cmpint (*len, >=, 8); @@ -92,10 +93,10 @@ typedef struct gint64 done; } ThreadedMessage; -static gboolean -handle_msg (gconstpointer data, - gsize *length, - gpointer user_data) +static bool +handle_msg (const void *data, + size_t *length, + void *user_data) { const ThreadedMessage *msg = data; gboolean *done = user_data; diff --git a/src/tests/test-resolvers.c b/src/tests/test-resolvers.c index 9021c6de..7cb85154 100644 --- a/src/tests/test-resolvers.c +++ b/src/tests/test-resolvers.c @@ -1,3 +1,4 @@ +#include #include static const SysprofCaptureSample * @@ -42,8 +43,12 @@ main (gint argc, g_ptr_array_add (resolvers, sysprof_jitmap_symbol_resolver_new ()); g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ()); - if (!(reader = sysprof_capture_reader_new (filename, &error))) - g_error ("%s", error->message); + if (!(reader = sysprof_capture_reader_new (filename))) + { + int errsv = errno; + g_error ("%s", g_strerror (errsv)); + return 1; + } for (guint r = 0; r < resolvers->len; r++) { diff --git a/src/tools/list-threads.c b/src/tools/list-threads.c index 42bfc1db..2a60540c 100644 --- a/src/tools/list-threads.c +++ b/src/tools/list-threads.c @@ -24,9 +24,11 @@ #include #include -static gboolean +#include "../libsysprof/sysprof-capture-autocleanups.h" + +static bool foreach_cb (const SysprofCaptureFrame *frame, - gpointer user_data) + void *user_data) { const SysprofCaptureSample *sample = (SysprofCaptureSample *)frame; GHashTable *seen = user_data; @@ -36,7 +38,7 @@ foreach_cb (const SysprofCaptureFrame *frame, GINT_TO_POINTER (sample->tid), GINT_TO_POINTER (frame->pid)); - return TRUE; + return true; } gint @@ -57,9 +59,9 @@ main (gint argc, } if (g_strcmp0 ("-", argv[1]) == 0) - reader = sysprof_capture_reader_new_from_fd (dup (STDIN_FILENO), 0); + reader = sysprof_capture_reader_new_from_fd (dup (STDIN_FILENO)); else - reader = sysprof_capture_reader_new (argv[1], 0); + reader = sysprof_capture_reader_new (argv[1]); if (reader == NULL) { diff --git a/src/tools/meson.build b/src/tools/meson.build index 670052a7..7cd69279 100644 --- a/src/tools/meson.build +++ b/src/tools/meson.build @@ -1,11 +1,15 @@ tools_deps = [ + dependency('glib-2.0'), libsysprof_capture_dep, ] +tools_cflags = [ '-DSYSPROF_COMPILATION '] + if get_option('libsysprof') and host_machine.system() == 'linux' polkit_agent_dep = dependency('polkit-agent-1') sysprof_cli = executable('sysprof-cli', 'sysprof-cli.c', dependencies: tools_deps + [libsysprof_dep, polkit_dep, polkit_agent_dep], + c_args: tools_cflags, install_dir: get_option('bindir'), install: true, ) @@ -13,21 +17,25 @@ endif sysprof_cat = executable('sysprof-cat', 'sysprof-cat.c', dependencies: tools_deps, + c_args: tools_cflags, install: false, ) sysprof_dump = executable('sysprof-dump', 'sysprof-dump.c', dependencies: tools_deps, + c_args: tools_cflags, install: false, ) sysprof_profiler_ctl = executable('sysprof-profiler-ctl', [ 'sysprof-profiler-ctl.c', ipc_profiler_src ], dependencies: [ tools_deps, gio_unix_dep ], + c_args: tools_cflags, install: false, ) list_threads = executable('list-threads', ['list-threads.c'], dependencies: [ tools_deps ], + c_args: tools_cflags, install: false, ) diff --git a/src/tools/sysprof-cat.c b/src/tools/sysprof-cat.c index b4187bf0..d023d82d 100644 --- a/src/tools/sysprof-cat.c +++ b/src/tools/sysprof-cat.c @@ -23,11 +23,13 @@ #include "config.h" #include +#include #include #include #include #include +#include "../libsysprof/sysprof-capture-autocleanups.h" #include "sysprof-capture-util-private.h" gint @@ -71,17 +73,19 @@ main (gint argc, g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(GError) error = NULL; - if (!(reader = sysprof_capture_reader_new (argv[i], &error))) + if (!(reader = sysprof_capture_reader_new (argv[i]))) { + int errsv = errno; g_printerr ("Failed to create reader for \"%s\": %s\n", - argv[i], error->message); + argv[i], g_strerror (errsv)); return EXIT_FAILURE; } - if (!sysprof_capture_writer_cat (writer, reader, &error)) + if (!sysprof_capture_writer_cat (writer, reader)) { + int errsv = errno; g_printerr ("Failed to join \"%s\": %s\n", - argv[i], error->message); + argv[i], g_strerror (errsv)); return EXIT_FAILURE; } } diff --git a/src/tools/sysprof-cli.c b/src/tools/sysprof-cli.c index 32f3c428..d4ead58a 100644 --- a/src/tools/sysprof-cli.c +++ b/src/tools/sysprof-cli.c @@ -134,19 +134,20 @@ merge_files (gint argc, for (guint i = 1; i < argc; i++) { g_autoptr(SysprofCaptureReader) reader = NULL; - g_autoptr(GError) error = NULL; - if (!(reader = sysprof_capture_reader_new (argv[i], &error))) + if (!(reader = sysprof_capture_reader_new (argv[i]))) { + int errsv = errno; g_printerr ("Failed to create reader for \"%s\": %s\n", - argv[i], error->message); + argv[i], g_strerror (errsv)); return EXIT_FAILURE; } - if (!sysprof_capture_writer_cat (writer, reader, &error)) + if (!sysprof_capture_writer_cat (writer, reader)) { + int errsv = errno; g_printerr ("Failed to join \"%s\": %s\n", - argv[i], error->message); + argv[i], g_strerror (errsv)); return EXIT_FAILURE; } } diff --git a/src/tools/sysprof-dump.c b/src/tools/sysprof-dump.c index 5491f3a9..cb85880d 100644 --- a/src/tools/sysprof-dump.c +++ b/src/tools/sysprof-dump.c @@ -20,6 +20,7 @@ #include "config.h" +#include #include #include #include @@ -55,13 +56,18 @@ main (gint argc, return EXIT_FAILURE; } - reader = sysprof_capture_reader_new (argv[1], &error); + if ((reader = sysprof_capture_reader_new (argv[1])) == NULL) + { + int errsv = errno; + g_printerr ("%s\n", g_strerror (errsv)); + return EXIT_FAILURE; + } if (list_files) { - g_auto(GStrv) files = sysprof_capture_reader_list_files (reader); + g_autofree const gchar **files = sysprof_capture_reader_list_files (reader); - for (guint i = 0; files[i]; i++) + for (gsize i = 0; files[i]; i++) g_print ("%s\n", files[i]); return EXIT_SUCCESS; @@ -74,12 +80,6 @@ main (gint argc, #define SET_CTR_TYPE(i,t) g_hash_table_insert(ctrtypes, GINT_TO_POINTER(i), GINT_TO_POINTER(t)) #define GET_CTR_TYPE(i) GPOINTER_TO_INT(g_hash_table_lookup(ctrtypes, GINT_TO_POINTER(i))) - if (reader == NULL) - { - g_printerr ("%s\n", error->message); - return EXIT_FAILURE; - } - begin_time = sysprof_capture_reader_get_start_time (reader); end_time = sysprof_capture_reader_get_end_time (reader); @@ -116,18 +116,18 @@ main (gint argc, case SYSPROF_CAPTURE_FRAME_JITMAP: { - g_autoptr(GHashTable) ret = sysprof_capture_reader_read_jitmap (reader); - GHashTableIter iter; + const SysprofCaptureJitmap *jitmap = sysprof_capture_reader_read_jitmap (reader); + SysprofCaptureJitmapIter iter; SysprofCaptureAddress addr; const gchar *str; - if (ret == NULL) + if (jitmap == NULL) return EXIT_FAILURE; g_print ("JITMAP:\n"); - g_hash_table_iter_init (&iter, ret); - while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str)) + sysprof_capture_jitmap_iter_init (&iter, jitmap); + while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str)) g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " : %s\n", addr, str); break;