Merge branch 'drop-glib' into 'master'

Drop GLib from libsysprof-capture

Closes #40

See merge request GNOME/sysprof!30
This commit is contained in:
Christian Hergert
2020-07-04 18:29:12 +00:00
89 changed files with 2894 additions and 1955 deletions

View File

@ -11,6 +11,7 @@
# include <sched.h> # include <sched.h>
#endif #endif
#include <glib.h>
#include <signal.h> #include <signal.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
#include <unistd.h> #include <unistd.h>

View File

@ -1,3 +1,3 @@
app = executable('example-app', 'app.c', app = executable('example-app', 'app.c',
dependencies: [libsysprof_capture_dep], dependencies: [dependency('glib-2.0'), libsysprof_capture_dep],
) )

View File

@ -12,7 +12,7 @@ gnome = import('gnome')
pkgconfig = import('pkgconfig') pkgconfig = import('pkgconfig')
i18n = import('i18n') i18n = import('i18n')
libsysprof_api_version = 3 libsysprof_api_version = 4
version_split = meson.project_version().split('.') version_split = meson.project_version().split('.')
datadir = get_option('datadir') datadir = get_option('datadir')
datadir_for_pc_file = join_paths('${prefix}', 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) config_h.set10('HAVE_EXECINFO_H', true)
endif endif
config_h.set('HAVE_STRLCPY', cc.has_function('strlcpy'))
if get_option('libunwind') if get_option('libunwind')
libunwind_dep = dependency('libunwind-generic', required: false) libunwind_dep = dependency('libunwind-generic', required: false)
if libunwind_dep.found() if libunwind_dep.found()

View File

@ -18,21 +18,23 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#define G_LOG_DOMAIN "mapped-ring-buffer"
#include "config.h" #include "config.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "sysprof-capture-util-private.h" #include "sysprof-capture-util-private.h"
#include "sysprof-macros-internal.h"
#include "sysprof-platform.h" #include "sysprof-platform.h"
#include "mapped-ring-buffer.h" #include "mapped-ring-buffer.h"
#define DEFAULT_N_PAGES 32 #define DEFAULT_N_PAGES 32
#define BUFFER_MAX_SIZE ((G_MAXUINT32/2)-_sysprof_getpagesize()) #define BUFFER_MAX_SIZE ((UINT32_MAX/2)-_sysprof_getpagesize())
enum { enum {
MODE_READER = 1, MODE_READER = 1,
@ -47,13 +49,13 @@ enum {
*/ */
typedef struct _MappedRingHeader typedef struct _MappedRingHeader
{ {
guint32 head; uint32_t head;
guint32 tail; uint32_t tail;
guint32 offset; uint32_t offset;
guint32 size; uint32_t size;
} MappedRingHeader; } 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 * MappedRingBuffer is used to wrap both the reader and writer
@ -61,12 +63,12 @@ G_STATIC_ASSERT (sizeof (MappedRingHeader) == 16);
*/ */
struct _MappedRingBuffer struct _MappedRingBuffer
{ {
volatile gint ref_count; volatile int ref_count;
int mode; int mode;
int fd; int fd;
void *map; void *map;
gsize body_size; size_t body_size;
gsize page_size; size_t page_size;
}; };
static inline MappedRingHeader * static inline MappedRingHeader *
@ -75,19 +77,19 @@ get_header (MappedRingBuffer *self)
return (MappedRingHeader *)self->map; return (MappedRingHeader *)self->map;
} }
static inline gpointer static inline void *
get_body_at_pos (MappedRingBuffer *self, 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 static void *
map_head_and_body_twice (int fd, map_head_and_body_twice (int fd,
gsize head_size, size_t head_size,
gsize body_size) size_t body_size)
{ {
void *map; void *map;
void *second; 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 * By mmap()'ing over the old region, the previous region is automatically
* munmap()'d for us. * munmap()'d for us.
*/ */
second = mmap ((guint8 *)map + head_size + body_size, second = mmap ((uint8_t *)map + head_size + body_size,
body_size, body_size,
PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED, MAP_SHARED | MAP_FIXED,
@ -131,7 +133,7 @@ map_head_and_body_twice (int fd,
return NULL; return NULL;
} }
g_assert (second == (gpointer)((guint8 *)map + head_size + body_size)); assert (second == (void *)((uint8_t *)map + head_size + body_size));
return map; return map;
} }
@ -157,16 +159,16 @@ map_head_and_body_twice (int fd,
* Returns: (transfer full): a #MappedRingBuffer * Returns: (transfer full): a #MappedRingBuffer
*/ */
MappedRingBuffer * MappedRingBuffer *
mapped_ring_buffer_new_reader (gsize buffer_size) mapped_ring_buffer_new_reader (size_t buffer_size)
{ {
MappedRingBuffer *self; MappedRingBuffer *self;
MappedRingHeader *header; MappedRingHeader *header;
gsize page_size; size_t page_size;
void *map; void *map;
int fd; int fd;
g_return_val_if_fail ((buffer_size % _sysprof_getpagesize ()) == 0, NULL); assert ((buffer_size % _sysprof_getpagesize ()) == 0);
g_return_val_if_fail (buffer_size < BUFFER_MAX_SIZE, NULL); assert (buffer_size < BUFFER_MAX_SIZE);
page_size = _sysprof_getpagesize (); page_size = _sysprof_getpagesize ();
@ -200,7 +202,10 @@ mapped_ring_buffer_new_reader (gsize buffer_size)
header->offset = page_size; header->offset = page_size;
header->size = buffer_size - 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->ref_count = 1;
self->mode = MODE_READER; self->mode = MODE_READER;
self->body_size = buffer_size - page_size; self->body_size = buffer_size - page_size;
@ -208,11 +213,11 @@ mapped_ring_buffer_new_reader (gsize buffer_size)
self->map = map; self->map = map;
self->page_size = page_size; self->page_size = page_size;
return g_steal_pointer (&self); return sysprof_steal_pointer (&self);
} }
MappedRingBuffer * MappedRingBuffer *
mapped_ring_buffer_new_readwrite (gsize buffer_size) mapped_ring_buffer_new_readwrite (size_t buffer_size)
{ {
MappedRingBuffer *self; MappedRingBuffer *self;
@ -234,50 +239,50 @@ mapped_ring_buffer_new_readwrite (gsize buffer_size)
* Returns: (transfer full) (nullable): a new #MappedRingBuffer * Returns: (transfer full) (nullable): a new #MappedRingBuffer
*/ */
MappedRingBuffer * MappedRingBuffer *
mapped_ring_buffer_new_writer (gint fd) mapped_ring_buffer_new_writer (int fd)
{ {
MappedRingBuffer *self; MappedRingBuffer *self;
MappedRingHeader *header; MappedRingHeader *header;
gssize buffer_size; ssize_t buffer_size;
gsize page_size; size_t page_size;
void *map; void *map;
g_return_val_if_fail (fd > -1, NULL); assert (fd > -1);
page_size = _sysprof_getpagesize (); page_size = _sysprof_getpagesize ();
/* Make our own copy of the FD */ /* Make our own copy of the FD */
if ((fd = dup (fd)) < 0) 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; return NULL;
} }
/* Seek to end to get buffer size */ /* Seek to end to get buffer size */
if ((buffer_size = lseek (fd, 0, SEEK_END)) < 0) 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; return NULL;
} }
/* Ensure non-zero sized buffer */ /* Ensure non-zero sized buffer */
if (buffer_size < (page_size + page_size)) 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; return NULL;
} }
/* Make sure it is less than our max size */ /* Make sure it is less than our max size */
if ((buffer_size - page_size) > BUFFER_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; return NULL;
} }
/* Ensure we have page-aligned buffer */ /* Ensure we have page-aligned buffer */
if ((buffer_size % page_size) != 0) 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; return NULL;
} }
@ -298,7 +303,14 @@ mapped_ring_buffer_new_writer (gint fd)
return NULL; 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->ref_count = 1;
self->mode = MODE_WRITER; self->mode = MODE_WRITER;
self->fd = fd; self->fd = fd;
@ -306,7 +318,7 @@ mapped_ring_buffer_new_writer (gint fd)
self->map = map; self->map = map;
self->page_size = page_size; self->page_size = page_size;
return g_steal_pointer (&self); return sysprof_steal_pointer (&self);
} }
static void static void
@ -328,28 +340,28 @@ mapped_ring_buffer_finalize (MappedRingBuffer *self)
void void
mapped_ring_buffer_unref (MappedRingBuffer *self) mapped_ring_buffer_unref (MappedRingBuffer *self)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (self->ref_count > 0); 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); mapped_ring_buffer_finalize (self);
} }
MappedRingBuffer * MappedRingBuffer *
mapped_ring_buffer_ref (MappedRingBuffer *self) mapped_ring_buffer_ref (MappedRingBuffer *self)
{ {
g_return_val_if_fail (self != NULL, NULL); assert (self != NULL);
g_return_val_if_fail (self->ref_count > 0, 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; return self;
} }
gint int
mapped_ring_buffer_get_fd (MappedRingBuffer *self) mapped_ring_buffer_get_fd (MappedRingBuffer *self)
{ {
g_return_val_if_fail (self != NULL, -1); assert (self != NULL);
return self->fd; 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 * Returns: (nullable): a pointer to data of at least @length bytes
* or %NULL if there is not enough space. * or %NULL if there is not enough space.
*/ */
gpointer void *
mapped_ring_buffer_allocate (MappedRingBuffer *self, mapped_ring_buffer_allocate (MappedRingBuffer *self,
gsize length) size_t length)
{ {
MappedRingHeader *header; MappedRingHeader *header;
gsize headpos; uint32_t headpos;
gsize tailpos; uint32_t tailpos;
g_return_val_if_fail (self != NULL, NULL); assert (self != NULL);
g_return_val_if_fail (self->mode & MODE_WRITER, NULL); assert (self->mode & MODE_WRITER);
g_return_val_if_fail (length > 0, NULL); assert (length > 0);
g_return_val_if_fail (length < self->body_size, NULL); assert (length < self->body_size);
g_return_val_if_fail ((length & 0x7) == 0, NULL); assert ((length & 0x7) == 0);
header = get_header (self); header = get_header (self);
headpos = g_atomic_int_get (&header->head); __atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST);
tailpos = g_atomic_int_get (&header->tail); __atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST);
/* We need to check that there is enough space for @length at the /* We need to check that there is enough space for @length at the
* current position in the write buffer. We cannot fully catch up * current position in the write buffer. We cannot fully catch up
@ -436,16 +448,16 @@ mapped_ring_buffer_allocate (MappedRingBuffer *self,
*/ */
void void
mapped_ring_buffer_advance (MappedRingBuffer *self, mapped_ring_buffer_advance (MappedRingBuffer *self,
gsize length) size_t length)
{ {
MappedRingHeader *header; MappedRingHeader *header;
guint32 tail; uint32_t tail;
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (self->mode & MODE_WRITER); assert (self->mode & MODE_WRITER);
g_return_if_fail (length > 0); assert (length > 0);
g_return_if_fail (length < self->body_size); assert (length < self->body_size);
g_return_if_fail ((length & 0x7) == 0); assert ((length & 0x7) == 0);
header = get_header (self); header = get_header (self);
tail = header->tail; 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 * we just update the position as the only way the head could have
* moved is forward. * 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 * Returns: %TRUE if the buffer was drained, %FALSE if @callback prematurely
* returned while draining. * returned while draining.
*/ */
gboolean bool
mapped_ring_buffer_drain (MappedRingBuffer *self, mapped_ring_buffer_drain (MappedRingBuffer *self,
MappedRingBufferCallback callback, MappedRingBufferCallback callback,
gpointer user_data) void *user_data)
{ {
MappedRingHeader *header; MappedRingHeader *header;
gsize headpos; uint32_t headpos;
gsize tailpos; uint32_t tailpos;
g_return_val_if_fail (self != NULL, FALSE); assert (self != NULL);
g_return_val_if_fail (self->mode & MODE_READER, FALSE); assert (self->mode & MODE_READER);
g_return_val_if_fail (callback != NULL, FALSE); assert (callback != NULL);
header = get_header (self); header = get_header (self);
headpos = g_atomic_int_get (&header->head); __atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST);
tailpos = g_atomic_int_get (&header->tail); __atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST);
g_assert (headpos < self->body_size); assert (headpos < self->body_size);
g_assert (tailpos < self->body_size); assert (tailpos < self->body_size);
if (headpos == tailpos) if (headpos == tailpos)
return TRUE; return true;
/* If head needs to wrap around to get to tail, we can just rely on /* If head needs to wrap around to get to tail, we can just rely on
* our double mapping instead actually manually wrapping/copying data. * our double mapping instead actually manually wrapping/copying data.
@ -506,131 +518,56 @@ mapped_ring_buffer_drain (MappedRingBuffer *self,
if (tailpos < headpos) if (tailpos < headpos)
tailpos += self->body_size; tailpos += self->body_size;
g_assert (headpos < tailpos); assert (headpos < tailpos);
while (headpos < tailpos) while (headpos < tailpos)
{ {
gconstpointer data = get_body_at_pos (self, headpos); const void *data = get_body_at_pos (self, headpos);
gsize len = tailpos - headpos; size_t len = tailpos - headpos;
uint32_t new_headpos;
if (!callback (data, &len, user_data)) if (!callback (data, &len, user_data))
return FALSE; return false;
if (len > (tailpos - headpos)) if (len > (tailpos - headpos))
return FALSE; return false;
headpos += len; headpos += len;
if (headpos >= self->body_size) if (headpos >= self->body_size)
g_atomic_int_set (&header->head, headpos - self->body_size); new_headpos = headpos - self->body_size;
else 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; MappedRingHeader *header;
uint32_t headpos, tailpos;
g_assert (real_source != NULL); header = get_header (self);
g_assert (real_source->self != NULL);
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 headpos == tailpos;
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);
} }
/** /**
@ -648,7 +585,7 @@ mapped_ring_buffer_clear (MappedRingBuffer *self)
{ {
MappedRingHeader *header; MappedRingHeader *header;
g_return_if_fail (self != NULL); assert (self != NULL);
header = get_header (self); header = get_header (self);
header->head = 0; header->head = 0;

View File

@ -20,9 +20,12 @@
#pragma once #pragma once
#include <glib.h> #include <stdbool.h>
#include <stddef.h>
G_BEGIN_DECLS #include "sysprof-macros.h"
SYSPROF_BEGIN_DECLS
typedef struct _MappedRingBuffer MappedRingBuffer; typedef struct _MappedRingBuffer MappedRingBuffer;
@ -49,44 +52,35 @@ typedef struct _MappedRingBuffer MappedRingBuffer;
* *
* Returns: %TRUE to coninue draining, otherwise %FALSE and draining stops * Returns: %TRUE to coninue draining, otherwise %FALSE and draining stops
*/ */
typedef gboolean (*MappedRingBufferCallback) (gconstpointer data, typedef bool (*MappedRingBufferCallback) (const void *data,
gsize *length, size_t *length,
gpointer user_data); void *user_data);
G_GNUC_INTERNAL SYSPROF_INTERNAL
MappedRingBuffer *mapped_ring_buffer_new_reader (gsize buffer_size); MappedRingBuffer *mapped_ring_buffer_new_reader (size_t buffer_size);
G_GNUC_INTERNAL SYSPROF_INTERNAL
MappedRingBuffer *mapped_ring_buffer_new_readwrite (gsize buffer_size); MappedRingBuffer *mapped_ring_buffer_new_readwrite (size_t buffer_size);
G_GNUC_INTERNAL SYSPROF_INTERNAL
MappedRingBuffer *mapped_ring_buffer_new_writer (gint fd); MappedRingBuffer *mapped_ring_buffer_new_writer (int fd);
G_GNUC_INTERNAL SYSPROF_INTERNAL
gint mapped_ring_buffer_get_fd (MappedRingBuffer *self); int mapped_ring_buffer_get_fd (MappedRingBuffer *self);
G_GNUC_INTERNAL SYSPROF_INTERNAL
MappedRingBuffer *mapped_ring_buffer_ref (MappedRingBuffer *self); MappedRingBuffer *mapped_ring_buffer_ref (MappedRingBuffer *self);
G_GNUC_INTERNAL SYSPROF_INTERNAL
void mapped_ring_buffer_unref (MappedRingBuffer *self); void mapped_ring_buffer_unref (MappedRingBuffer *self);
G_GNUC_INTERNAL SYSPROF_INTERNAL
void mapped_ring_buffer_clear (MappedRingBuffer *self); void mapped_ring_buffer_clear (MappedRingBuffer *self);
G_GNUC_INTERNAL SYSPROF_INTERNAL
gpointer mapped_ring_buffer_allocate (MappedRingBuffer *self, void *mapped_ring_buffer_allocate (MappedRingBuffer *self,
gsize length); size_t length);
G_GNUC_INTERNAL SYSPROF_INTERNAL
void mapped_ring_buffer_advance (MappedRingBuffer *self, void mapped_ring_buffer_advance (MappedRingBuffer *self,
gsize length); size_t length);
G_GNUC_INTERNAL SYSPROF_INTERNAL
gboolean mapped_ring_buffer_drain (MappedRingBuffer *self, bool mapped_ring_buffer_drain (MappedRingBuffer *self,
MappedRingBufferCallback callback, MappedRingBufferCallback callback,
gpointer user_data); void *user_data);
G_GNUC_INTERNAL SYSPROF_INTERNAL
guint mapped_ring_buffer_create_source (MappedRingBuffer *self, bool mapped_ring_buffer_is_empty (MappedRingBuffer *self);
MappedRingBufferCallback callback,
gpointer user_data);
G_GNUC_INTERNAL
guint mapped_ring_buffer_create_source_full (MappedRingBuffer *self,
MappedRingBufferCallback callback,
gpointer user_data,
GDestroyNotify destroy);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (MappedRingBuffer, mapped_ring_buffer_unref) SYSPROF_END_DECLS
G_END_DECLS

View File

@ -7,6 +7,7 @@ libsysprof_capture_headers = files([
'sysprof-capture-types.h', 'sysprof-capture-types.h',
'sysprof-capture-writer.h', 'sysprof-capture-writer.h',
'sysprof-collector.h', 'sysprof-collector.h',
'sysprof-macros.h',
'sysprof-platform.h', 'sysprof-platform.h',
'sysprof-capture.h', 'sysprof-capture.h',
'sysprof-version-macros.h', 'sysprof-version-macros.h',
@ -36,9 +37,7 @@ configure_file(
) )
libsysprof_capture_deps = [ libsysprof_capture_deps = [
glib_dep, dependency('threads'),
gio_dep,
gio_unix_dep,
] ]
libsysprof_capture = static_library( libsysprof_capture = static_library(
@ -68,7 +67,6 @@ pkgconfig.generate(
filebase: 'sysprof-capture-@0@'.format(libsysprof_api_version), filebase: 'sysprof-capture-@0@'.format(libsysprof_api_version),
description: 'The static capture library for tools that generate profiling capture data', description: 'The static capture library for tools that generate profiling capture data',
install_dir: join_paths(get_option('libdir'), 'pkgconfig'), install_dir: join_paths(get_option('libdir'), 'pkgconfig'),
requires: [ 'glib-2.0' ],
variables: [ variables: [
'datadir=' + datadir_for_pc_file, 'datadir=' + datadir_for_pc_file,
], ],

View File

@ -61,10 +61,12 @@
#else #else
# include "sysprof-address-fallback.h" # include "sysprof-address-fallback.h"
#endif #endif
#include <stdbool.h>
#include <stddef.h>
#include "sysprof-address.h" #include "sysprof-address.h"
gboolean bool
sysprof_address_is_context_switch (SysprofAddress address, sysprof_address_is_context_switch (SysprofAddress address,
SysprofAddressContext *context) SysprofAddressContext *context)
{ {
@ -77,35 +79,35 @@ sysprof_address_is_context_switch (SysprofAddress address,
{ {
case PERF_CONTEXT_HV: case PERF_CONTEXT_HV:
*context = SYSPROF_ADDRESS_CONTEXT_HYPERVISOR; *context = SYSPROF_ADDRESS_CONTEXT_HYPERVISOR;
return TRUE; return true;
case PERF_CONTEXT_KERNEL: case PERF_CONTEXT_KERNEL:
*context = SYSPROF_ADDRESS_CONTEXT_KERNEL; *context = SYSPROF_ADDRESS_CONTEXT_KERNEL;
return TRUE; return true;
case PERF_CONTEXT_USER: case PERF_CONTEXT_USER:
*context = SYSPROF_ADDRESS_CONTEXT_USER; *context = SYSPROF_ADDRESS_CONTEXT_USER;
return TRUE; return true;
case PERF_CONTEXT_GUEST: case PERF_CONTEXT_GUEST:
*context = SYSPROF_ADDRESS_CONTEXT_GUEST; *context = SYSPROF_ADDRESS_CONTEXT_GUEST;
return TRUE; return true;
case PERF_CONTEXT_GUEST_KERNEL: case PERF_CONTEXT_GUEST_KERNEL:
*context = SYSPROF_ADDRESS_CONTEXT_GUEST_KERNEL; *context = SYSPROF_ADDRESS_CONTEXT_GUEST_KERNEL;
return TRUE; return true;
case PERF_CONTEXT_GUEST_USER: case PERF_CONTEXT_GUEST_USER:
*context = SYSPROF_ADDRESS_CONTEXT_GUEST_USER; *context = SYSPROF_ADDRESS_CONTEXT_GUEST_USER;
return TRUE; return true;
default: default:
*context = SYSPROF_ADDRESS_CONTEXT_NONE; *context = SYSPROF_ADDRESS_CONTEXT_NONE;
return FALSE; return false;
} }
} }
const gchar * const char *
sysprof_address_context_to_string (SysprofAddressContext context) sysprof_address_context_to_string (SysprofAddressContext context)
{ {
switch (context) switch (context)

View File

@ -56,13 +56,19 @@
#pragma once #pragma once
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "sysprof-macros.h"
#include "sysprof-version-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 typedef enum
{ {
@ -76,12 +82,12 @@ typedef enum
} SysprofAddressContext; } SysprofAddressContext;
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_address_is_context_switch (SysprofAddress address, bool sysprof_address_is_context_switch (SysprofAddress address,
SysprofAddressContext *context); SysprofAddressContext *context);
SYSPROF_AVAILABLE_IN_ALL 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, sysprof_address_compare (SysprofAddress a,
SysprofAddress b) SysprofAddress b)
{ {
@ -93,4 +99,4 @@ sysprof_address_compare (SysprofAddress a,
return 1; return 1;
} }
G_END_DECLS SYSPROF_END_DECLS

View File

@ -54,13 +54,16 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-capture-condition"
#include "config.h" #include "config.h"
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "sysprof-capture-condition.h" #include "sysprof-capture-condition.h"
#include "sysprof-capture-util-private.h"
#include "sysprof-macros-internal.h"
/** /**
* SECTION:sysprof-capture-condition * SECTION:sysprof-capture-condition
@ -86,30 +89,39 @@ typedef enum
struct _SysprofCaptureCondition struct _SysprofCaptureCondition
{ {
volatile gint ref_count; volatile int ref_count;
SysprofCaptureConditionType type; SysprofCaptureConditionType type;
union { union {
GArray *where_type_in;
struct { struct {
gint64 begin; SysprofCaptureFrameType *data;
gint64 end; size_t len;
} where_type_in;
struct {
int64_t begin;
int64_t end;
} where_time_between; } where_time_between;
GArray *where_pid_in; struct {
GArray *where_counter_in; int32_t *data;
size_t len;
} where_pid_in;
struct {
unsigned int *data;
size_t len;
} where_counter_in;
struct { struct {
SysprofCaptureCondition *left; SysprofCaptureCondition *left;
SysprofCaptureCondition *right; SysprofCaptureCondition *right;
} and, or; } and, or;
gchar *where_file; char *where_file;
} u; } u;
}; };
gboolean bool
sysprof_capture_condition_match (const SysprofCaptureCondition *self, sysprof_capture_condition_match (const SysprofCaptureCondition *self,
const SysprofCaptureFrame *frame) const SysprofCaptureFrame *frame)
{ {
g_assert (self != NULL); assert (self != NULL);
g_assert (frame != NULL); assert (frame != NULL);
switch (self->type) switch (self->type)
{ {
@ -122,34 +134,34 @@ sysprof_capture_condition_match (const SysprofCaptureCondition *self,
sysprof_capture_condition_match (self->u.or.right, frame); sysprof_capture_condition_match (self->u.or.right, frame);
case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN: 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)) if (frame->type == self->u.where_type_in.data[i])
return TRUE; return true;
} }
return FALSE; return false;
case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN: case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN:
return (frame->time >= self->u.where_time_between.begin && frame->time <= self->u.where_time_between.end); return (frame->time >= self->u.where_time_between.begin && frame->time <= self->u.where_time_between.end);
case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN: 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)) if (frame->pid == self->u.where_pid_in.data[i])
return TRUE; return true;
} }
return FALSE; return false;
case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN: case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN:
if (frame->type == SYSPROF_CAPTURE_FRAME_CTRSET) if (frame->type == SYSPROF_CAPTURE_FRAME_CTRSET)
{ {
const SysprofCaptureCounterSet *set = (SysprofCaptureCounterSet *)frame; 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] || if (counter == set->values[j].ids[0] ||
counter == set->values[j].ids[1] || 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[5] ||
counter == set->values[j].ids[6] || counter == set->values[j].ids[6] ||
counter == set->values[j].ids[7]) 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; 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) if (def->counters[j].id == counter)
return TRUE; return true;
} }
} }
} }
return FALSE; return false;
case SYSPROF_CAPTURE_CONDITION_WHERE_FILE: case SYSPROF_CAPTURE_CONDITION_WHERE_FILE:
if (frame->type != SYSPROF_CAPTURE_FRAME_FILE_CHUNK) 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: default:
break; break;
} }
g_assert_not_reached (); sysprof_assert_not_reached ();
return FALSE; return false;
} }
static SysprofCaptureCondition * static SysprofCaptureCondition *
@ -201,12 +216,16 @@ sysprof_capture_condition_init (void)
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
self = g_slice_new0 (SysprofCaptureCondition); self = sysprof_malloc0 (sizeof (SysprofCaptureCondition));
if (self == NULL)
return NULL;
self->ref_count = 1; self->ref_count = 1;
return g_steal_pointer (&self); return sysprof_steal_pointer (&self);
} }
/* Returns NULL on allocation failure. */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_copy (const SysprofCaptureCondition *self) 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: case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN:
return sysprof_capture_condition_new_where_type_in ( return sysprof_capture_condition_new_where_type_in (
self->u.where_type_in->len, self->u.where_type_in.len,
(const SysprofCaptureFrameType *)(gpointer)self->u.where_type_in->data); self->u.where_type_in.data);
case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN: case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN:
return sysprof_capture_condition_new_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: case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN:
return sysprof_capture_condition_new_where_pid_in ( return sysprof_capture_condition_new_where_pid_in (
self->u.where_pid_in->len, self->u.where_pid_in.len,
(const gint32 *)(gpointer)self->u.where_pid_in->data); self->u.where_pid_in.data);
case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN: case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN:
return sysprof_capture_condition_new_where_counter_in ( return sysprof_capture_condition_new_where_counter_in (
self->u.where_counter_in->len, self->u.where_counter_in.len,
(const guint *)(gpointer)self->u.where_counter_in->data); self->u.where_counter_in.data);
case SYSPROF_CAPTURE_CONDITION_WHERE_FILE: case SYSPROF_CAPTURE_CONDITION_WHERE_FILE:
return sysprof_capture_condition_new_where_file (self->u.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; break;
} }
g_return_val_if_reached (NULL); sysprof_assert_not_reached ();
} }
static void static void
@ -268,83 +287,93 @@ sysprof_capture_condition_finalize (SysprofCaptureCondition *self)
break; break;
case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN: case SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN:
g_array_free (self->u.where_type_in, TRUE); free (self->u.where_type_in.data);
break; break;
case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN: case SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN:
break; break;
case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN: case SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN:
g_array_free (self->u.where_pid_in, TRUE); free (self->u.where_pid_in.data);
break; break;
case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN: case SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN:
g_array_free (self->u.where_counter_in, TRUE); free (self->u.where_counter_in.data);
break; break;
case SYSPROF_CAPTURE_CONDITION_WHERE_FILE: case SYSPROF_CAPTURE_CONDITION_WHERE_FILE:
g_free (self->u.where_file); free (self->u.where_file);
break; break;
default: default:
g_assert_not_reached (); sysprof_assert_not_reached ();
break; break;
} }
g_slice_free (SysprofCaptureCondition, self); free (self);
} }
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_ref (SysprofCaptureCondition *self) sysprof_capture_condition_ref (SysprofCaptureCondition *self)
{ {
g_return_val_if_fail (self != NULL, NULL); assert (self != NULL);
g_return_val_if_fail (self->ref_count > 0, 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; return self;
} }
void void
sysprof_capture_condition_unref (SysprofCaptureCondition *self) sysprof_capture_condition_unref (SysprofCaptureCondition *self)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (self->ref_count > 0); 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); sysprof_capture_condition_finalize (self);
} }
/* Returns NULL on allocation failure. */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_where_type_in (guint n_types, sysprof_capture_condition_new_where_type_in (unsigned int n_types,
const SysprofCaptureFrameType *types) const SysprofCaptureFrameType *types)
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
g_return_val_if_fail (types != NULL, NULL); assert (types != NULL);
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN; self->type = SYSPROF_CAPTURE_CONDITION_WHERE_TYPE_IN;
self->u.where_type_in = g_array_sized_new (FALSE, FALSE, sizeof (SysprofCaptureFrameType), n_types); self->u.where_type_in.data = calloc (n_types, sizeof (SysprofCaptureFrameType));
g_array_set_size (self->u.where_type_in, n_types); if (self->u.where_type_in.data == NULL)
memcpy (self->u.where_type_in->data, types, sizeof (SysprofCaptureFrameType) * n_types); return NULL;
self->u.where_type_in.len = n_types;
memcpy (self->u.where_type_in.data, types, sizeof (SysprofCaptureFrameType) * n_types);
return self; return self;
} }
/* Returns NULL on allocation failure. */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_where_time_between (gint64 begin_time, sysprof_capture_condition_new_where_time_between (int64_t begin_time,
gint64 end_time) int64_t end_time)
{ {
SysprofCaptureCondition *self; 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; begin_time = end_time;
end_time = tmp; end_time = tmp;
} }
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN; self->type = SYSPROF_CAPTURE_CONDITION_WHERE_TIME_BETWEEN;
self->u.where_time_between.begin = begin_time; self->u.where_time_between.begin = begin_time;
self->u.where_time_between.end = end_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; return self;
} }
/* Returns NULL on allocation failure. */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_where_pid_in (guint n_pids, sysprof_capture_condition_new_where_pid_in (unsigned int n_pids,
const gint32 *pids) const int32_t *pids)
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
g_return_val_if_fail (pids != NULL, NULL); assert (pids != NULL);
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN; self->type = SYSPROF_CAPTURE_CONDITION_WHERE_PID_IN;
self->u.where_pid_in = g_array_sized_new (FALSE, FALSE, sizeof (gint32), n_pids); self->u.where_pid_in.data = calloc (n_pids, sizeof (int32_t));
g_array_set_size (self->u.where_pid_in, n_pids); if (self->u.where_pid_in.data == NULL)
memcpy (self->u.where_pid_in->data, pids, sizeof (gint32) * n_pids); {
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; return self;
} }
/* Returns NULL on allocation failure. */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_where_counter_in (guint n_counters, sysprof_capture_condition_new_where_counter_in (unsigned int n_counters,
const guint *counters) const unsigned int *counters)
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
g_return_val_if_fail (counters != NULL || n_counters == 0, NULL); assert (counters != NULL || n_counters == 0);
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_WHERE_COUNTER_IN; 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) if (n_counters > 0)
{ memcpy (self->u.where_counter_in.data, counters, sizeof (unsigned int) * n_counters);
g_array_set_size (self->u.where_counter_in, n_counters);
memcpy (self->u.where_counter_in->data, counters, sizeof (guint) * n_counters);
}
return self; 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 * Creates a new #SysprofCaptureCondition that requires both left and right
* to evaluate to %TRUE. * to evaluate to %TRUE.
* *
* Returns: (transfer full): A new #SysprofCaptureCondition. * Returns: (transfer full) (nullable): A new #SysprofCaptureCondition, or %NULL
* on allocation failure.
*/ */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_and (SysprofCaptureCondition *left, sysprof_capture_condition_new_and (SysprofCaptureCondition *left,
@ -406,10 +452,13 @@ sysprof_capture_condition_new_and (SysprofCaptureCondition *left,
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
g_return_val_if_fail (left != NULL, NULL); assert (left != NULL);
g_return_val_if_fail (right != NULL, NULL); assert (right != NULL);
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_AND; self->type = SYSPROF_CAPTURE_CONDITION_AND;
self->u.and.left = left; self->u.and.left = left;
self->u.and.right = right; 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 * Creates a new #SysprofCaptureCondition that requires either left and right
* to evaluate to %TRUE. * to evaluate to %TRUE.
* *
* Returns: (transfer full): A new #SysprofCaptureCondition. * Returns: (transfer full) (nullable): A new #SysprofCaptureCondition, or %NULL
* on allocation failure.
*/ */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_or (SysprofCaptureCondition *left, sysprof_capture_condition_new_or (SysprofCaptureCondition *left,
@ -433,10 +483,13 @@ sysprof_capture_condition_new_or (SysprofCaptureCondition *left,
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
g_return_val_if_fail (left != NULL, NULL); assert (left != NULL);
g_return_val_if_fail (right != NULL, NULL); assert (right != NULL);
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_OR; self->type = SYSPROF_CAPTURE_CONDITION_OR;
self->u.or.left = left; self->u.or.left = left;
self->u.or.right = right; self->u.or.right = right;
@ -451,18 +504,27 @@ sysprof_capture_condition_new_or (SysprofCaptureCondition *left,
* Creates a new condition that matches #SysprofCaptureFileChunk frames * Creates a new condition that matches #SysprofCaptureFileChunk frames
* which contain the path @path. * which contain the path @path.
* *
* Returns: (transfer full): a new #SysprofCaptureCondition * Returns: (transfer full) (nullable): a new #SysprofCaptureCondition, or %NULL
* on allocation failure.
*/ */
SysprofCaptureCondition * SysprofCaptureCondition *
sysprof_capture_condition_new_where_file (const gchar *path) sysprof_capture_condition_new_where_file (const char *path)
{ {
SysprofCaptureCondition *self; SysprofCaptureCondition *self;
g_return_val_if_fail (path != NULL, NULL); assert (path != NULL);
self = sysprof_capture_condition_init (); self = sysprof_capture_condition_init ();
if (self == NULL)
return NULL;
self->type = SYSPROF_CAPTURE_CONDITION_WHERE_FILE; 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; return self;
} }

View File

@ -56,10 +56,13 @@
#pragma once #pragma once
#include <stdbool.h>
#include "sysprof-capture-types.h" #include "sysprof-capture-types.h"
#include "sysprof-macros.h"
#include "sysprof-version-macros.h" #include "sysprof-version-macros.h"
G_BEGIN_DECLS SYSPROF_BEGIN_DECLS
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureCondition *sysprof_capture_condition_copy (const SysprofCaptureCondition *self); 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 *sysprof_capture_condition_new_or (SysprofCaptureCondition *left,
SysprofCaptureCondition *right); SysprofCaptureCondition *right);
SYSPROF_AVAILABLE_IN_ALL 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); const SysprofCaptureFrameType *types);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureCondition *sysprof_capture_condition_new_where_time_between (gint64 begin_time, SysprofCaptureCondition *sysprof_capture_condition_new_where_time_between (int64_t begin_time,
gint64 end_time); int64_t end_time);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureCondition *sysprof_capture_condition_new_where_pid_in (guint n_pids, SysprofCaptureCondition *sysprof_capture_condition_new_where_pid_in (unsigned int n_pids,
const gint32 *pids); const int32_t *pids);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureCondition *sysprof_capture_condition_new_where_counter_in (guint n_counters, SysprofCaptureCondition *sysprof_capture_condition_new_where_counter_in (unsigned int n_counters,
const guint *counters); const unsigned int *counters);
SYSPROF_AVAILABLE_IN_ALL 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 SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_condition_match (const SysprofCaptureCondition *self, bool sysprof_capture_condition_match (const SysprofCaptureCondition *self,
const SysprofCaptureFrame *frame); const SysprofCaptureFrame *frame);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureCondition, sysprof_capture_condition_unref) SYSPROF_END_DECLS
G_END_DECLS

View File

@ -54,13 +54,16 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-capture-cursor"
#include "config.h" #include "config.h"
#include <assert.h>
#include <stdlib.h>
#include "sysprof-capture-condition.h" #include "sysprof-capture-condition.h"
#include "sysprof-capture-cursor.h" #include "sysprof-capture-cursor.h"
#include "sysprof-capture-reader.h" #include "sysprof-capture-reader.h"
#include "sysprof-capture-util-private.h"
#include "sysprof-macros-internal.h"
#define READ_DELEGATE(f) ((ReadDelegate)(f)) #define READ_DELEGATE(f) ((ReadDelegate)(f))
@ -68,18 +71,21 @@ typedef const SysprofCaptureFrame *(*ReadDelegate) (SysprofCaptureReader *);
struct _SysprofCaptureCursor struct _SysprofCaptureCursor
{ {
volatile gint ref_count; volatile int ref_count;
GPtrArray *conditions; SysprofCaptureCondition **conditions; /* (nullable) (owned) */
size_t n_conditions;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
guint reversed : 1; unsigned int reversed : 1;
}; };
static void static void
sysprof_capture_cursor_finalize (SysprofCaptureCursor *self) sysprof_capture_cursor_finalize (SysprofCaptureCursor *self)
{ {
g_clear_pointer (&self->conditions, g_ptr_array_unref); for (size_t i = 0; i < self->n_conditions; i++)
g_clear_pointer (&self->reader, sysprof_capture_reader_unref); sysprof_capture_condition_unref (self->conditions[i]);
g_slice_free (SysprofCaptureCursor, self); sysprof_clear_pointer (&self->conditions, free);
sysprof_clear_pointer (&self->reader, sysprof_capture_reader_unref);
free (self);
} }
static SysprofCaptureCursor * static SysprofCaptureCursor *
@ -87,11 +93,15 @@ sysprof_capture_cursor_init (void)
{ {
SysprofCaptureCursor *self; SysprofCaptureCursor *self;
self = g_slice_new0 (SysprofCaptureCursor); self = sysprof_malloc0 (sizeof (SysprofCaptureCursor));
self->conditions = g_ptr_array_new_with_free_func ((GDestroyNotify) sysprof_capture_condition_unref); if (self == NULL)
return NULL;
self->conditions = NULL;
self->n_conditions = 0;
self->ref_count = 1; self->ref_count = 1;
return g_steal_pointer (&self); return sysprof_steal_pointer (&self);
} }
/** /**
@ -105,10 +115,10 @@ sysprof_capture_cursor_init (void)
SysprofCaptureCursor * SysprofCaptureCursor *
sysprof_capture_cursor_ref (SysprofCaptureCursor *self) sysprof_capture_cursor_ref (SysprofCaptureCursor *self)
{ {
g_return_val_if_fail (self != NULL, NULL); assert (self != NULL);
g_return_val_if_fail (self->ref_count > 0, 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; return self;
} }
@ -121,10 +131,10 @@ sysprof_capture_cursor_ref (SysprofCaptureCursor *self)
void void
sysprof_capture_cursor_unref (SysprofCaptureCursor *self) sysprof_capture_cursor_unref (SysprofCaptureCursor *self)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (self->ref_count > 0); 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); sysprof_capture_cursor_finalize (self);
} }
@ -138,11 +148,11 @@ sysprof_capture_cursor_unref (SysprofCaptureCursor *self)
void void
sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, sysprof_capture_cursor_foreach (SysprofCaptureCursor *self,
SysprofCaptureCursorCallback callback, SysprofCaptureCursorCallback callback,
gpointer user_data) void *user_data)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (self->reader != NULL); assert (self->reader != NULL);
g_return_if_fail (callback != NULL); assert (callback != NULL);
for (;;) for (;;)
{ {
@ -224,16 +234,16 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self,
if (NULL == (frame = delegate (self->reader))) if (NULL == (frame = delegate (self->reader)))
return; return;
if (self->conditions->len == 0) if (self->n_conditions == 0)
{ {
if (!callback (frame, user_data)) if (!callback (frame, user_data))
return; return;
} }
else 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)) if (sysprof_capture_condition_match (condition, frame))
{ {
@ -249,8 +259,8 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self,
void void
sysprof_capture_cursor_reset (SysprofCaptureCursor *self) sysprof_capture_cursor_reset (SysprofCaptureCursor *self)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (self->reader != NULL); assert (self->reader != NULL);
sysprof_capture_reader_reset (self->reader); sysprof_capture_reader_reset (self->reader);
} }
@ -258,7 +268,7 @@ sysprof_capture_cursor_reset (SysprofCaptureCursor *self)
void void
sysprof_capture_cursor_reverse (SysprofCaptureCursor *self) sysprof_capture_cursor_reverse (SysprofCaptureCursor *self)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
self->reversed = !self->reversed; self->reversed = !self->reversed;
} }
@ -275,10 +285,18 @@ void
sysprof_capture_cursor_add_condition (SysprofCaptureCursor *self, sysprof_capture_cursor_add_condition (SysprofCaptureCursor *self,
SysprofCaptureCondition *condition) SysprofCaptureCondition *condition)
{ {
g_return_if_fail (self != NULL); assert (self != NULL);
g_return_if_fail (condition != 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 its constructed.
*
* FIXME: Theres 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; SysprofCaptureCursor *self;
g_return_val_if_fail (reader != NULL, NULL); assert (reader != NULL);
self = sysprof_capture_cursor_init (); self = sysprof_capture_cursor_init ();
self->reader = sysprof_capture_reader_copy (reader); self->reader = sysprof_capture_reader_copy (reader);
@ -311,7 +329,7 @@ sysprof_capture_cursor_new (SysprofCaptureReader *reader)
SysprofCaptureReader * SysprofCaptureReader *
sysprof_capture_cursor_get_reader (SysprofCaptureCursor *self) sysprof_capture_cursor_get_reader (SysprofCaptureCursor *self)
{ {
g_return_val_if_fail (self != NULL, NULL); assert (self != NULL);
return self->reader; return self->reader;
} }

View File

@ -56,10 +56,13 @@
#pragma once #pragma once
#include <stdbool.h>
#include "sysprof-capture-types.h" #include "sysprof-capture-types.h"
#include "sysprof-macros.h"
#include "sysprof-version-macros.h" #include "sysprof-version-macros.h"
G_BEGIN_DECLS SYSPROF_BEGIN_DECLS
typedef struct _SysprofCaptureCursor SysprofCaptureCursor; typedef struct _SysprofCaptureCursor SysprofCaptureCursor;
@ -74,8 +77,8 @@ typedef struct _SysprofCaptureCursor SysprofCaptureCursor;
* *
* Returns: %TRUE if iteration should continue, otherwise %FALSE. * Returns: %TRUE if iteration should continue, otherwise %FALSE.
*/ */
typedef gboolean (*SysprofCaptureCursorCallback) (const SysprofCaptureFrame *frame, typedef bool (*SysprofCaptureCursorCallback) (const SysprofCaptureFrame *frame,
gpointer user_data); void *user_data);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureCursor *sysprof_capture_cursor_new (SysprofCaptureReader *reader); SysprofCaptureCursor *sysprof_capture_cursor_new (SysprofCaptureReader *reader);
@ -88,7 +91,7 @@ SysprofCaptureReader *sysprof_capture_cursor_get_reader (SysprofCaptureCursor
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, void sysprof_capture_cursor_foreach (SysprofCaptureCursor *self,
SysprofCaptureCursorCallback callback, SysprofCaptureCursorCallback callback,
gpointer user_data); void *user_data);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_cursor_reset (SysprofCaptureCursor *self); void sysprof_capture_cursor_reset (SysprofCaptureCursor *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
@ -97,6 +100,4 @@ SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_cursor_add_condition (SysprofCaptureCursor *self, void sysprof_capture_cursor_add_condition (SysprofCaptureCursor *self,
SysprofCaptureCondition *condition); SysprofCaptureCondition *condition);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureCursor, sysprof_capture_cursor_unref) SYSPROF_END_DECLS
G_END_DECLS

File diff suppressed because it is too large Load Diff

View File

@ -56,19 +56,20 @@
#pragma once #pragma once
#include <stdbool.h>
#include "sysprof-capture-types.h" #include "sysprof-capture-types.h"
#include "sysprof-macros.h"
#include "sysprof-version-macros.h" #include "sysprof-version-macros.h"
G_BEGIN_DECLS SYSPROF_BEGIN_DECLS
typedef struct _SysprofCaptureReader SysprofCaptureReader; typedef struct _SysprofCaptureReader SysprofCaptureReader;
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_reader_new (const gchar *filename, SysprofCaptureReader *sysprof_capture_reader_new (const char *filename);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_reader_new_from_fd (int fd, SysprofCaptureReader *sysprof_capture_reader_new_from_fd (int fd);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_reader_copy (SysprofCaptureReader *self); SysprofCaptureReader *sysprof_capture_reader_copy (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
@ -76,22 +77,22 @@ SysprofCaptureReader *sysprof_capture_reader_ref (
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_reader_unref (SysprofCaptureReader *self); void sysprof_capture_reader_unref (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL 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 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 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 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 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 SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_skip (SysprofCaptureReader *self); bool sysprof_capture_reader_skip (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_peek_type (SysprofCaptureReader *self, bool sysprof_capture_reader_peek_type (SysprofCaptureReader *self,
SysprofCaptureFrameType *type); SysprofCaptureFrameType *type);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_peek_frame (SysprofCaptureReader *self, bool sysprof_capture_reader_peek_frame (SysprofCaptureReader *self,
SysprofCaptureFrame *frame); SysprofCaptureFrame *frame);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureLog *sysprof_capture_reader_read_log (SysprofCaptureReader *self); const SysprofCaptureLog *sysprof_capture_reader_read_log (SysprofCaptureReader *self);
@ -112,7 +113,7 @@ const SysprofCaptureProcess *sysprof_capture_reader_read_process (
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureSample *sysprof_capture_reader_read_sample (SysprofCaptureReader *self); const SysprofCaptureSample *sysprof_capture_reader_read_sample (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL 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 SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureCounterDefine *sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self); const SysprofCaptureCounterDefine *sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
@ -122,31 +123,44 @@ const SysprofCaptureFileChunk *sysprof_capture_reader_read_file (
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
const SysprofCaptureAllocation *sysprof_capture_reader_read_allocation (SysprofCaptureReader *self); const SysprofCaptureAllocation *sysprof_capture_reader_read_allocation (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_reset (SysprofCaptureReader *self); bool sysprof_capture_reader_reset (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_splice (SysprofCaptureReader *self, bool sysprof_capture_reader_splice (SysprofCaptureReader *self,
SysprofCaptureWriter *dest, SysprofCaptureWriter *dest);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_save_as (SysprofCaptureReader *self, bool sysprof_capture_reader_save_as (SysprofCaptureReader *self,
const gchar *filename, const char *filename);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_get_stat (SysprofCaptureReader *self, bool sysprof_capture_reader_get_stat (SysprofCaptureReader *self,
SysprofCaptureStat *st_buf); SysprofCaptureStat *st_buf);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_reader_set_stat (SysprofCaptureReader *self, void sysprof_capture_reader_set_stat (SysprofCaptureReader *self,
const SysprofCaptureStat *st_buf); const SysprofCaptureStat *st_buf);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureFileChunk *sysprof_capture_reader_find_file (SysprofCaptureReader *self, const SysprofCaptureFileChunk *sysprof_capture_reader_find_file (SysprofCaptureReader *self,
const gchar *path); const char *path);
SYSPROF_AVAILABLE_IN_ALL 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 SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self, bool sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self,
const gchar *path, const char *path,
gint fd); 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

View File

@ -56,13 +56,18 @@
#pragma once #pragma once
#include <glib.h> #include <assert.h>
#include <endian.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include "sysprof-clock.h" #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)) #define SYSPROF_CAPTURE_ALIGN (sizeof(SysprofCaptureAddress))
#if defined(_MSC_VER) #if defined(_MSC_VER)
@ -73,14 +78,16 @@ G_BEGIN_DECLS
# define SYSPROF_ALIGNED_END(_N) __attribute__((aligned ((_N)))) # define SYSPROF_ALIGNED_END(_N) __attribute__((aligned ((_N))))
#endif #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 static_assert (sizeof (void *) == sizeof (uintptr_t),
# define SYSPROF_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE000000000000000) "UINTPTR_MAX cant be used to determine sizeof(void*) at compile time");
#elif GLIB_SIZEOF_VOID_P == 4 #if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu
# define SYSPROF_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE0000000) # define SYSPROF_CAPTURE_JITMAP_MARK SYSPROF_UINT64_CONSTANT(0xE000000000000000)
#elif UINTPTR_MAX == 0xFFFFFFFF
# define SYSPROF_CAPTURE_JITMAP_MARK SYSPROF_UINT64_CONSTANT(0xE0000000)
#else #else
#error Unknown GLIB_SIZEOF_VOID_P #error Unknown UINTPTR_MAX
#endif #endif
#define SYSPROF_CAPTURE_CURRENT_TIME (sysprof_clock_get_current_time()) #define SYSPROF_CAPTURE_CURRENT_TIME (sysprof_clock_get_current_time())
@ -92,25 +99,25 @@ typedef struct _SysprofCaptureWriter SysprofCaptureWriter;
typedef struct _SysprofCaptureCursor SysprofCaptureCursor; typedef struct _SysprofCaptureCursor SysprofCaptureCursor;
typedef struct _SysprofCaptureCondition SysprofCaptureCondition; typedef struct _SysprofCaptureCondition SysprofCaptureCondition;
typedef guint64 SysprofCaptureAddress; typedef uint64_t SysprofCaptureAddress;
typedef struct typedef struct
{ {
/* /*
* The number of frames indexed by SysprofCaptureFrameType * The number of frames indexed by SysprofCaptureFrameType
*/ */
gsize frame_count[16]; size_t frame_count[16];
/* /*
* Padding for future expansion. * Padding for future expansion.
*/ */
gsize padding[48]; size_t padding[48];
} SysprofCaptureStat; } SysprofCaptureStat;
typedef union typedef union
{ {
gint64 v64; int64_t v64;
gdouble vdbl; double vdbl;
} SysprofCaptureCounterValue; } SysprofCaptureCounterValue;
typedef enum typedef enum
@ -137,28 +144,28 @@ typedef enum
SYSPROF_ALIGNED_BEGIN(1) SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
guint32 magic; uint32_t magic;
guint32 version : 8; uint32_t version : 8;
guint32 little_endian : 1; uint32_t little_endian : 1;
guint32 padding : 23; uint32_t padding : 23;
gchar capture_time[64]; char capture_time[64];
gint64 time; int64_t time;
gint64 end_time; int64_t end_time;
gchar suffix[168]; char suffix[168];
} SysprofCaptureFileHeader } SysprofCaptureFileHeader
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
SYSPROF_ALIGNED_BEGIN(1) SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
guint16 len; uint16_t len;
gint16 cpu; int16_t cpu;
gint32 pid; int32_t pid;
gint64 time; int64_t time;
guint32 type : 8; uint32_t type : 8;
guint32 padding1 : 24; uint32_t padding1 : 24;
guint32 padding2; uint32_t padding2;
guint8 data[0]; uint8_t data[0];
} SysprofCaptureFrame } SysprofCaptureFrame
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -166,11 +173,11 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint64 start; uint64_t start;
guint64 end; uint64_t end;
guint64 offset; uint64_t offset;
guint64 inode; uint64_t inode;
gchar filename[0]; char filename[0];
} SysprofCaptureMap } SysprofCaptureMap
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -178,8 +185,8 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint32 n_jitmaps; uint32_t n_jitmaps;
guint8 data[0]; uint8_t data[0];
} SysprofCaptureJitmap } SysprofCaptureJitmap
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -187,7 +194,7 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
gchar cmdline[0]; char cmdline[0];
} SysprofCaptureProcess } SysprofCaptureProcess
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -195,9 +202,9 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint32 n_addrs : 16; uint32_t n_addrs : 16;
guint32 padding1 : 16; uint32_t padding1 : 16;
gint32 tid; int32_t tid;
SysprofCaptureAddress addrs[0]; SysprofCaptureAddress addrs[0];
} SysprofCaptureSample } SysprofCaptureSample
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -206,7 +213,7 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
gint32 child_pid; int32_t child_pid;
} SysprofCaptureFork } SysprofCaptureFork
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -227,11 +234,11 @@ SYSPROF_ALIGNED_END(1);
SYSPROF_ALIGNED_BEGIN(1) SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
gchar category[32]; char category[32];
gchar name[32]; char name[32];
gchar description[52]; char description[52];
guint32 id : 24; uint32_t id : 24;
guint32 type : 8; uint32_t type : 8;
SysprofCaptureCounterValue value; SysprofCaptureCounterValue value;
} SysprofCaptureCounter } SysprofCaptureCounter
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -240,9 +247,9 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint32 n_counters : 16; uint32_t n_counters : 16;
guint32 padding1 : 16; uint32_t padding1 : 16;
guint32 padding2; uint32_t padding2;
SysprofCaptureCounter counters[0]; SysprofCaptureCounter counters[0];
} SysprofCaptureCounterDefine } SysprofCaptureCounterDefine
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -255,7 +262,7 @@ typedef struct
* bytes. So this makes a nice 2-cacheline aligned size which is * bytes. So this makes a nice 2-cacheline aligned size which is
* useful when the number of counters is rather small. * useful when the number of counters is rather small.
*/ */
guint32 ids[8]; uint32_t ids[8];
SysprofCaptureCounterValue values[8]; SysprofCaptureCounterValue values[8];
} SysprofCaptureCounterValues } SysprofCaptureCounterValues
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -264,9 +271,9 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint32 n_values : 16; uint32_t n_values : 16;
guint32 padding1 : 16; uint32_t padding1 : 16;
guint32 padding2; uint32_t padding2;
SysprofCaptureCounterValues values[0]; SysprofCaptureCounterValues values[0];
} SysprofCaptureCounterSet } SysprofCaptureCounterSet
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -275,10 +282,10 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
gint64 duration; int64_t duration;
gchar group[24]; char group[24];
gchar name[40]; char name[40];
gchar message[0]; char message[0];
} SysprofCaptureMark } SysprofCaptureMark
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -286,8 +293,8 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
gchar id[40]; char id[40];
gchar metadata[0]; char metadata[0];
} SysprofCaptureMetadata } SysprofCaptureMetadata
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -295,11 +302,11 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint32 severity : 16; uint32_t severity : 16;
guint32 padding1 : 16; uint32_t padding1 : 16;
guint32 padding2 : 32; uint32_t padding2 : 32;
gchar domain[32]; char domain[32];
gchar message[0]; char message[0];
} SysprofCaptureLog } SysprofCaptureLog
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -307,11 +314,11 @@ SYSPROF_ALIGNED_BEGIN(1)
typedef struct typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
guint32 is_last : 1; uint32_t is_last : 1;
guint32 padding1 : 15; uint32_t padding1 : 15;
guint32 len : 16; uint32_t len : 16;
gchar path[256]; char path[256];
guint8 data[0]; uint8_t data[0];
} SysprofCaptureFileChunk } SysprofCaptureFileChunk
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
@ -320,37 +327,37 @@ typedef struct
{ {
SysprofCaptureFrame frame; SysprofCaptureFrame frame;
SysprofCaptureAddress alloc_addr; SysprofCaptureAddress alloc_addr;
gint64 alloc_size; int64_t alloc_size;
gint32 tid; int32_t tid;
guint32 n_addrs : 16; uint32_t n_addrs : 16;
guint32 padding1 : 16; uint32_t padding1 : 16;
SysprofCaptureAddress addrs[0]; SysprofCaptureAddress addrs[0];
} SysprofCaptureAllocation } SysprofCaptureAllocation
SYSPROF_ALIGNED_END(1); SYSPROF_ALIGNED_END(1);
G_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256); static_assert (sizeof (SysprofCaptureFileHeader) == 256, "SysprofCaptureFileHeader changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24); static_assert (sizeof (SysprofCaptureFrame) == 24, "SysprofCaptureFrame changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56); static_assert (sizeof (SysprofCaptureMap) == 56, "SysprofCaptureMap changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureJitmap) == 28); static_assert (sizeof (SysprofCaptureJitmap) == 28, "SysprofCaptureJitmap changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureProcess) == 24); static_assert (sizeof (SysprofCaptureProcess) == 24, "SysprofCaptureProcess changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureSample) == 32); static_assert (sizeof (SysprofCaptureSample) == 32, "SysprofCaptureSample changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureFork) == 28); static_assert (sizeof (SysprofCaptureFork) == 28, "SysprofCaptureFork changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureExit) == 24); static_assert (sizeof (SysprofCaptureExit) == 24, "SysprofCaptureExit changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureTimestamp) == 24); static_assert (sizeof (SysprofCaptureTimestamp) == 24, "SysprofCaptureTimestamp changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureCounter) == 128); static_assert (sizeof (SysprofCaptureCounter) == 128, "SysprofCaptureCounter changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureCounterValues) == 96); static_assert (sizeof (SysprofCaptureCounterValues) == 96, "SysprofCaptureCounterValues changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureCounterDefine) == 32); static_assert (sizeof (SysprofCaptureCounterDefine) == 32, "SysprofCaptureCounterDefine changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureCounterSet) == 32); static_assert (sizeof (SysprofCaptureCounterSet) == 32, "SysprofCaptureCounterSet changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureMark) == 96); static_assert (sizeof (SysprofCaptureMark) == 96, "SysprofCaptureMark changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureMetadata) == 64); static_assert (sizeof (SysprofCaptureMetadata) == 64, "SysprofCaptureMetadata changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureLog) == 64); static_assert (sizeof (SysprofCaptureLog) == 64, "SysprofCaptureLog changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureFileChunk) == 284); static_assert (sizeof (SysprofCaptureFileChunk) == 284, "SysprofCaptureFileChunk changed size");
G_STATIC_ASSERT (sizeof (SysprofCaptureAllocation) == 48); static_assert (sizeof (SysprofCaptureAllocation) == 48, "SysprofCaptureAllocation changed size");
G_STATIC_ASSERT ((G_STRUCT_OFFSET (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0); static_assert ((offsetof (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureAllocation.addrs is not aligned");
G_STATIC_ASSERT ((G_STRUCT_OFFSET (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0); 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, sysprof_capture_address_compare (SysprofCaptureAddress a,
SysprofCaptureAddress b) SysprofCaptureAddress b)
{ {
@ -362,4 +369,17 @@ sysprof_capture_address_compare (SysprofCaptureAddress a,
return 0; 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

View File

@ -56,14 +56,24 @@
#pragma once #pragma once
#include <glib.h>
#ifdef __linux__ #ifdef __linux__
# include <sys/sendfile.h> # include <sys/sendfile.h>
#endif #endif
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
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__ #ifdef __linux__
# define _sysprof_getpagesize() getpagesize() # define _sysprof_getpagesize() getpagesize()
# define _sysprof_pread(a,b,c,d) pread(a,b,c,d) # 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, ssize_t _sysprof_write (int fd,
const void *buf, const void *buf,
size_t count); size_t count);
gint32 _sysprof_getpid (void); int32_t _sysprof_getpid (void);
ssize_t _sysprof_sendfile (int out_fd, ssize_t _sysprof_sendfile (int out_fd,
int in_fd, int in_fd,
off_t *offset, off_t *offset,
size_t count); 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 #endif

View File

@ -54,24 +54,23 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-capture-util"
#include "config.h" #include "config.h"
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <glib.h>
#include <unistd.h> #include <unistd.h>
#ifdef G_OS_WIN32 #ifdef _WIN32
# include <process.h> # include <process.h>
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
# include <windows.h> # include <windows.h>
#endif #endif
#include "sysprof-capture-util-private.h" #include "sysprof-capture-util-private.h"
#include "sysprof-macros.h"
#ifdef G_OS_WIN32 #ifdef _WIN32
static G_LOCK_DEFINE (_sysprof_io_sync); static void *_sysprof_io_sync_lock = SRWLOCK_INIT;
#endif #endif
size_t size_t
@ -79,9 +78,9 @@ size_t
{ {
static size_t pgsz = 0; 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; SYSTEM_INFO system_info;
GetSystemInfo (&system_info); GetSystemInfo (&system_info);
pgsz = system_info.dwPageSize; pgsz = system_info.dwPageSize;
@ -99,14 +98,14 @@ ssize_t
size_t count, size_t count,
off_t offset) off_t offset)
{ {
#ifdef G_OS_WIN32 #ifdef _WIN32
ssize_t ret = -1; ssize_t ret = -1;
G_LOCK (_sysprof_io_sync); AcquireSRWLockExclusive (_sysprof_io_sync_lock);
errno = 0; errno = 0;
if (lseek (fd, offset, SEEK_SET) != -1) if (lseek (fd, offset, SEEK_SET) != -1)
ret = read (fd, buf, count); ret = read (fd, buf, count);
G_UNLOCK (_sysprof_io_sync); ReleaseSRWLockExclusive (_sysprof_io_sync_lock);
return ret; return ret;
#else #else
@ -121,14 +120,14 @@ ssize_t
size_t count, size_t count,
off_t offset) off_t offset)
{ {
#ifdef G_OS_WIN32 #ifdef _WIN32
ssize_t ret = -1; ssize_t ret = -1;
G_LOCK (_sysprof_io_sync); AcquireSRWLockExclusive (_sysprof_io_sync_lock);
errno = 0; errno = 0;
if (lseek (fd, offset, SEEK_SET) != -1) if (lseek (fd, offset, SEEK_SET) != -1)
ret = write (fd, buf, count); ret = write (fd, buf, count);
G_UNLOCK (_sysprof_io_sync); ReleaseSRWLockExclusive (_sysprof_io_sync_lock);
return ret; return ret;
#else #else
@ -142,13 +141,13 @@ ssize_t
const void *buf, const void *buf,
size_t count) size_t count)
{ {
#ifdef G_OS_WIN32 #ifdef _WIN32
ssize_t ret = -1; ssize_t ret = -1;
G_LOCK (_sysprof_io_sync); AcquireSRWLockExclusive (_sysprof_io_sync_lock);
errno = 0; errno = 0;
ret = write (fd, buf, count); ret = write (fd, buf, count);
G_UNLOCK (_sysprof_io_sync); ReleaseSRWLockExclusive (_sysprof_io_sync_lock);
return ret; return ret;
#else #else
@ -157,10 +156,10 @@ ssize_t
#endif #endif
} }
gint32 int32_t
(_sysprof_getpid) (void) (_sysprof_getpid) (void)
{ {
#ifdef G_OS_WIN32 #ifdef _WIN32
return _getpid (); return _getpid ();
#else #else
return getpid (); return getpid ();
@ -205,14 +204,14 @@ ssize_t
if (n_read <= 0) if (n_read <= 0)
return -1; return -1;
g_assert (count >= n_read); assert (count >= n_read);
count -= n_read; count -= n_read;
rpos += n_read; rpos += n_read;
while (wpos < rpos) while (wpos < rpos)
{ {
g_assert (off < sizeof buf); assert (off < sizeof buf);
errno = 0; errno = 0;
n_written = write (out_fd, &buf[off], rpos - wpos); 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) if (offset != NULL)
*offset = rpos; *offset = rpos;
@ -234,3 +233,23 @@ ssize_t
errno = 0; errno = 0;
return total; 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;
}

View File

@ -54,21 +54,31 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-cat"
#include "config.h" #include "config.h"
#include <glib/gstdio.h> #include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <sysprof-capture.h>
#include <unistd.h> #include <unistd.h>
#include "sysprof-capture.h"
#include "sysprof-macros-internal.h"
typedef struct typedef struct
{ {
guint64 src; uint64_t src;
guint64 dst; uint64_t dst;
} TranslateItem; } TranslateItem;
typedef struct
{
TranslateItem *items;
size_t n_items;
size_t n_items_allocated;
} TranslateTable;
enum { enum {
TRANSLATE_ADDR, TRANSLATE_ADDR,
TRANSLATE_CTR, TRANSLATE_CTR,
@ -76,15 +86,19 @@ enum {
}; };
static void static void
translate_table_clear (GArray **tables, translate_table_clear (TranslateTable *tables,
guint table) 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 static int
compare_by_src (gconstpointer a, compare_by_src (const void *a,
gconstpointer b) const void *b)
{ {
const TranslateItem *itema = a; const TranslateItem *itema = a;
const TranslateItem *itemb = b; const TranslateItem *itemb = b;
@ -98,32 +112,41 @@ compare_by_src (gconstpointer a,
} }
static void static void
translate_table_sort (GArray **tables, translate_table_sort (TranslateTable *tables,
guint table) unsigned int table)
{ {
if (tables[table]) TranslateTable *table_ptr = &tables[table];
g_array_sort (tables[table], compare_by_src);
if (table_ptr->items)
qsort (table_ptr->items, table_ptr->n_items, sizeof (*table_ptr->items), compare_by_src);
} }
static void static void
translate_table_add (GArray **tables, translate_table_add (TranslateTable *tables,
guint table, unsigned int table,
guint64 src, uint64_t src,
guint64 dst) uint64_t dst)
{ {
TranslateTable *table_ptr = &tables[table];
const TranslateItem item = { src, dst }; const TranslateItem item = { src, dst };
if (tables[table] == NULL) if (table_ptr->n_items == table_ptr->n_items_allocated)
tables[table] = g_array_new (FALSE, FALSE, sizeof (TranslateItem)); {
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 static uint64_t
translate_table_translate (GArray **tables, translate_table_translate (TranslateTable *tables,
guint table, unsigned int table,
guint64 src) uint64_t src)
{ {
TranslateTable *table_ptr = &tables[table];
const TranslateItem *item; const TranslateItem *item;
TranslateItem key = { src, 0 }; TranslateItem key = { src, 0 };
@ -133,31 +156,30 @@ translate_table_translate (GArray **tables,
return src; return src;
} }
if (tables[table] == NULL) if (table_ptr->items == NULL)
return src; return src;
item = bsearch (&key, item = bsearch (&key,
tables[table]->data, table_ptr->items,
tables[table]->len, table_ptr->n_items,
sizeof (TranslateItem), sizeof (*table_ptr->items),
compare_by_src); compare_by_src);
return item != NULL ? item->dst : src; return item != NULL ? item->dst : src;
} }
gboolean bool
sysprof_capture_writer_cat (SysprofCaptureWriter *self, sysprof_capture_writer_cat (SysprofCaptureWriter *self,
SysprofCaptureReader *reader, SysprofCaptureReader *reader)
GError **error)
{ {
GArray *tables[N_TRANSLATE] = { NULL }; TranslateTable tables[N_TRANSLATE] = { 0, };
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
gint64 start_time; int64_t start_time;
gint64 first_start_time = G_MAXINT64; int64_t first_start_time = INT64_MAX;
gint64 end_time = -1; int64_t end_time = -1;
g_return_val_if_fail (self != NULL, FALSE); assert (self != NULL);
g_return_val_if_fail (reader != NULL, FALSE); assert (reader != NULL);
sysprof_capture_reader_reset (reader); sysprof_capture_reader_reset (reader);
@ -174,10 +196,10 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
*/ */
while (sysprof_capture_reader_peek_type (reader, &type)) while (sysprof_capture_reader_peek_type (reader, &type))
{ {
g_autoptr(GHashTable) jitmap = NULL; const SysprofCaptureJitmap *jitmap;
GHashTableIter iter; SysprofCaptureJitmapIter iter;
const gchar *name; SysprofCaptureAddress addr;
guint64 addr; const char *name;
if (type != SYSPROF_CAPTURE_FRAME_JITMAP) if (type != SYSPROF_CAPTURE_FRAME_JITMAP)
{ {
@ -189,10 +211,10 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
if (!(jitmap = sysprof_capture_reader_read_jitmap (reader))) if (!(jitmap = sysprof_capture_reader_read_jitmap (reader)))
goto panic; goto panic;
g_hash_table_iter_init (&iter, jitmap); sysprof_capture_jitmap_iter_init (&iter, jitmap);
while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&name)) 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 need to keep a table of replacement addresses so that
* we can translate the samples into the destination address * we can translate the samples into the destination address
* space that we synthesized for the address identifier. * space that we synthesized for the address identifier.
@ -364,7 +386,7 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
frame->frame.pid, frame->frame.pid,
frame->id, frame->id,
frame->metadata, frame->metadata,
frame->frame.len - G_STRUCT_OFFSET (SysprofCaptureMetadata, metadata)); frame->frame.len - offsetof (SysprofCaptureMetadata, metadata));
break; break;
} }
@ -378,7 +400,7 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
{ {
SysprofCaptureAddress addrs[frame->n_addrs]; 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]); addrs[z] = translate_table_translate (tables, TRANSLATE_ADDR, frame->addrs[z]);
sysprof_capture_writer_add_sample (self, sysprof_capture_writer_add_sample (self,
@ -401,27 +423,30 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
goto panic; 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]; SysprofCaptureCounter c = frame->counters[z];
guint src = c.id; unsigned int src = c.id;
c.id = sysprof_capture_writer_request_counter (self, 1); c.id = sysprof_capture_writer_request_counter (self, 1);
if (c.id != src) if (c.id != src)
translate_table_add (tables, TRANSLATE_CTR, src, c.id); 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, sysprof_capture_writer_define_counters (self,
frame->frame.time, frame->frame.time,
frame->frame.cpu, frame->frame.cpu,
frame->frame.pid, frame->frame.pid,
(gpointer)counter->data, counters,
counter->len); n_counters);
translate_table_sort (tables, TRANSLATE_CTR); translate_table_sort (tables, TRANSLATE_CTR);
} }
@ -437,35 +462,46 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
goto panic; goto panic;
{ {
g_autoptr(GArray) ids = g_array_new (FALSE, FALSE, sizeof (guint)); unsigned int *ids = NULL;
g_autoptr(GArray) values = g_array_new (FALSE, FALSE, sizeof (SysprofCaptureCounterValue)); 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]; 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]) 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]; SysprofCaptureCounterValue value = v->values[y];
g_array_append_val (ids, dst); if (n_elements == n_elements_allocated)
g_array_append_val (values, value); {
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, sysprof_capture_writer_set_counters (self,
frame->frame.time, frame->frame.time,
frame->frame.cpu, frame->frame.cpu,
frame->frame.pid, frame->frame.pid,
(const guint *)(gpointer)ids->data, ids,
(const SysprofCaptureCounterValue *)(gpointer)values->data, values,
ids->len); n_elements);
} }
break; break;
@ -512,16 +548,12 @@ sysprof_capture_writer_cat (SysprofCaptureWriter *self,
translate_table_clear (tables, TRANSLATE_ADDR); translate_table_clear (tables, TRANSLATE_ADDR);
translate_table_clear (tables, TRANSLATE_CTR); translate_table_clear (tables, TRANSLATE_CTR);
return TRUE; return true;
panic: 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_ADDR);
translate_table_clear (tables, TRANSLATE_CTR); translate_table_clear (tables, TRANSLATE_CTR);
return FALSE; errno = EIO;
return false;
} }

File diff suppressed because it is too large Load Diff

View File

@ -56,36 +56,27 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include "sysprof-capture-types.h" #include "sysprof-capture-types.h"
#include "sysprof-version-macros.h" #include "sysprof-version-macros.h"
G_BEGIN_DECLS SYSPROF_BEGIN_DECLS
typedef struct _SysprofCaptureWriter SysprofCaptureWriter; 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 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 SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureWriter *sysprof_capture_writer_new (const gchar *filename, SysprofCaptureWriter *sysprof_capture_writer_new (const char *filename,
gsize buffer_size); size_t buffer_size);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureWriter *sysprof_capture_writer_new_from_fd (int fd, SysprofCaptureWriter *sysprof_capture_writer_new_from_fd (int fd,
gsize buffer_size); size_t buffer_size);
SYSPROF_AVAILABLE_IN_ALL 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 SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureWriter *sysprof_capture_writer_ref (SysprofCaptureWriter *self); SysprofCaptureWriter *sysprof_capture_writer_ref (SysprofCaptureWriter *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
@ -94,161 +85,149 @@ SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_writer_stat (SysprofCaptureWriter *self, void sysprof_capture_writer_stat (SysprofCaptureWriter *self,
SysprofCaptureStat *stat); SysprofCaptureStat *stat);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_writer_set_flush_delay (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_file (SysprofCaptureWriter *self,
GMainContext *main_context, int64_t time,
guint timeout_seconds); int cpu,
int32_t pid,
const char *path,
bool is_last,
const uint8_t *data,
size_t data_len);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_file (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
const gchar *path, const char *path,
gboolean is_last, int fd);
const guint8 *data,
gsize data_len);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_file_fd (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_map (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
const gchar *path, uint64_t start,
gint fd); uint64_t end,
uint64_t offset,
uint64_t inode,
const char *filename);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_map (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_mark (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
guint64 start, uint64_t duration,
guint64 end, const char *group,
guint64 offset, const char *name,
guint64 inode, const char *message);
const gchar *filename);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
guint64 duration, const char *id,
const gchar *group, const char *metadata,
const gchar *name, ssize_t metadata_len);
const gchar *message);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, uint64_t sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self,
gint64 time, const char *name);
gint cpu,
gint32 pid,
const gchar *id,
const gchar *metadata,
gssize metadata_len);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
guint64 sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_process (SysprofCaptureWriter *self,
const gchar *name); int64_t time,
int cpu,
int32_t pid,
const char *cmdline);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_process (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_sample (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
const gchar *cmdline); int32_t tid,
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_sample (SysprofCaptureWriter *self,
gint64 time,
gint cpu,
gint32 pid,
gint32 tid,
const SysprofCaptureAddress *addrs, const SysprofCaptureAddress *addrs,
guint n_addrs); unsigned int n_addrs);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_fork (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_fork (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
gint32 child_pid); int32_t child_pid);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_exit (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_exit (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid); int32_t pid);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_timestamp (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_timestamp (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid); int32_t pid);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_define_counters (SysprofCaptureWriter *self, bool sysprof_capture_writer_define_counters (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
const SysprofCaptureCounter *counters, const SysprofCaptureCounter *counters,
guint n_counters); unsigned int n_counters);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_set_counters (SysprofCaptureWriter *self, bool sysprof_capture_writer_set_counters (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
const guint *counters_ids, const unsigned int *counters_ids,
const SysprofCaptureCounterValue *values, const SysprofCaptureCounterValue *values,
guint n_counters); unsigned int n_counters);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_add_log (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_log (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
GLogLevelFlags severity, int severity,
const gchar *domain, const char *domain,
const gchar *message); const char *message);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
gboolean sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_allocation (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
gint32 tid, int32_t tid,
SysprofCaptureAddress alloc_addr, SysprofCaptureAddress alloc_addr,
gint64 alloc_size, int64_t alloc_size,
SysprofBacktraceFunc backtrace_func, SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data); void *backtrace_data);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
gboolean sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self, bool sysprof_capture_writer_add_allocation_copy (SysprofCaptureWriter *self,
gint64 time, int64_t time,
gint cpu, int cpu,
gint32 pid, int32_t pid,
gint32 tid, int32_t tid,
SysprofCaptureAddress alloc_addr, SysprofCaptureAddress alloc_addr,
gint64 alloc_size, int64_t alloc_size,
const SysprofCaptureAddress *addrs, const SysprofCaptureAddress *addrs,
guint n_addrs); unsigned int n_addrs);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_flush (SysprofCaptureWriter *self); bool sysprof_capture_writer_flush (SysprofCaptureWriter *self);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_save_as (SysprofCaptureWriter *self, bool sysprof_capture_writer_save_as (SysprofCaptureWriter *self,
const gchar *filename, const char *filename);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
guint sysprof_capture_writer_request_counter (SysprofCaptureWriter *self, unsigned int sysprof_capture_writer_request_counter (SysprofCaptureWriter *self,
guint n_counters); unsigned int n_counters);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_writer_create_reader (SysprofCaptureWriter *self, SysprofCaptureReader *sysprof_capture_writer_create_reader (SysprofCaptureWriter *self);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_splice (SysprofCaptureWriter *self, bool sysprof_capture_writer_splice (SysprofCaptureWriter *self,
SysprofCaptureWriter *dest, SysprofCaptureWriter *dest);
GError **error);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_writer_cat (SysprofCaptureWriter *self, bool sysprof_capture_writer_cat (SysprofCaptureWriter *self,
SysprofCaptureReader *reader, SysprofCaptureReader *reader);
GError **error); SYSPROF_INTERNAL
G_GNUC_INTERNAL bool _sysprof_capture_writer_add_raw (SysprofCaptureWriter *self,
gboolean _sysprof_capture_writer_add_raw (SysprofCaptureWriter *self,
const SysprofCaptureFrame *frame); const SysprofCaptureFrame *frame);
G_GNUC_INTERNAL SYSPROF_INTERNAL
gboolean _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self, bool _sysprof_capture_writer_splice_from_fd (SysprofCaptureWriter *self,
int fd, int fd) SYSPROF_INTERNAL;
GError **error) G_GNUC_INTERNAL; SYSPROF_INTERNAL
G_GNUC_INTERNAL bool _sysprof_capture_writer_set_time_range (SysprofCaptureWriter *self,
gboolean _sysprof_capture_writer_set_time_range (SysprofCaptureWriter *self, int64_t start_time,
gint64 start_time, int64_t end_time) SYSPROF_INTERNAL;
gint64 end_time) G_GNUC_INTERNAL;
SYSPROF_END_DECLS
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref)
G_END_DECLS

View File

@ -56,10 +56,6 @@
#pragma once #pragma once
#include <glib.h>
G_BEGIN_DECLS
#define SYSPROF_CAPTURE_INSIDE #define SYSPROF_CAPTURE_INSIDE
# include "sysprof-address.h" # include "sysprof-address.h"
@ -74,5 +70,3 @@ G_BEGIN_DECLS
# include "sysprof-version-macros.h" # include "sysprof-version-macros.h"
#undef SYSPROF_CAPTURE_INSIDE #undef SYSPROF_CAPTURE_INSIDE
G_END_DECLS

View File

@ -54,18 +54,20 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-clock"
#include "config.h" #include "config.h"
#include "sysprof-clock.h" #include <assert.h>
#include <stdbool.h>
gint sysprof_clock = -1; #include "sysprof-clock.h"
#include "sysprof-macros-internal.h"
int sysprof_clock = -1;
void void
sysprof_clock_init (void) sysprof_clock_init (void)
{ {
static const gint clock_ids[] = { static const int clock_ids[] = {
CLOCK_MONOTONIC, CLOCK_MONOTONIC,
CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_RAW,
#ifdef __linux__ #ifdef __linux__
@ -78,7 +80,7 @@ sysprof_clock_init (void)
if (sysprof_clock != -1) if (sysprof_clock != -1)
return; 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; struct timespec ts;
int clock_id = clock_ids [i]; int clock_id = clock_ids [i];
@ -90,5 +92,5 @@ sysprof_clock_init (void)
} }
} }
g_assert_not_reached (); sysprof_assert_not_reached ();
} }

View File

@ -56,18 +56,19 @@
#pragma once #pragma once
#include <glib.h> #include <stdint.h>
#include <time.h> #include <time.h>
#include "sysprof-macros.h"
#include "sysprof-version-macros.h" #include "sysprof-version-macros.h"
G_BEGIN_DECLS SYSPROF_BEGIN_DECLS
typedef gint SysprofClock; typedef int SysprofClock;
typedef gint64 SysprofTimeStamp; typedef int64_t SysprofTimeStamp;
typedef gint32 SysprofTimeSysprofan; 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 SYSPROF_AVAILABLE_IN_ALL
SysprofClock sysprof_clock; SysprofClock sysprof_clock;
@ -78,7 +79,7 @@ sysprof_clock_get_current_time (void)
struct timespec ts; struct timespec ts;
SysprofClock clock = sysprof_clock; SysprofClock clock = sysprof_clock;
if G_UNLIKELY (clock == -1) if SYSPROF_UNLIKELY (clock == -1)
clock = CLOCK_MONOTONIC; clock = CLOCK_MONOTONIC;
clock_gettime (clock, &ts); clock_gettime (clock, &ts);
@ -94,4 +95,4 @@ sysprof_clock_get_relative_time (SysprofTimeStamp epoch)
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
void sysprof_clock_init (void); void sysprof_clock_init (void);
G_END_DECLS SYSPROF_END_DECLS

View File

@ -54,56 +54,70 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-collector"
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
# define _GNU_SOURCE # define _GNU_SOURCE
#endif #endif
#include <glib-unix.h> #include <assert.h>
#include <gio/gio.h> #include <errno.h>
#include <gio/gunixconnection.h> #include <poll.h>
#include <pthread.h>
#ifdef __linux__ #ifdef __linux__
# include <sched.h> # include <sched.h>
#endif #endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/socket.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "mapped-ring-buffer.h" #include "mapped-ring-buffer.h"
#include "sysprof-capture-writer.h" #include "sysprof-capture-util-private.h"
#include "sysprof-collector.h" #include "sysprof-collector.h"
#include "sysprof-macros-internal.h"
#define MAX_UNWIND_DEPTH 128 #define MAX_UNWIND_DEPTH 128
#define CREATRING "CreatRing\0" #define CREATRING "CreatRing\0"
#define CREATRING_LEN 10 #define CREATRING_LEN 10
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#ifndef MSG_CMSG_CLOEXEC
#define MSG_CMSG_CLOEXEC 0
#endif
typedef struct typedef struct
{ {
MappedRingBuffer *buffer; MappedRingBuffer *buffer;
gboolean is_shared; bool is_shared;
int tid; int tid;
int pid; int pid;
} SysprofCollector; } SysprofCollector;
#define COLLECTOR_INVALID ((gpointer)&invalid) #define COLLECTOR_INVALID ((void *)&invalid)
static MappedRingBuffer *request_writer (void); 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 const SysprofCollector *sysprof_collector_get (void);
static G_LOCK_DEFINE (control_fd); static pthread_mutex_t control_fd_lock = PTHREAD_MUTEX_INITIALIZER;
static GPrivate collector_key = G_PRIVATE_INIT (sysprof_collector_free); static pthread_key_t collector_key; /* initialised in sysprof_collector_init() */
static GPrivate single_trace_key = G_PRIVATE_INIT (NULL); 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 *shared_collector;
static SysprofCollector invalid; static SysprofCollector invalid;
static inline gboolean static inline bool
use_single_trace (void) use_single_trace (void)
{ {
return GPOINTER_TO_INT (g_private_get (&single_trace_key)); return (bool) pthread_getspecific (single_trace_key);
} }
static inline int static inline int
@ -116,60 +130,218 @@ _do_getcpu (void)
#endif #endif
} }
static inline gsize static inline size_t
realign (gsize size) realign (size_t size)
{ {
return (size + SYSPROF_CAPTURE_ALIGN - 1) & ~(SYSPROF_CAPTURE_ALIGN - 1); 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 * static MappedRingBuffer *
request_writer (void) request_writer (void)
{ {
static GUnixConnection *conn; static int peer_fd = -1;
MappedRingBuffer *buffer = NULL; MappedRingBuffer *buffer = NULL;
if (conn == NULL) if (peer_fd == -1)
{ {
const gchar *fdstr = g_getenv ("SYSPROF_CONTROL_FD"); const char *fdstr = getenv ("SYSPROF_CONTROL_FD");
int peer_fd = -1;
if (fdstr != NULL) if (fdstr != NULL)
peer_fd = atoi (fdstr); peer_fd = atoi (fdstr);
g_unsetenv ("SYSPROF_CONTROL_FD"); unsetenv ("SYSPROF_CONTROL_FD");
if (peer_fd > 0) if (peer_fd > 0)
{ {
g_autoptr(GSocket) sock = NULL; (void) set_fd_blocking (peer_fd);
g_unix_set_fd_nonblocking (peer_fd, FALSE, NULL); #ifdef SO_NOSIGPIPE
{
if ((sock = g_socket_new_from_fd (peer_fd, NULL))) int opt_value = 1;
{ (void) setsockopt (peer_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt_value, sizeof (opt_value));
g_autoptr(GSocketConnection) scon = NULL; }
#endif
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));
}
} }
} }
if (conn != NULL) if (peer_fd >= 0)
{ {
GOutputStream *out_stream; if (send_all_blocking (peer_fd, (const uint8_t *) CREATRING, CREATRING_LEN, NULL))
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)
{ {
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); buffer = mapped_ring_buffer_new_writer (ring_fd);
close (ring_fd); close (ring_fd);
@ -177,7 +349,7 @@ request_writer (void)
} }
} }
return g_steal_pointer (&buffer); return sysprof_steal_pointer (&buffer);
} }
static void static void
@ -185,7 +357,7 @@ write_final_frame (MappedRingBuffer *ring)
{ {
SysprofCaptureFrame *fr; SysprofCaptureFrame *fr;
g_assert (ring != NULL); assert (ring != NULL);
if ((fr = mapped_ring_buffer_allocate (ring, sizeof *fr))) if ((fr = mapped_ring_buffer_allocate (ring, sizeof *fr)))
{ {
@ -199,13 +371,13 @@ write_final_frame (MappedRingBuffer *ring)
} }
static void static void
sysprof_collector_free (gpointer data) sysprof_collector_free (void *data)
{ {
SysprofCollector *collector = data; SysprofCollector *collector = data;
if (collector != NULL && collector != COLLECTOR_INVALID) if (collector != NULL && collector != COLLECTOR_INVALID)
{ {
MappedRingBuffer *buffer = g_steal_pointer (&collector->buffer); MappedRingBuffer *buffer = sysprof_steal_pointer (&collector->buffer);
if (buffer != NULL) if (buffer != NULL)
{ {
@ -213,33 +385,41 @@ sysprof_collector_free (gpointer data)
mapped_ring_buffer_unref (buffer); mapped_ring_buffer_unref (buffer);
} }
g_free (collector); free (collector);
} }
} }
static const SysprofCollector * static const SysprofCollector *
sysprof_collector_get (void) 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 */ /* We might have gotten here recursively */
if G_UNLIKELY (collector == COLLECTOR_INVALID) if SYSPROF_UNLIKELY (collector == COLLECTOR_INVALID)
return COLLECTOR_INVALID; return COLLECTOR_INVALID;
if G_LIKELY (collector != NULL) if SYSPROF_LIKELY (collector != NULL)
return collector; return collector;
if (use_single_trace () && shared_collector != COLLECTOR_INVALID) if (use_single_trace () && shared_collector != COLLECTOR_INVALID)
return shared_collector; 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 (); self->pid = getpid ();
#ifdef __linux__ #ifdef __linux__
self->tid = syscall (__NR_gettid, 0); self->tid = syscall (__NR_gettid, 0);
@ -247,66 +427,91 @@ sysprof_collector_get (void)
self->tid = self->pid; self->tid = self->pid;
#endif #endif
if (g_getenv ("SYSPROF_CONTROL_FD") != NULL) pthread_mutex_lock (&control_fd_lock);
if (getenv ("SYSPROF_CONTROL_FD") != NULL)
self->buffer = request_writer (); self->buffer = request_writer ();
if (self->is_shared) /* Update the stored collector */
shared_collector = self; old_collector = pthread_getspecific (collector_key);
else
g_private_replace (&collector_key, self);
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; 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 void
sysprof_collector_init (void) sysprof_collector_init (void)
{ {
static gsize once_init; if SYSPROF_UNLIKELY (pthread_once (&collector_init, collector_init_cb) != 0)
abort ();
if (g_once_init_enter (&once_init))
{
sysprof_clock_init ();
(void)sysprof_collector_get ();
g_once_init_leave (&once_init, TRUE);
}
} }
#define COLLECTOR_BEGIN \ #define COLLECTOR_BEGIN \
G_STMT_START { \ do { \
const SysprofCollector *collector = sysprof_collector_get (); \ const SysprofCollector *collector = sysprof_collector_get (); \
if G_LIKELY (collector->buffer) \ if SYSPROF_LIKELY (collector->buffer) \
{ \ { \
if G_UNLIKELY (collector->is_shared) \ if SYSPROF_UNLIKELY (collector->is_shared) \
G_LOCK (control_fd); \ pthread_mutex_lock (&control_fd_lock); \
\ \
{ {
#define COLLECTOR_END \ #define COLLECTOR_END \
} \ } \
\ \
if G_UNLIKELY (collector->is_shared) \ if SYSPROF_UNLIKELY (collector->is_shared) \
G_UNLOCK (control_fd); \ pthread_mutex_unlock (&control_fd_lock); \
} \ } \
} G_STMT_END } while (0)
void void
sysprof_collector_allocate (SysprofCaptureAddress alloc_addr, sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
gint64 alloc_size, int64_t alloc_size,
SysprofBacktraceFunc backtrace_func, SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data) void *backtrace_data)
{ {
COLLECTOR_BEGIN { COLLECTOR_BEGIN {
SysprofCaptureAllocation *ev; SysprofCaptureAllocation *ev;
gsize len; size_t len;
len = sizeof *ev + (sizeof (SysprofCaptureAllocation) * MAX_UNWIND_DEPTH); len = sizeof *ev + (sizeof (SysprofCaptureAllocation) * MAX_UNWIND_DEPTH);
if ((ev = mapped_ring_buffer_allocate (collector->buffer, len))) 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 /* First take a backtrace, so that backtrace_func() can overwrite
* a little bit of data *BEFORE* ev->addrs as stratch space. This * a little bit of data *BEFORE* ev->addrs as stratch space. This
@ -321,7 +526,7 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
else else
n_addrs = 0; 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.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs;
ev->frame.type = SYSPROF_CAPTURE_FRAME_ALLOCATION; ev->frame.type = SYSPROF_CAPTURE_FRAME_ALLOCATION;
ev->frame.cpu = _do_getcpu (); ev->frame.cpu = _do_getcpu ();
@ -339,18 +544,18 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
} }
void void
sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data) void *backtrace_data)
{ {
COLLECTOR_BEGIN { COLLECTOR_BEGIN {
SysprofCaptureSample *ev; SysprofCaptureSample *ev;
gsize len; size_t len;
len = sizeof *ev + (sizeof (SysprofCaptureSample) * MAX_UNWIND_DEPTH); len = sizeof *ev + (sizeof (SysprofCaptureSample) * MAX_UNWIND_DEPTH);
if ((ev = mapped_ring_buffer_allocate (collector->buffer, len))) if ((ev = mapped_ring_buffer_allocate (collector->buffer, len)))
{ {
gint n_addrs; int n_addrs;
/* See comment from sysprof_collector_allocate(). */ /* See comment from sysprof_collector_allocate(). */
if (backtrace_func) if (backtrace_func)
@ -358,7 +563,7 @@ sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
else else
n_addrs = 0; 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.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs;
ev->frame.type = SYSPROF_CAPTURE_FRAME_SAMPLE; ev->frame.type = SYSPROF_CAPTURE_FRAME_SAMPLE;
ev->frame.cpu = _do_getcpu (); ev->frame.cpu = _do_getcpu ();
@ -374,16 +579,16 @@ sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
} }
void void
sysprof_collector_mark (gint64 time, sysprof_collector_mark (int64_t time,
gint64 duration, int64_t duration,
const gchar *group, const char *group,
const gchar *mark, const char *mark,
const gchar *message) const char *message)
{ {
COLLECTOR_BEGIN { COLLECTOR_BEGIN {
SysprofCaptureMark *ev; SysprofCaptureMark *ev;
gsize len; size_t len;
gsize sl; size_t sl;
if (group == NULL) if (group == NULL)
group = ""; group = "";
@ -405,8 +610,8 @@ sysprof_collector_mark (gint64 time,
ev->frame.pid = collector->pid; ev->frame.pid = collector->pid;
ev->frame.time = time; ev->frame.time = time;
ev->duration = duration; ev->duration = duration;
g_strlcpy (ev->group, group, sizeof ev->group); _sysprof_strlcpy (ev->group, group, sizeof ev->group);
g_strlcpy (ev->name, mark, sizeof ev->name); _sysprof_strlcpy (ev->name, mark, sizeof ev->name);
memcpy (ev->message, message, sl); memcpy (ev->message, message, sl);
ev->message[sl] = 0; ev->message[sl] = 0;
@ -417,14 +622,14 @@ sysprof_collector_mark (gint64 time,
} }
void void
sysprof_collector_log (GLogLevelFlags severity, sysprof_collector_log (int severity,
const gchar *domain, const char *domain,
const gchar *message) const char *message)
{ {
COLLECTOR_BEGIN { COLLECTOR_BEGIN {
SysprofCaptureLog *ev; SysprofCaptureLog *ev;
gsize len; size_t len;
gsize sl; size_t sl;
if (domain == NULL) if (domain == NULL)
domain = ""; domain = "";
@ -445,7 +650,7 @@ sysprof_collector_log (GLogLevelFlags severity,
ev->severity = severity & 0xFFFF; ev->severity = severity & 0xFFFF;
ev->padding1 = 0; ev->padding1 = 0;
ev->padding2 = 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); memcpy (ev->message, message, sl);
ev->message[sl] = 0; ev->message[sl] = 0;
@ -456,20 +661,20 @@ sysprof_collector_log (GLogLevelFlags severity,
} }
void void
sysprof_collector_log_printf (GLogLevelFlags severity, sysprof_collector_log_printf (int severity,
const gchar *domain, const char *domain,
const gchar *format, const char *format,
...) ...)
{ {
COLLECTOR_BEGIN { COLLECTOR_BEGIN {
g_autofree gchar *formatted = NULL; char formatted[2048];
SysprofCaptureLog *ev; SysprofCaptureLog *ev;
va_list args; va_list args;
gsize len; size_t len;
gsize sl; size_t sl;
va_start (args, format); va_start (args, format);
formatted = g_strdup_vprintf (format, args); vsnprintf (formatted, sizeof (formatted), format, args);
va_end (args); va_end (args);
if (domain == NULL) if (domain == NULL)
@ -488,7 +693,7 @@ sysprof_collector_log_printf (GLogLevelFlags severity,
ev->severity = severity & 0xFFFF; ev->severity = severity & 0xFFFF;
ev->padding1 = 0; ev->padding1 = 0;
ev->padding2 = 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); memcpy (ev->message, formatted, sl);
ev->message[sl] = 0; ev->message[sl] = 0;

View File

@ -57,34 +57,34 @@
#pragma once #pragma once
#include "sysprof-capture-types.h" #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 SYSPROF_AVAILABLE_IN_3_36
void sysprof_collector_init (void); void sysprof_collector_init (void);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
void sysprof_collector_allocate (SysprofCaptureAddress alloc_addr, void sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
gint64 alloc_size, int64_t alloc_size,
SysprofBacktraceFunc backtrace_func, SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data); void *backtrace_data);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
void sysprof_collector_sample (SysprofBacktraceFunc backtrace_func, void sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data); void *backtrace_data);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
void sysprof_collector_mark (gint64 time, void sysprof_collector_mark (int64_t time,
gint64 duration, int64_t duration,
const gchar *group, const char *group,
const gchar *mark, const char *mark,
const gchar *message); const char *message);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
void sysprof_collector_log (GLogLevelFlags severity, void sysprof_collector_log (int severity,
const gchar *domain, const char *domain,
const gchar *message); const char *message);
SYSPROF_AVAILABLE_IN_3_38 SYSPROF_AVAILABLE_IN_3_38
void sysprof_collector_log_printf (GLogLevelFlags severity, void sysprof_collector_log_printf (int severity,
const gchar *domain, const char *domain,
const gchar *format, const char *format,
...) G_GNUC_PRINTF (3, 4); ...) SYSPROF_PRINTF (3, 4);
G_END_DECLS SYSPROF_END_DECLS

View File

@ -0,0 +1,77 @@
/* sysprof-macros.h
*
* Copyright 2020 Endless OS Foundation
*
* Author:
* - Philip Withnall <withnall@endlessm.com>
*
* 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)

View File

@ -0,0 +1,98 @@
/* sysprof-macros.h
*
* Copyright 2020 Endless OS Foundation
*
* Author:
* - Philip Withnall <withnall@endlessm.com>
*
* 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 <limits.h>
#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

View File

@ -54,18 +54,36 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent * SPDX-License-Identifier: BSD-2-Clause-Patent
*/ */
#define G_LOG_DOMAIN "sysprof-platform"
#include "config.h" #include "config.h"
#include <glib.h> #include <stdlib.h>
#include <glib/gstdio.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
#include "sysprof-capture-util-private.h" #include "sysprof-capture-util-private.h"
#include "sysprof-platform.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: * sysprof_memfd_create:
* @name: (nullable): A descriptive name for the memfd or %NULL * @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. * Returns: An fd if successful; otherwise -1 and errno is set.
*/ */
int int
sysprof_memfd_create (const gchar *name) sysprof_memfd_create (const char *name)
{ {
#ifdef __NR_memfd_create #ifdef __NR_memfd_create
if (name == NULL) if (name == NULL)
name = "[sysprof]"; name = "[sysprof]";
return syscall (__NR_memfd_create, name, 0); return syscall (__NR_memfd_create, name, 0);
#else #else
gchar *name_used = NULL;
int fd; int fd;
const char *tmpdir;
char *template = NULL;
size_t template_len = 0;
/* /*
* TODO: It would be nice to ensure tmpfs * 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 * that the tmpfile we open is on tmpfs so that we get anonymous backed
* pages after unlinking. * 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); errno = ENOMEM;
g_free (name_used); 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; return fd;
#endif #endif
} }
@ -116,7 +150,7 @@ sysprof_memfd_create (const gchar *name)
* *
* Since: 3.36 * Since: 3.36
*/ */
gsize size_t
sysprof_getpagesize (void) sysprof_getpagesize (void)
{ {
return _sysprof_getpagesize (); return _sysprof_getpagesize ();

View File

@ -56,13 +56,17 @@
#pragma once #pragma once
#include "sysprof-version-macros.h" #include <stdint.h>
#include <string.h>
G_BEGIN_DECLS #include "sysprof-version-macros.h"
#include "sysprof-macros.h"
SYSPROF_BEGIN_DECLS
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
int sysprof_memfd_create (const gchar *desc); int sysprof_memfd_create (const char *desc);
SYSPROF_AVAILABLE_IN_3_36 SYSPROF_AVAILABLE_IN_3_36
gsize sysprof_getpagesize (void); size_t sysprof_getpagesize (void);
G_END_DECLS SYSPROF_END_DECLS

View File

@ -56,42 +56,54 @@
#pragma once #pragma once
#include <glib.h>
#include "sysprof-version.h" #include "sysprof-version.h"
#ifndef _SYSPROF_EXTERN #ifndef _SYSPROF_EXTERN
#define _SYSPROF_EXTERN extern #define _SYSPROF_EXTERN extern
#endif #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 #ifdef SYSPROF_DISABLE_DEPRECATION_WARNINGS
#define SYSPROF_DEPRECATED _SYSPROF_EXTERN #define SYSPROF_DEPRECATED _SYSPROF_EXTERN
#define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN #define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN
#define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN #define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN
#else #else
#define SYSPROF_DEPRECATED G_DEPRECATED _SYSPROF_EXTERN #define SYSPROF_DEPRECATED _SYSPROF_DEPRECATED _SYSPROF_EXTERN
#define SYSPROF_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _SYSPROF_EXTERN #define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN
#define SYSPROF_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _SYSPROF_EXTERN #define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN
#endif #endif
#define SYSPROF_VERSION_3_34 (G_ENCODE_VERSION (3, 34)) #define SYSPROF_VERSION_3_34 (SYSPROF_ENCODE_VERSION (3, 34, 0))
#define SYSPROF_VERSION_3_36 (G_ENCODE_VERSION (3, 36)) #define SYSPROF_VERSION_3_36 (SYSPROF_ENCODE_VERSION (3, 36, 0))
#define SYSPROF_VERSION_3_38 (G_ENCODE_VERSION (3, 38)) #define SYSPROF_VERSION_3_38 (SYSPROF_ENCODE_VERSION (3, 38, 0))
#if (SYSPROF_MINOR_VERSION == 99) #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) #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 #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 #endif
#if (SYSPROF_MINOR_VERSION == 99) #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) #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 #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 #endif
/** /**

View File

@ -81,7 +81,7 @@ sysprof_battery_aid_prepare (SysprofAid *self,
#endif #endif
} }
static gboolean static bool
collect_battery_counters (const SysprofCaptureFrame *frame, collect_battery_counters (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -114,7 +114,7 @@ sysprof_callgraph_aid_prepare (SysprofAid *self,
#endif #endif
} }
static gboolean static bool
discover_samples_cb (const SysprofCaptureFrame *frame, discover_samples_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -123,7 +123,7 @@ build_title (const SysprofCaptureCounter *ctr)
return g_string_free (str, FALSE); return g_string_free (str, FALSE);
} }
static gboolean static bool
collect_counters (const SysprofCaptureFrame *frame, collect_counters (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -85,7 +85,7 @@ sysprof_cpu_aid_prepare (SysprofAid *self,
#endif #endif
} }
static gboolean static bool
collect_info (const SysprofCaptureFrame *frame, collect_info (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -62,7 +62,7 @@ state_free (State *st)
g_slice_free (State, st); g_slice_free (State, st);
} }
static gboolean static bool
discover_max_n_addr (const SysprofCaptureFrame *frame, discover_max_n_addr (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {
@ -78,7 +78,7 @@ discover_max_n_addr (const SysprofCaptureFrame *frame,
return TRUE; return TRUE;
} }
static gboolean static bool
build_point_cache_cb (const SysprofCaptureFrame *frame, build_point_cache_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -135,7 +135,7 @@ update_cpu_info_cb (GObject *object,
gtk_label_set_label (self->cpu_label, str); gtk_label_set_label (self->cpu_label, str);
} }
static gboolean static bool
cpu_info_cb (const SysprofCaptureFrame *frame, cpu_info_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -80,7 +80,7 @@ sysprof_diskstat_aid_prepare (SysprofAid *self,
sysprof_profiler_add_source (profiler, source); sysprof_profiler_add_source (profiler, source);
} }
static gboolean static bool
collect_diskstat_counters (const SysprofCaptureFrame *frame, collect_diskstat_counters (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -143,7 +143,7 @@ sysprof_display_profiler_stopped_cb (SysprofDisplay *self,
g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(GError) error = 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); g_warning ("Failed to create capture creader: %s\n", error->message);
gtk_stack_set_visible_child (priv->stack, GTK_WIDGET (priv->failed_view)); 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); 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 *dialog;
GtkWidget *window; GtkWidget *window;
@ -1229,7 +1229,7 @@ sysprof_display_save (SysprofDisplay *self)
g_autofree gchar *path = g_file_get_path (file); g_autofree gchar *path = g_file_get_path (file);
g_autoptr(GError) error = NULL; 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; GtkWidget *msg;

View File

@ -73,7 +73,7 @@ typedef struct
G_DEFINE_TYPE (SysprofDuplexVisualizer, sysprof_duplex_visualizer, SYSPROF_TYPE_VISUALIZER) G_DEFINE_TYPE (SysprofDuplexVisualizer, sysprof_duplex_visualizer, SYSPROF_TYPE_VISUALIZER)
static gboolean static bool
collect_ranges_cb (const SysprofCaptureFrame *frame, collect_ranges_cb (const SysprofCaptureFrame *frame,
gpointer data) gpointer data)
{ {
@ -126,7 +126,7 @@ collect_ranges_cb (const SysprofCaptureFrame *frame,
return TRUE; return TRUE;
} }
static gboolean static bool
collect_values_cb (const SysprofCaptureFrame *frame, collect_values_cb (const SysprofCaptureFrame *frame,
gpointer data) gpointer data)
{ {

View File

@ -613,7 +613,7 @@ calc_y_int64 (gint64 lower,
return (gdouble)(value - lower) / (gdouble)(upper - lower); return (gdouble)(value - lower) / (gdouble)(upper - lower);
} }
static gboolean static bool
sysprof_line_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame, sysprof_line_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {
@ -655,7 +655,7 @@ sysprof_line_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame,
return TRUE; return TRUE;
} }
static gboolean static bool
sysprof_line_visualizer_load_data_range_cb (const SysprofCaptureFrame *frame, sysprof_line_visualizer_load_data_range_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -289,7 +289,7 @@ sysprof_log_model_init (SysprofLogModel *self)
self->items = g_array_new (FALSE, FALSE, sizeof (Item)); self->items = g_array_new (FALSE, FALSE, sizeof (Item));
} }
static gboolean static bool
cursor_foreach_cb (const SysprofCaptureFrame *frame, cursor_foreach_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -80,7 +80,7 @@ sysprof_logs_aid_new (void)
return g_object_new (SYSPROF_TYPE_LOGS_AID, NULL); return g_object_new (SYSPROF_TYPE_LOGS_AID, NULL);
} }
static gboolean static bool
find_marks_cb (const SysprofCaptureFrame *frame, find_marks_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -84,7 +84,7 @@ sysprof_marks_aid_new (void)
return g_object_new (SYSPROF_TYPE_MARKS_AID, NULL); return g_object_new (SYSPROF_TYPE_MARKS_AID, NULL);
} }
static gboolean static bool
find_marks_cb (const SysprofCaptureFrame *frame, find_marks_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -301,7 +301,7 @@ sysprof_marks_model_init (SysprofMarksModel *self)
self->items = g_array_new (FALSE, FALSE, sizeof (Item)); self->items = g_array_new (FALSE, FALSE, sizeof (Item));
} }
static gboolean static bool
cursor_foreach_cb (const SysprofCaptureFrame *frame, cursor_foreach_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -87,7 +87,7 @@ sysprof_memprof_aid_prepare (SysprofAid *self,
#endif #endif
} }
static gboolean static bool
discover_samples_cb (const SysprofCaptureFrame *frame, discover_samples_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -79,7 +79,7 @@ sysprof_netdev_aid_prepare (SysprofAid *self,
sysprof_profiler_add_source (profiler, source); sysprof_profiler_add_source (profiler, source);
} }
static gboolean static bool
collect_netdev_counters (const SysprofCaptureFrame *frame, collect_netdev_counters (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -65,7 +65,7 @@ discovery_ref (Discovery *d)
return d; return d;
} }
static gboolean static bool
discover_max_cb (const SysprofCaptureFrame *frame, discover_max_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {
@ -85,7 +85,7 @@ discover_max_cb (const SysprofCaptureFrame *frame,
return TRUE; return TRUE;
} }
static gboolean static bool
calc_points_cb (const SysprofCaptureFrame *frame, calc_points_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -69,7 +69,7 @@ sysprof_rapl_aid_new (void)
return g_object_new (SYSPROF_TYPE_RAPL_AID, NULL); return g_object_new (SYSPROF_TYPE_RAPL_AID, NULL);
} }
static gboolean static bool
collect_info (const SysprofCaptureFrame *frame, collect_info (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -382,7 +382,7 @@ calc_x (gint64 lower,
return (gdouble)(value - lower) / (gdouble)(upper - lower); return (gdouble)(value - lower) / (gdouble)(upper - lower);
} }
static gboolean static bool
sysprof_time_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame, sysprof_time_visualizer_load_data_frame_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -608,7 +608,7 @@ compare_gint64 (const gint64 *a,
return 0; return 0;
} }
static gboolean static bool
index_frame_times_frame_cb (const SysprofCaptureFrame *frame, index_frame_times_frame_cb (const SysprofCaptureFrame *frame,
gpointer user_data) gpointer user_data)
{ {

View File

@ -0,0 +1,121 @@
/* mapped-ring-buffer-source.c
*
* Copyright 2020 Christian Hergert <chergert@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "sysprof-mapped-ring-buffer-source"
#include "config.h"
#include <glib.h>
#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);
}

View File

@ -0,0 +1,47 @@
/* mapped-ring-buffer-source.h
*
* Copyright 2020 Christian Hergert <chergert@redhat.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#if !defined (SYSPROF_INSIDE) && !defined (SYSPROF_COMPILATION)
# error "Only <sysprof.h> can be included directly."
#endif
#include <glib.h>
#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

View File

@ -37,6 +37,7 @@ libsysprof_public_sources = [
libsysprof_public_headers = [ libsysprof_public_headers = [
'sysprof-battery-source.h', 'sysprof-battery-source.h',
'sysprof-callgraph-profile.h', 'sysprof-callgraph-profile.h',
'sysprof-capture-autocleanups.h',
'sysprof-capture-gobject.h', 'sysprof-capture-gobject.h',
'sysprof-capture-symbol-resolver.h', 'sysprof-capture-symbol-resolver.h',
'sysprof-control-source.h', 'sysprof-control-source.h',
@ -71,6 +72,7 @@ libsysprof_private_sources = [
'binfile.c', 'binfile.c',
'demangle.cpp', 'demangle.cpp',
'elfparser.c', 'elfparser.c',
'mapped-ring-buffer-source.c',
'sysprof-flatpak.c', 'sysprof-flatpak.c',
'sysprof-helpers.c', 'sysprof-helpers.c',
'sysprof-kallsyms.c', 'sysprof-kallsyms.c',

View File

@ -1,6 +1,7 @@
libdl_dep = cc.find_library('dl', required: false) libdl_dep = cc.find_library('dl', required: false)
preload_deps = [ preload_deps = [
dependency('glib-2.0'),
libsysprof_capture_dep, libsysprof_capture_dep,
libdl_dep, libdl_dep,
] ]
@ -14,7 +15,7 @@ libsysprof_memory_preload = shared_library('sysprof-memory-@0@'.format(libsyspro
['sysprof-memory-collector.c'], ['sysprof-memory-collector.c'],
dependencies: preload_deps, dependencies: preload_deps,
install: true, install: true,
install_dir: get_option('libexecdir'), install_dir: get_option('libdir'),
) )
libsysprof_speedtrack_preload = shared_library('sysprof-speedtrack-@0@'.format(libsysprof_api_version), libsysprof_speedtrack_preload = shared_library('sysprof-speedtrack-@0@'.format(libsysprof_api_version),

View File

@ -23,6 +23,7 @@
#include "config.h" #include "config.h"
#include <dlfcn.h> #include <dlfcn.h>
#include <glib.h>
#include <sched.h> #include <sched.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/syscall.h> #include <sys/syscall.h>
@ -119,8 +120,6 @@ scratch_calloc (size_t nmemb,
static void static void
scratch_free (void *ptr) scratch_free (void *ptr)
{ {
if ((char *)ptr >= scratch.buf && (char *)ptr < scratch.buf + scratch.off)
return;
} }
static void static void
@ -198,8 +197,12 @@ realloc (void *ptr,
void void
free (void *ptr) free (void *ptr)
{ {
real_free (ptr); if G_LIKELY (ptr < (void *)scratch.buf ||
track_free (ptr); ptr >= (void *)&scratch.buf[sizeof scratch.buf])
{
real_free (ptr);
track_free (ptr);
}
} }
void * void *

View File

@ -24,6 +24,7 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <fcntl.h> #include <fcntl.h>
#include <glib.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>

View File

@ -0,0 +1,41 @@
/* sysprof-capture-gobject.h
*
* Copyright 2020 Endless Mobile, Inc.
*
* Author:
* - Philip Withnall <withnall@endlessm.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#if !defined (SYSPROF_INSIDE) && !defined (SYSPROF_COMPILATION)
# error "Only <sysprof.h> can be included directly."
#endif
#include <glib.h>
#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

View File

@ -20,10 +20,73 @@
#include "config.h" #include "config.h"
#include "sysprof-capture-gobject.h" #include <errno.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
#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 (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 (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) 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;
}

View File

@ -41,4 +41,18 @@ GType sysprof_capture_writer_get_type (void);
SYSPROF_AVAILABLE_IN_ALL SYSPROF_AVAILABLE_IN_ALL
GType sysprof_capture_cursor_get_type (void); 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 G_END_DECLS

View File

@ -33,6 +33,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "mapped-ring-buffer.h" #include "mapped-ring-buffer.h"
#include "mapped-ring-buffer-source.h"
#include "sysprof-control-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); g_array_set_clear_func (self->source_ids, remove_source_id);
} }
static gboolean static bool
event_frame_cb (gconstpointer data, event_frame_cb (const void *data,
gsize *length, size_t *length,
gpointer user_data) void *user_data)
{ {
const SysprofCaptureFrame *fr = data; const SysprofCaptureFrame *fr = data;
RingData *rd = user_data; RingData *rd = user_data;

View File

@ -74,8 +74,8 @@ sysprof_jitmap_symbol_resolver_load (SysprofSymbolResolver *resolver,
while (sysprof_capture_reader_peek_type (reader, &type)) while (sysprof_capture_reader_peek_type (reader, &type))
{ {
g_autoptr(GHashTable) jitmap = NULL; const SysprofCaptureJitmap *jitmap;
GHashTableIter iter; SysprofCaptureJitmapIter iter;
SysprofCaptureAddress addr; SysprofCaptureAddress addr;
const gchar *str; const gchar *str;
@ -89,8 +89,8 @@ sysprof_jitmap_symbol_resolver_load (SysprofSymbolResolver *resolver,
if (!(jitmap = sysprof_capture_reader_read_jitmap (reader))) if (!(jitmap = sysprof_capture_reader_read_jitmap (reader)))
return; return;
g_hash_table_iter_init (&iter, jitmap); sysprof_capture_jitmap_iter_init (&iter, jitmap);
while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str)) while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str))
g_hash_table_insert (self->jitmap, GSIZE_TO_POINTER (addr), g_strdup (str)); g_hash_table_insert (self->jitmap, GSIZE_TO_POINTER (addr), g_strdup (str));
} }
} }

View File

@ -24,6 +24,8 @@
# error "Only <sysprof.h> can be included directly." # error "Only <sysprof.h> can be included directly."
#endif #endif
#include <glib.h>
#include "sysprof-capture-types.h" #include "sysprof-capture-types.h"
G_BEGIN_DECLS G_BEGIN_DECLS

View File

@ -34,6 +34,7 @@
#include "sysprof-local-profiler.h" #include "sysprof-local-profiler.h"
#include "sysprof-platform.h" #include "sysprof-platform.h"
#include "sysprof-capture-autocleanups.h"
#include "sysprof-control-source.h" #include "sysprof-control-source.h"
#include "sysprof-gjs-source.h" #include "sysprof-gjs-source.h"
#include "sysprof-hostinfo-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->is_stopping == TRUE);
g_assert (priv->stopping->len == 0); 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++) 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; iface->stopped = sysprof_local_profiler_real_stopped;
} }
static gboolean static bool
find_profiler_meta_cb (const SysprofCaptureFrame *frame, find_profiler_meta_cb (const SysprofCaptureFrame *frame,
gpointer user_data) void *user_data)
{ {
const SysprofCaptureMetadata *meta = (const SysprofCaptureMetadata *)frame; const SysprofCaptureMetadata *meta = (const SysprofCaptureMetadata *)frame;
GKeyFile **keyfile = user_data; GKeyFile **keyfile = user_data;
@ -1005,7 +1007,7 @@ find_profiler_meta_cb (const SysprofCaptureFrame *frame,
return *keyfile == NULL; return *keyfile == NULL;
} }
return TRUE; return true;
} }
SysprofProfiler * SysprofProfiler *

View File

@ -20,6 +20,8 @@
#include "config.h" #include "config.h"
#include <glib.h>
#include "sysprof-map-lookaside.h" #include "sysprof-map-lookaside.h"
struct _SysprofMapLookaside struct _SysprofMapLookaside

View File

@ -20,6 +20,8 @@
#pragma once #pragma once
#include <glib.h>
#include "sysprof-capture-types.h" #include "sysprof-capture-types.h"
G_BEGIN_DECLS G_BEGIN_DECLS

View File

@ -24,6 +24,7 @@
#include <sysprof-capture.h> #include <sysprof-capture.h>
#include "sysprof-capture-autocleanups.h"
#include "sysprof-capture-symbol-resolver.h" #include "sysprof-capture-symbol-resolver.h"
#include "sysprof-elf-symbol-resolver.h" #include "sysprof-elf-symbol-resolver.h"
#include "sysprof-kernel-symbol-resolver.h" #include "sysprof-kernel-symbol-resolver.h"
@ -250,9 +251,9 @@ create_cursor (SysprofCaptureReader *reader)
return cursor; return cursor;
} }
static gboolean static bool
all_allocs_foreach_cb (const SysprofCaptureFrame *frame, all_allocs_foreach_cb (const SysprofCaptureFrame *frame,
gpointer user_data) void *user_data)
{ {
Generate *g = 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)); (gchar *)g_string_chunk_insert_const (g->symbols, cmdline));
} }
return TRUE; return true;
} }
/* Short-circuit if we don't care about this frame */ /* Short-circuit if we don't care about this frame */
if (!sysprof_selection_contains (g->selection, frame->time)) if (!sysprof_selection_contains (g->selection, frame->time))
return TRUE; return true;
if (frame->type == SYSPROF_CAPTURE_FRAME_ALLOCATION) if (frame->type == SYSPROF_CAPTURE_FRAME_ALLOCATION)
{ {
@ -360,7 +361,7 @@ all_allocs_foreach_cb (const SysprofCaptureFrame *frame,
} }
} }
return TRUE; return true;
} }
static gint static gint

View File

@ -450,12 +450,11 @@ sysprof_proxy_source_cat (SysprofProxySource *self,
g_assert (SYSPROF_IS_PROXY_SOURCE (self)); g_assert (SYSPROF_IS_PROXY_SOURCE (self));
g_assert (reader != NULL); g_assert (reader != NULL);
if (self->writer != NULL) if (self->writer != NULL &&
!sysprof_capture_writer_cat (self->writer, reader))
{ {
g_autoptr(GError) error = NULL; int errsv = errno;
g_warning ("Failed to join reader: %s", g_strerror (errsv));
if (!sysprof_capture_writer_cat (self->writer, reader, &error))
g_warning ("Failed to join reader: %s\n", error->message);
} }
} }
@ -464,14 +463,16 @@ sysprof_proxy_source_complete_monitor (SysprofProxySource *self,
Monitor *monitor) Monitor *monitor)
{ {
g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(GError) error = NULL;
g_assert (SYSPROF_IS_PROXY_SOURCE (self)); g_assert (SYSPROF_IS_PROXY_SOURCE (self));
g_assert (monitor != NULL); g_assert (monitor != NULL);
g_assert (monitor->self == self); g_assert (monitor->self == self);
if (!(reader = sysprof_capture_reader_new_from_fd (steal_fd (&monitor->fd), &error))) if (!(reader = sysprof_capture_reader_new_from_fd (steal_fd (&monitor->fd))))
g_warning ("Failed to load reader from peer FD: %s", error->message); {
int errsv = errno;
g_warning ("Failed to load reader from peer FD: %s", g_strerror (errsv));
}
else else
sysprof_proxy_source_cat (self, reader); sysprof_proxy_source_cat (self, reader);
} }

View File

@ -24,6 +24,7 @@
# error "Only <sysprof.h> can be included directly." # error "Only <sysprof.h> can be included directly."
#endif #endif
#include <glib.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>

View File

@ -25,6 +25,7 @@
#include <errno.h> #include <errno.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
#include "sysprof-capture-autocleanups.h"
#include "sysprof-platform.h" #include "sysprof-platform.h"
#include "sysprof-tracefd-source.h" #include "sysprof-tracefd-source.h"
@ -258,8 +259,9 @@ sysprof_tracefd_source_stop (SysprofSource *source)
{ {
g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(SysprofCaptureReader) reader = NULL;
if ((reader = sysprof_capture_reader_new_from_fd (priv->tracefd, 0))) /* FIXME: Error handling is ignored here */
sysprof_capture_writer_cat (priv->writer, reader, NULL); if ((reader = sysprof_capture_reader_new_from_fd (priv->tracefd)))
sysprof_capture_writer_cat (priv->writer, reader);
priv->tracefd = -1; priv->tracefd = -1;
} }

View File

@ -18,6 +18,7 @@
#pragma once #pragma once
#include <glib.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -26,6 +27,7 @@ G_BEGIN_DECLS
# include "sysprof-battery-source.h" # include "sysprof-battery-source.h"
# include "sysprof-callgraph-profile.h" # include "sysprof-callgraph-profile.h"
# include "sysprof-capture-autocleanups.h"
# include "sysprof-capture-gobject.h" # include "sysprof-capture-gobject.h"
# include "sysprof-capture-symbol-resolver.h" # include "sysprof-capture-symbol-resolver.h"
# include "sysprof-control-source.h" # include "sysprof-control-source.h"

View File

@ -134,9 +134,10 @@ main (gint argc,
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE); 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; return EXIT_FAILURE;
} }

View File

@ -205,9 +205,10 @@ main (gint argc,
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE); 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; return EXIT_FAILURE;
} }

View File

@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include <glib.h>
#include <stddef.h> #include <stddef.h>
#include <rax.h> #include <rax.h>
#include <sysprof.h> #include <sysprof.h>
@ -115,7 +116,6 @@ main (gint argc,
{ {
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const gchar *filename = argv[1]; const gchar *filename = argv[1];
g_autoptr(GError) error = NULL;
if (argc < 2) if (argc < 2)
{ {
@ -123,9 +123,10 @@ main (gint argc,
return EXIT_FAILURE; 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; return EXIT_FAILURE;
} }

View File

@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include <glib.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
static struct { static struct {
@ -140,7 +141,6 @@ main (gint argc,
{ {
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const gchar *filename = argv[1]; const gchar *filename = argv[1];
g_autoptr(GError) error = NULL;
if (argc < 2) if (argc < 2)
{ {
@ -148,9 +148,10 @@ main (gint argc,
return EXIT_FAILURE; 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; return EXIT_FAILURE;
} }

View File

@ -77,9 +77,10 @@ main (gint argc,
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE); 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; return EXIT_FAILURE;
} }

View File

@ -12,24 +12,29 @@ test_cflags = [
'-DSYSPROF_COMPILATION=1', '-DSYSPROF_COMPILATION=1',
] ]
test_capture_deps = [
dependency('glib-2.0'),
libsysprof_capture_dep,
]
test_capture = executable('test-capture', 'test-capture.c', test_capture = executable('test-capture', 'test-capture.c',
c_args: test_cflags, c_args: test_cflags,
dependencies: [libsysprof_capture_dep], dependencies: test_capture_deps,
) )
test_capture_cursor = executable('test-capture-cursor', 'test-capture-cursor.c', test_capture_cursor = executable('test-capture-cursor', 'test-capture-cursor.c',
c_args: test_cflags, 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', test_mapped_ring_buffer = executable('test-mapped-ring-buffer', 'test-mapped-ring-buffer.c',
c_args: test_cflags, c_args: test_cflags,
dependencies: [libsysprof_capture_dep], dependencies: test_capture_deps,
) )
find_temp_allocs = executable('find-temp-allocs', 'find-temp-allocs.c', find_temp_allocs = executable('find-temp-allocs', 'find-temp-allocs.c',
c_args: test_cflags, c_args: test_cflags,
dependencies: [libsysprof_capture_dep], dependencies: test_capture_deps,
) )
test('test-capture', test_capture, env: test_env) test('test-capture', test_capture, env: test_env)

View File

@ -21,6 +21,7 @@
#include "config.h" #include "config.h"
#include <cairo.h> #include <cairo.h>
#include <glib.h>
#include <stddef.h> #include <stddef.h>
#include <rax.h> #include <rax.h>
#include <sysprof.h> #include <sysprof.h>
@ -167,7 +168,6 @@ main (gint argc,
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const gchar *filename = argv[1]; const gchar *filename = argv[1];
g_autoptr(SysprofProfile) memprof = NULL; g_autoptr(SysprofProfile) memprof = NULL;
g_autoptr(GError) error = NULL;
if (argc < 2) if (argc < 2)
{ {
@ -177,9 +177,10 @@ main (gint argc,
main_loop = g_main_loop_new (NULL, FALSE); 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; return EXIT_FAILURE;
} }

View File

@ -1,4 +1,5 @@
#include <fcntl.h> #include <fcntl.h>
#include <glib.h>
#include <sysprof.h> #include <sysprof.h>
#include "sysprof-platform.h" #include "sysprof-platform.h"
@ -10,7 +11,6 @@ main (gint argc,
{ {
g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(SysprofSymbolResolver) resolver = NULL; g_autoptr(SysprofSymbolResolver) resolver = NULL;
g_autoptr(GError) error = NULL;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
if (argc != 2) if (argc != 2)
@ -19,9 +19,10 @@ main (gint argc,
return 1; 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; return 1;
} }

View File

@ -1,4 +1,5 @@
#include <fcntl.h> #include <fcntl.h>
#include <glib.h>
#include <sysprof.h> #include <sysprof.h>
#include "sysprof-platform.h" #include "sysprof-platform.h"
@ -91,9 +92,10 @@ main (gint argc,
return 1; 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; return 1;
} }

View File

@ -18,16 +18,17 @@
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
#include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
static gboolean static bool
increment (const SysprofCaptureFrame *frame, increment (const SysprofCaptureFrame *frame,
gpointer user_data) void *user_data)
{ {
gint *count= user_data; gint *count= user_data;
(*count)++; (*count)++;
return TRUE; return true;
} }
static void static void
@ -36,20 +37,18 @@ test_cursor_basic (void)
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
SysprofCaptureWriter *writer; SysprofCaptureWriter *writer;
SysprofCaptureCursor *cursor; SysprofCaptureCursor *cursor;
GError *error = NULL;
gint64 t = SYSPROF_CAPTURE_CURRENT_TIME; gint64 t = SYSPROF_CAPTURE_CURRENT_TIME;
guint i; guint i;
gint r; gint r;
gint count = 0; gint count = 0;
writer = sysprof_capture_writer_new ("capture-cursor-file", 0); writer = sysprof_capture_writer_new ("capture-cursor-file", 0);
g_assert (writer != NULL); g_assert_nonnull (writer);
sysprof_capture_writer_flush (writer); sysprof_capture_writer_flush (writer);
reader = sysprof_capture_reader_new ("capture-cursor-file", &error); reader = sysprof_capture_reader_new ("capture-cursor-file");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
for (i = 0; i < 100; i++) for (i = 0; i < 100; i++)
{ {

View File

@ -37,7 +37,7 @@ main (gint argc,
return 1; 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); g_printerr ("Failed to load reader: %s\n", error->message);
return 1; return 1;

View File

@ -21,6 +21,7 @@
#include "config.h" #include "config.h"
#include <fcntl.h> #include <fcntl.h>
#include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <string.h> #include <string.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
@ -31,15 +32,16 @@
#include "sysprof-capture-util-private.h" #include "sysprof-capture-util-private.h"
static void static void
copy_into (GHashTable *src, copy_into (const SysprofCaptureJitmap *src,
GHashTable *dst) GHashTable *dst)
{ {
GHashTableIter iter; SysprofCaptureJitmapIter iter;
gpointer k, v; SysprofCaptureAddress addr;
const char *name;
g_hash_table_iter_init (&iter, src); sysprof_capture_jitmap_iter_init (&iter, src);
while (g_hash_table_iter_next (&iter, &k, &v)) while (sysprof_capture_jitmap_iter_next (&iter, &addr, &name))
g_hash_table_insert (dst, k, g_strdup ((gchar *)v)); g_hash_table_insert (dst, GSIZE_TO_POINTER (addr), g_strdup (name));
} }
static void static void
@ -59,9 +61,8 @@ test_reader_basic (void)
sysprof_capture_writer_flush (writer); sysprof_capture_writer_flush (writer);
reader = sysprof_capture_reader_new ("capture-file", &error); reader = sysprof_capture_reader_new ("capture-file");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
for (i = 0; i < 100; i++) for (i = 0; i < 100; i++)
{ {
@ -317,19 +318,19 @@ test_reader_basic (void)
for (;;) for (;;)
{ {
SysprofCaptureFrameType type = -1; SysprofCaptureFrameType type = -1;
g_autoptr(GHashTable) ret = NULL; const SysprofCaptureJitmap *jitmap;
if (sysprof_capture_reader_peek_type (reader, &type)) if (sysprof_capture_reader_peek_type (reader, &type))
g_assert_cmpint (type, ==, SYSPROF_CAPTURE_FRAME_JITMAP); g_assert_cmpint (type, ==, SYSPROF_CAPTURE_FRAME_JITMAP);
else else
break; break;
ret = sysprof_capture_reader_read_jitmap (reader); jitmap = sysprof_capture_reader_read_jitmap (reader);
g_assert (ret != NULL); 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); g_assert_cmpint (1000, ==, i);
@ -398,9 +399,8 @@ test_reader_basic (void)
g_assert_not_reached (); g_assert_not_reached ();
} }
r = sysprof_capture_writer_save_as (writer, "capture-file.bak", &error); r = sysprof_capture_writer_save_as (writer, "capture-file.bak");
g_assert_no_error (error); g_assert_true (r);
g_assert (r);
g_assert (g_file_test ("capture-file.bak", G_FILE_TEST_IS_REGULAR)); g_assert (g_file_test ("capture-file.bak", G_FILE_TEST_IS_REGULAR));
/* make sure contents are equal */ /* make sure contents are equal */
@ -428,9 +428,8 @@ test_reader_basic (void)
g_clear_pointer (&writer, sysprof_capture_writer_unref); g_clear_pointer (&writer, sysprof_capture_writer_unref);
g_clear_pointer (&reader, sysprof_capture_reader_unref); g_clear_pointer (&reader, sysprof_capture_reader_unref);
reader = sysprof_capture_reader_new ("capture-file.bak", &error); reader = sysprof_capture_reader_new ("capture-file.bak");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
@ -462,7 +461,6 @@ test_writer_splice (void)
SysprofCaptureWriter *writer2; SysprofCaptureWriter *writer2;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
GError *error = NULL;
guint i; guint i;
gint r; gint r;
@ -472,16 +470,14 @@ test_writer_splice (void)
for (i = 0; i < 1000; i++) for (i = 0; i < 1000; i++)
sysprof_capture_writer_add_timestamp (writer1, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1); sysprof_capture_writer_add_timestamp (writer1, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1);
r = sysprof_capture_writer_splice (writer1, writer2, &error); r = sysprof_capture_writer_splice (writer1, writer2);
g_assert_no_error (error); g_assert_true (r);
g_assert (r == TRUE);
g_clear_pointer (&writer1, sysprof_capture_writer_unref); g_clear_pointer (&writer1, sysprof_capture_writer_unref);
g_clear_pointer (&writer2, sysprof_capture_writer_unref); g_clear_pointer (&writer2, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("writer2.syscap", &error); reader = sysprof_capture_reader_new ("writer2.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
for (i = 0; i < 1000; i++) for (i = 0; i < 1000; i++)
{ {
@ -509,7 +505,6 @@ test_reader_splice (void)
SysprofCaptureWriter *writer2; SysprofCaptureWriter *writer2;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
GError *error = NULL;
guint i; guint i;
guint count; guint count;
gint r; gint r;
@ -525,9 +520,8 @@ test_reader_splice (void)
g_clear_pointer (&writer1, sysprof_capture_writer_unref); g_clear_pointer (&writer1, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("writer1.syscap", &error); reader = sysprof_capture_reader_new ("writer1.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
/* advance to the end of the reader to non-start boundary for fd */ /* 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); r = sysprof_capture_reader_peek_type (reader, &type);
g_assert_cmpint (r, ==, FALSE); g_assert_cmpint (r, ==, FALSE);
r = sysprof_capture_reader_splice (reader, writer2, &error); r = sysprof_capture_reader_splice (reader, writer2);
g_assert_no_error (error); g_assert_true (r);
g_assert_cmpint (r, ==, TRUE);
g_clear_pointer (&reader, sysprof_capture_reader_unref); g_clear_pointer (&reader, sysprof_capture_reader_unref);
g_clear_pointer (&writer2, sysprof_capture_writer_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++) for (i = 0; i < 1000; i++)
{ {
@ -568,19 +562,16 @@ test_reader_splice (void)
g_clear_pointer (&reader, sysprof_capture_reader_unref); g_clear_pointer (&reader, sysprof_capture_reader_unref);
reader = sysprof_capture_reader_new ("writer2.syscap", &error); reader = sysprof_capture_reader_new ("writer2.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
r = sysprof_capture_reader_save_as (reader, "writer3.syscap", &error); r = sysprof_capture_reader_save_as (reader, "writer3.syscap");
g_assert_no_error (error); g_assert_true (r);
g_assert_cmpint (r, ==, TRUE);
g_clear_pointer (&reader, sysprof_capture_reader_unref); g_clear_pointer (&reader, sysprof_capture_reader_unref);
reader = sysprof_capture_reader_new ("writer3.syscap", &error); reader = sysprof_capture_reader_new ("writer3.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
count = 0; count = 0;
while (sysprof_capture_reader_skip (reader)) while (sysprof_capture_reader_skip (reader))
@ -601,7 +592,6 @@ test_reader_writer_log (void)
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const SysprofCaptureLog *log; const SysprofCaptureLog *log;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
GError *error = NULL;
gint r; gint r;
writer = sysprof_capture_writer_new ("log1.syscap", 0); 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); g_clear_pointer (&writer, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("log1.syscap", &error); reader = sysprof_capture_reader_new ("log1.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
log = sysprof_capture_reader_read_log (reader); log = sysprof_capture_reader_read_log (reader);
g_assert_nonnull (log); g_assert_nonnull (log);
@ -655,7 +644,6 @@ test_reader_writer_mark (void)
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const SysprofCaptureMark *mark; const SysprofCaptureMark *mark;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
GError *error = NULL;
gint r; gint r;
writer = sysprof_capture_writer_new ("mark1.syscap", 0); 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); g_clear_pointer (&writer, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("mark1.syscap", &error); reader = sysprof_capture_reader_new ("mark1.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
mark = sysprof_capture_reader_read_mark (reader); mark = sysprof_capture_reader_read_mark (reader);
g_assert_nonnull (mark); g_assert_nonnull (mark);
@ -702,7 +689,6 @@ test_reader_writer_metadata (void)
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const SysprofCaptureMetadata *metadata; const SysprofCaptureMetadata *metadata;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
GError *error = NULL;
gint r; gint r;
writer = sysprof_capture_writer_new ("metadata1.syscap", 0); 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); g_clear_pointer (&writer, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("metadata1.syscap", &error); reader = sysprof_capture_reader_new ("metadata1.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
metadata = sysprof_capture_reader_read_metadata (reader); metadata = sysprof_capture_reader_read_metadata (reader);
g_assert_nonnull (metadata); g_assert_nonnull (metadata);
@ -746,11 +731,10 @@ test_reader_writer_file (void)
{ {
g_autofree gchar *data = NULL; g_autofree gchar *data = NULL;
GByteArray *buf = g_byte_array_new (); GByteArray *buf = g_byte_array_new ();
g_auto(GStrv) files = NULL; g_autofree const gchar **files = NULL;
SysprofCaptureWriter *writer; SysprofCaptureWriter *writer;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
SysprofCaptureFrameType type; SysprofCaptureFrameType type;
GError *error = NULL;
gsize data_len; gsize data_len;
guint count = 0; guint count = 0;
gint fd; gint fd;
@ -773,9 +757,8 @@ test_reader_writer_file (void)
g_clear_pointer (&writer, sysprof_capture_writer_unref); g_clear_pointer (&writer, sysprof_capture_writer_unref);
reader = sysprof_capture_reader_new ("file1.syscap", &error); reader = sysprof_capture_reader_new ("file1.syscap");
g_assert_no_error (error); g_assert_nonnull (reader);
g_assert (reader != NULL);
while (count < 2) while (count < 2)
{ {
@ -829,7 +812,6 @@ test_reader_writer_cat_jitmap (void)
SysprofCaptureWriter *res; SysprofCaptureWriter *res;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
const SysprofCaptureSample *sample; const SysprofCaptureSample *sample;
GError *error = NULL;
SysprofCaptureAddress addrs[20]; SysprofCaptureAddress addrs[20];
gboolean r; gboolean r;
@ -865,28 +847,23 @@ test_reader_writer_cat_jitmap (void)
addrs, addrs,
G_N_ELEMENTS (addrs)); G_N_ELEMENTS (addrs));
reader = sysprof_capture_writer_create_reader (writer1, &error); reader = sysprof_capture_writer_create_reader (writer1);
g_assert_no_error (error);
g_assert_nonnull (reader); g_assert_nonnull (reader);
r = sysprof_capture_writer_cat (res, reader, &error); r = sysprof_capture_writer_cat (res, reader);
g_assert_no_error (error);
g_assert_true (r); g_assert_true (r);
sysprof_capture_writer_unref (writer1); sysprof_capture_writer_unref (writer1);
sysprof_capture_reader_unref (reader); sysprof_capture_reader_unref (reader);
reader = sysprof_capture_writer_create_reader (writer2, &error); reader = sysprof_capture_writer_create_reader (writer2);
g_assert_no_error (error);
g_assert_nonnull (reader); g_assert_nonnull (reader);
r = sysprof_capture_writer_cat (res, reader, &error); r = sysprof_capture_writer_cat (res, reader);
g_assert_no_error (error);
g_assert_true (r); g_assert_true (r);
sysprof_capture_writer_unref (writer2); sysprof_capture_writer_unref (writer2);
sysprof_capture_reader_unref (reader); sysprof_capture_reader_unref (reader);
reader = sysprof_capture_writer_create_reader (res, &error); reader = sysprof_capture_writer_create_reader (res);
g_assert_no_error (error);
g_assert_nonnull (reader); 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); sample = sysprof_capture_reader_read_sample (reader);
g_assert_cmpint (sample->frame.pid, ==, getpid ()); g_assert_cmpint (sample->frame.pid, ==, getpid ());
g_assert_cmpint (sample->n_addrs, ==, G_N_ELEMENTS (addrs)); g_assert_cmpint (sample->n_addrs, ==, G_N_ELEMENTS (addrs));
@ -905,7 +882,6 @@ test_writer_memory_alloc_free (void)
{ {
SysprofCaptureWriter *writer; SysprofCaptureWriter *writer;
SysprofCaptureReader *reader; SysprofCaptureReader *reader;
GError *error = NULL;
SysprofCaptureAddress addrs[20] = { SysprofCaptureAddress addrs[20] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 11, 12, 13, 14, 15, 16, 17, 18, 19,
@ -930,8 +906,7 @@ test_writer_memory_alloc_free (void)
sysprof_capture_writer_flush (writer); sysprof_capture_writer_flush (writer);
reader = sysprof_capture_writer_create_reader (writer, &error); reader = sysprof_capture_writer_create_reader (writer);
g_assert_no_error (error);
g_assert_nonnull (reader); g_assert_nonnull (reader);
for (guint i = 0; i < 20; i++) for (guint i = 0; i < 20; i++)

View File

@ -1,13 +1,14 @@
#include "mapped-ring-buffer.h" #include "mapped-ring-buffer.h"
#include <glib.h>
#include <stdint.h> #include <stdint.h>
static gsize real_count; static gsize real_count;
static gboolean static bool
drain_nth_cb (gconstpointer data, drain_nth_cb (const void *data,
gsize *len, size_t *len,
gpointer user_data) void *user_data)
{ {
const gint64 *v64 = data; const gint64 *v64 = data;
g_assert_cmpint (*len, >=, 8); g_assert_cmpint (*len, >=, 8);
@ -16,10 +17,10 @@ drain_nth_cb (gconstpointer data,
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
} }
static gboolean static bool
drain_count_cb (gconstpointer data, drain_count_cb (const void *data,
gsize *len, size_t *len,
gpointer user_data) void *user_data)
{ {
const gint64 *v64 = data; const gint64 *v64 = data;
g_assert_cmpint (*len, >=, 8); g_assert_cmpint (*len, >=, 8);
@ -92,10 +93,10 @@ typedef struct
gint64 done; gint64 done;
} ThreadedMessage; } ThreadedMessage;
static gboolean static bool
handle_msg (gconstpointer data, handle_msg (const void *data,
gsize *length, size_t *length,
gpointer user_data) void *user_data)
{ {
const ThreadedMessage *msg = data; const ThreadedMessage *msg = data;
gboolean *done = user_data; gboolean *done = user_data;

View File

@ -1,3 +1,4 @@
#include <glib.h>
#include <sysprof.h> #include <sysprof.h>
static const SysprofCaptureSample * 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_jitmap_symbol_resolver_new ());
g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ()); g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ());
if (!(reader = sysprof_capture_reader_new (filename, &error))) if (!(reader = sysprof_capture_reader_new (filename)))
g_error ("%s", error->message); {
int errsv = errno;
g_error ("%s", g_strerror (errsv));
return 1;
}
for (guint r = 0; r < resolvers->len; r++) for (guint r = 0; r < resolvers->len; r++)
{ {

View File

@ -24,9 +24,11 @@
#include <sysprof-capture.h> #include <sysprof-capture.h>
#include <unistd.h> #include <unistd.h>
static gboolean #include "../libsysprof/sysprof-capture-autocleanups.h"
static bool
foreach_cb (const SysprofCaptureFrame *frame, foreach_cb (const SysprofCaptureFrame *frame,
gpointer user_data) void *user_data)
{ {
const SysprofCaptureSample *sample = (SysprofCaptureSample *)frame; const SysprofCaptureSample *sample = (SysprofCaptureSample *)frame;
GHashTable *seen = user_data; GHashTable *seen = user_data;
@ -36,7 +38,7 @@ foreach_cb (const SysprofCaptureFrame *frame,
GINT_TO_POINTER (sample->tid), GINT_TO_POINTER (sample->tid),
GINT_TO_POINTER (frame->pid)); GINT_TO_POINTER (frame->pid));
return TRUE; return true;
} }
gint gint
@ -57,9 +59,9 @@ main (gint argc,
} }
if (g_strcmp0 ("-", argv[1]) == 0) 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 else
reader = sysprof_capture_reader_new (argv[1], 0); reader = sysprof_capture_reader_new (argv[1]);
if (reader == NULL) if (reader == NULL)
{ {

View File

@ -1,11 +1,15 @@
tools_deps = [ tools_deps = [
dependency('glib-2.0'),
libsysprof_capture_dep, libsysprof_capture_dep,
] ]
tools_cflags = [ '-DSYSPROF_COMPILATION ']
if get_option('libsysprof') and host_machine.system() == 'linux' if get_option('libsysprof') and host_machine.system() == 'linux'
polkit_agent_dep = dependency('polkit-agent-1') polkit_agent_dep = dependency('polkit-agent-1')
sysprof_cli = executable('sysprof-cli', 'sysprof-cli.c', sysprof_cli = executable('sysprof-cli', 'sysprof-cli.c',
dependencies: tools_deps + [libsysprof_dep, polkit_dep, polkit_agent_dep], dependencies: tools_deps + [libsysprof_dep, polkit_dep, polkit_agent_dep],
c_args: tools_cflags,
install_dir: get_option('bindir'), install_dir: get_option('bindir'),
install: true, install: true,
) )
@ -13,21 +17,25 @@ endif
sysprof_cat = executable('sysprof-cat', 'sysprof-cat.c', sysprof_cat = executable('sysprof-cat', 'sysprof-cat.c',
dependencies: tools_deps, dependencies: tools_deps,
c_args: tools_cflags,
install: false, install: false,
) )
sysprof_dump = executable('sysprof-dump', 'sysprof-dump.c', sysprof_dump = executable('sysprof-dump', 'sysprof-dump.c',
dependencies: tools_deps, dependencies: tools_deps,
c_args: tools_cflags,
install: false, install: false,
) )
sysprof_profiler_ctl = executable('sysprof-profiler-ctl', sysprof_profiler_ctl = executable('sysprof-profiler-ctl',
[ 'sysprof-profiler-ctl.c', ipc_profiler_src ], [ 'sysprof-profiler-ctl.c', ipc_profiler_src ],
dependencies: [ tools_deps, gio_unix_dep ], dependencies: [ tools_deps, gio_unix_dep ],
c_args: tools_cflags,
install: false, install: false,
) )
list_threads = executable('list-threads', ['list-threads.c'], list_threads = executable('list-threads', ['list-threads.c'],
dependencies: [ tools_deps ], dependencies: [ tools_deps ],
c_args: tools_cflags,
install: false, install: false,
) )

View File

@ -23,11 +23,13 @@
#include "config.h" #include "config.h"
#include <errno.h> #include <errno.h>
#include <glib.h>
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
#include <unistd.h> #include <unistd.h>
#include "../libsysprof/sysprof-capture-autocleanups.h"
#include "sysprof-capture-util-private.h" #include "sysprof-capture-util-private.h"
gint gint
@ -71,17 +73,19 @@ main (gint argc,
g_autoptr(SysprofCaptureReader) reader = NULL; g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(GError) error = 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", g_printerr ("Failed to create reader for \"%s\": %s\n",
argv[i], error->message); argv[i], g_strerror (errsv));
return EXIT_FAILURE; 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", g_printerr ("Failed to join \"%s\": %s\n",
argv[i], error->message); argv[i], g_strerror (errsv));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }

View File

@ -134,19 +134,20 @@ merge_files (gint argc,
for (guint i = 1; i < argc; i++) for (guint i = 1; i < argc; i++)
{ {
g_autoptr(SysprofCaptureReader) reader = NULL; 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", g_printerr ("Failed to create reader for \"%s\": %s\n",
argv[i], error->message); argv[i], g_strerror (errsv));
return EXIT_FAILURE; 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", g_printerr ("Failed to join \"%s\": %s\n",
argv[i], error->message); argv[i], g_strerror (errsv));
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }

View File

@ -20,6 +20,7 @@
#include "config.h" #include "config.h"
#include <glib.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sysprof-capture.h> #include <sysprof-capture.h>
@ -55,13 +56,18 @@ main (gint argc,
return EXIT_FAILURE; 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) 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]); g_print ("%s\n", files[i]);
return EXIT_SUCCESS; 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 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))) #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); begin_time = sysprof_capture_reader_get_start_time (reader);
end_time = sysprof_capture_reader_get_end_time (reader); end_time = sysprof_capture_reader_get_end_time (reader);
@ -116,18 +116,18 @@ main (gint argc,
case SYSPROF_CAPTURE_FRAME_JITMAP: case SYSPROF_CAPTURE_FRAME_JITMAP:
{ {
g_autoptr(GHashTable) ret = sysprof_capture_reader_read_jitmap (reader); const SysprofCaptureJitmap *jitmap = sysprof_capture_reader_read_jitmap (reader);
GHashTableIter iter; SysprofCaptureJitmapIter iter;
SysprofCaptureAddress addr; SysprofCaptureAddress addr;
const gchar *str; const gchar *str;
if (ret == NULL) if (jitmap == NULL)
return EXIT_FAILURE; return EXIT_FAILURE;
g_print ("JITMAP:\n"); g_print ("JITMAP:\n");
g_hash_table_iter_init (&iter, ret); sysprof_capture_jitmap_iter_init (&iter, jitmap);
while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str)) while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str))
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " : %s\n", addr, str); g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " : %s\n", addr, str);
break; break;