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>
#endif
#include <glib.h>
#include <signal.h>
#include <sysprof-capture.h>
#include <unistd.h>

View File

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

View File

@ -18,21 +18,23 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define G_LOG_DOMAIN "mapped-ring-buffer"
#include "config.h"
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include "sysprof-capture-util-private.h"
#include "sysprof-macros-internal.h"
#include "sysprof-platform.h"
#include "mapped-ring-buffer.h"
#define DEFAULT_N_PAGES 32
#define BUFFER_MAX_SIZE ((G_MAXUINT32/2)-_sysprof_getpagesize())
#define BUFFER_MAX_SIZE ((UINT32_MAX/2)-_sysprof_getpagesize())
enum {
MODE_READER = 1,
@ -47,13 +49,13 @@ enum {
*/
typedef struct _MappedRingHeader
{
guint32 head;
guint32 tail;
guint32 offset;
guint32 size;
uint32_t head;
uint32_t tail;
uint32_t offset;
uint32_t size;
} MappedRingHeader;
G_STATIC_ASSERT (sizeof (MappedRingHeader) == 16);
static_assert (sizeof (MappedRingHeader) == 16, "MappedRingHeader changed size");
/*
* MappedRingBuffer is used to wrap both the reader and writer
@ -61,12 +63,12 @@ G_STATIC_ASSERT (sizeof (MappedRingHeader) == 16);
*/
struct _MappedRingBuffer
{
volatile gint ref_count;
volatile int ref_count;
int mode;
int fd;
void *map;
gsize body_size;
gsize page_size;
size_t body_size;
size_t page_size;
};
static inline MappedRingHeader *
@ -75,19 +77,19 @@ get_header (MappedRingBuffer *self)
return (MappedRingHeader *)self->map;
}
static inline gpointer
static inline void *
get_body_at_pos (MappedRingBuffer *self,
gsize pos)
size_t pos)
{
g_assert (pos < (self->body_size + self->body_size));
assert (pos < (self->body_size + self->body_size));
return (guint8 *)self->map + self->page_size + pos;
return (uint8_t *)self->map + self->page_size + pos;
}
static gpointer
map_head_and_body_twice (int fd,
gsize head_size,
gsize body_size)
static void *
map_head_and_body_twice (int fd,
size_t head_size,
size_t body_size)
{
void *map;
void *second;
@ -118,7 +120,7 @@ map_head_and_body_twice (int fd,
* By mmap()'ing over the old region, the previous region is automatically
* munmap()'d for us.
*/
second = mmap ((guint8 *)map + head_size + body_size,
second = mmap ((uint8_t *)map + head_size + body_size,
body_size,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED,
@ -131,7 +133,7 @@ map_head_and_body_twice (int fd,
return NULL;
}
g_assert (second == (gpointer)((guint8 *)map + head_size + body_size));
assert (second == (void *)((uint8_t *)map + head_size + body_size));
return map;
}
@ -157,16 +159,16 @@ map_head_and_body_twice (int fd,
* Returns: (transfer full): a #MappedRingBuffer
*/
MappedRingBuffer *
mapped_ring_buffer_new_reader (gsize buffer_size)
mapped_ring_buffer_new_reader (size_t buffer_size)
{
MappedRingBuffer *self;
MappedRingHeader *header;
gsize page_size;
size_t page_size;
void *map;
int fd;
g_return_val_if_fail ((buffer_size % _sysprof_getpagesize ()) == 0, NULL);
g_return_val_if_fail (buffer_size < BUFFER_MAX_SIZE, NULL);
assert ((buffer_size % _sysprof_getpagesize ()) == 0);
assert (buffer_size < BUFFER_MAX_SIZE);
page_size = _sysprof_getpagesize ();
@ -200,7 +202,10 @@ mapped_ring_buffer_new_reader (gsize buffer_size)
header->offset = page_size;
header->size = buffer_size - page_size;
self = g_slice_new0 (MappedRingBuffer);
self = sysprof_malloc0 (sizeof (MappedRingBuffer));
if (self == NULL)
return NULL;
self->ref_count = 1;
self->mode = MODE_READER;
self->body_size = buffer_size - page_size;
@ -208,11 +213,11 @@ mapped_ring_buffer_new_reader (gsize buffer_size)
self->map = map;
self->page_size = page_size;
return g_steal_pointer (&self);
return sysprof_steal_pointer (&self);
}
MappedRingBuffer *
mapped_ring_buffer_new_readwrite (gsize buffer_size)
mapped_ring_buffer_new_readwrite (size_t buffer_size)
{
MappedRingBuffer *self;
@ -234,50 +239,50 @@ mapped_ring_buffer_new_readwrite (gsize buffer_size)
* Returns: (transfer full) (nullable): a new #MappedRingBuffer
*/
MappedRingBuffer *
mapped_ring_buffer_new_writer (gint fd)
mapped_ring_buffer_new_writer (int fd)
{
MappedRingBuffer *self;
MappedRingHeader *header;
gssize buffer_size;
gsize page_size;
ssize_t buffer_size;
size_t page_size;
void *map;
g_return_val_if_fail (fd > -1, NULL);
assert (fd > -1);
page_size = _sysprof_getpagesize ();
/* Make our own copy of the FD */
if ((fd = dup (fd)) < 0)
{
g_printerr ("Failed to dup() fd, cannot continue\n");
fprintf (stderr, "Failed to dup() fd, cannot continue\n");
return NULL;
}
/* Seek to end to get buffer size */
if ((buffer_size = lseek (fd, 0, SEEK_END)) < 0)
{
g_printerr ("Failed to seek to end of file. Cannot determine buffer size.\n");
fprintf (stderr, "Failed to seek to end of file. Cannot determine buffer size.\n");
return NULL;
}
/* Ensure non-zero sized buffer */
if (buffer_size < (page_size + page_size))
{
g_printerr ("Buffer is too small, cannot continue.\n");
fprintf (stderr, "Buffer is too small, cannot continue.\n");
return NULL;
}
/* Make sure it is less than our max size */
if ((buffer_size - page_size) > BUFFER_MAX_SIZE)
{
g_printerr ("Buffer is too large, cannot continue.\n");
fprintf (stderr, "Buffer is too large, cannot continue.\n");
return NULL;
}
/* Ensure we have page-aligned buffer */
if ((buffer_size % page_size) != 0)
{
g_printerr ("Invalid buffer size, not page aligned.\n");
fprintf (stderr, "Invalid buffer size, not page aligned.\n");
return NULL;
}
@ -298,7 +303,14 @@ mapped_ring_buffer_new_writer (gint fd)
return NULL;
}
self = g_slice_new0 (MappedRingBuffer);
self = sysprof_malloc0 (sizeof (MappedRingBuffer));
if (self == NULL)
{
munmap (map, page_size + ((buffer_size - page_size) * 2));
close (fd);
return NULL;
}
self->ref_count = 1;
self->mode = MODE_WRITER;
self->fd = fd;
@ -306,7 +318,7 @@ mapped_ring_buffer_new_writer (gint fd)
self->map = map;
self->page_size = page_size;
return g_steal_pointer (&self);
return sysprof_steal_pointer (&self);
}
static void
@ -328,28 +340,28 @@ mapped_ring_buffer_finalize (MappedRingBuffer *self)
void
mapped_ring_buffer_unref (MappedRingBuffer *self)
{
g_return_if_fail (self != NULL);
g_return_if_fail (self->ref_count > 0);
assert (self != NULL);
assert (self->ref_count > 0);
if (g_atomic_int_dec_and_test (&self->ref_count))
if (__atomic_fetch_sub (&self->ref_count, 1, __ATOMIC_SEQ_CST) == 1)
mapped_ring_buffer_finalize (self);
}
MappedRingBuffer *
mapped_ring_buffer_ref (MappedRingBuffer *self)
{
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (self->ref_count > 0, NULL);
assert (self != NULL);
assert (self->ref_count > 0);
g_atomic_int_inc (&self->ref_count);
__atomic_fetch_add (&self->ref_count, 1, __ATOMIC_SEQ_CST);
return self;
}
gint
int
mapped_ring_buffer_get_fd (MappedRingBuffer *self)
{
g_return_val_if_fail (self != NULL, -1);
assert (self != NULL);
return self->fd;
}
@ -377,23 +389,23 @@ mapped_ring_buffer_get_fd (MappedRingBuffer *self)
* Returns: (nullable): a pointer to data of at least @length bytes
* or %NULL if there is not enough space.
*/
gpointer
void *
mapped_ring_buffer_allocate (MappedRingBuffer *self,
gsize length)
size_t length)
{
MappedRingHeader *header;
gsize headpos;
gsize tailpos;
uint32_t headpos;
uint32_t tailpos;
g_return_val_if_fail (self != NULL, NULL);
g_return_val_if_fail (self->mode & MODE_WRITER, NULL);
g_return_val_if_fail (length > 0, NULL);
g_return_val_if_fail (length < self->body_size, NULL);
g_return_val_if_fail ((length & 0x7) == 0, NULL);
assert (self != NULL);
assert (self->mode & MODE_WRITER);
assert (length > 0);
assert (length < self->body_size);
assert ((length & 0x7) == 0);
header = get_header (self);
headpos = g_atomic_int_get (&header->head);
tailpos = g_atomic_int_get (&header->tail);
__atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST);
__atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST);
/* We need to check that there is enough space for @length at the
* current position in the write buffer. We cannot fully catch up
@ -436,16 +448,16 @@ mapped_ring_buffer_allocate (MappedRingBuffer *self,
*/
void
mapped_ring_buffer_advance (MappedRingBuffer *self,
gsize length)
size_t length)
{
MappedRingHeader *header;
guint32 tail;
uint32_t tail;
g_return_if_fail (self != NULL);
g_return_if_fail (self->mode & MODE_WRITER);
g_return_if_fail (length > 0);
g_return_if_fail (length < self->body_size);
g_return_if_fail ((length & 0x7) == 0);
assert (self != NULL);
assert (self->mode & MODE_WRITER);
assert (length > 0);
assert (length < self->body_size);
assert ((length & 0x7) == 0);
header = get_header (self);
tail = header->tail;
@ -460,7 +472,7 @@ mapped_ring_buffer_advance (MappedRingBuffer *self,
* we just update the position as the only way the head could have
* moved is forward.
*/
g_atomic_int_set (&header->tail, tail);
__atomic_store (&header->tail, &tail, __ATOMIC_SEQ_CST);
}
/**
@ -477,28 +489,28 @@ mapped_ring_buffer_advance (MappedRingBuffer *self,
* Returns: %TRUE if the buffer was drained, %FALSE if @callback prematurely
* returned while draining.
*/
gboolean
bool
mapped_ring_buffer_drain (MappedRingBuffer *self,
MappedRingBufferCallback callback,
gpointer user_data)
void *user_data)
{
MappedRingHeader *header;
gsize headpos;
gsize tailpos;
uint32_t headpos;
uint32_t tailpos;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (self->mode & MODE_READER, FALSE);
g_return_val_if_fail (callback != NULL, FALSE);
assert (self != NULL);
assert (self->mode & MODE_READER);
assert (callback != NULL);
header = get_header (self);
headpos = g_atomic_int_get (&header->head);
tailpos = g_atomic_int_get (&header->tail);
__atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST);
__atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST);
g_assert (headpos < self->body_size);
g_assert (tailpos < self->body_size);
assert (headpos < self->body_size);
assert (tailpos < self->body_size);
if (headpos == tailpos)
return TRUE;
return true;
/* If head needs to wrap around to get to tail, we can just rely on
* our double mapping instead actually manually wrapping/copying data.
@ -506,131 +518,56 @@ mapped_ring_buffer_drain (MappedRingBuffer *self,
if (tailpos < headpos)
tailpos += self->body_size;
g_assert (headpos < tailpos);
assert (headpos < tailpos);
while (headpos < tailpos)
{
gconstpointer data = get_body_at_pos (self, headpos);
gsize len = tailpos - headpos;
const void *data = get_body_at_pos (self, headpos);
size_t len = tailpos - headpos;
uint32_t new_headpos;
if (!callback (data, &len, user_data))
return FALSE;
return false;
if (len > (tailpos - headpos))
return FALSE;
return false;
headpos += len;
if (headpos >= self->body_size)
g_atomic_int_set (&header->head, headpos - self->body_size);
new_headpos = headpos - self->body_size;
else
g_atomic_int_set (&header->head, headpos);
new_headpos = headpos;
__atomic_store (&header->head, &new_headpos, __ATOMIC_SEQ_CST);
}
return TRUE;
return true;
}
typedef struct _MappedRingSource
/**
* mapped_ring_buffer_is_empty:
* @self: a #MappedRingBuffer
*
* Checks whether the ring buffer is currently empty.
*
* This should only be called by a reader created with
* mapped_ring_buffer_new_reader().
*
* Returns: %TRUE if the buffer is empty, %FALSE otherwise
*/
bool
mapped_ring_buffer_is_empty (MappedRingBuffer *self)
{
GSource source;
MappedRingBuffer *self;
} MappedRingSource;
static gboolean
mapped_ring_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MappedRingSource *real_source = (MappedRingSource *)source;
g_assert (source != NULL);
return mapped_ring_buffer_drain (real_source->self,
(MappedRingBufferCallback)callback,
user_data);
}
static void
mapped_ring_source_finalize (GSource *source)
{
MappedRingSource *real_source = (MappedRingSource *)source;
if (real_source != NULL)
g_clear_pointer (&real_source->self, mapped_ring_buffer_unref);
}
static gboolean
mapped_ring_source_check (GSource *source)
{
MappedRingSource *real_source = (MappedRingSource *)source;
MappedRingHeader *header;
uint32_t headpos, tailpos;
g_assert (real_source != NULL);
g_assert (real_source->self != NULL);
header = get_header (self);
header = get_header (real_source->self);
__atomic_load (&header->head, &headpos, __ATOMIC_SEQ_CST);
__atomic_load (&header->tail, &tailpos, __ATOMIC_SEQ_CST);
if (g_atomic_int_get (&header->head) != g_atomic_int_get (&header->tail))
return TRUE;
return FALSE;
}
static gboolean
mapped_ring_source_prepare (GSource *source,
gint *timeout_)
{
MappedRingSource *real_source = (MappedRingSource *)source;
MappedRingHeader *header;
g_assert (real_source != NULL);
g_assert (real_source->self != NULL);
header = get_header (real_source->self);
if (g_atomic_int_get (&header->head) != g_atomic_int_get (&header->tail))
return TRUE;
*timeout_ = 5;
return FALSE;
}
static GSourceFuncs mapped_ring_source_funcs = {
.prepare = mapped_ring_source_prepare,
.check = mapped_ring_source_check,
.dispatch = mapped_ring_source_dispatch,
.finalize = mapped_ring_source_finalize,
};
guint
mapped_ring_buffer_create_source_full (MappedRingBuffer *self,
MappedRingBufferCallback source_func,
gpointer user_data,
GDestroyNotify destroy)
{
MappedRingSource *source;
guint ret;
g_return_val_if_fail (self != NULL, 0);
g_return_val_if_fail (source_func != NULL, 0);
source = (MappedRingSource *)g_source_new (&mapped_ring_source_funcs, sizeof (MappedRingSource));
source->self = mapped_ring_buffer_ref (self);
g_source_set_callback ((GSource *)source, (GSourceFunc)source_func, user_data, destroy);
g_source_set_name ((GSource *)source, "MappedRingSource");
ret = g_source_attach ((GSource *)source, g_main_context_default ());
g_source_unref ((GSource *)source);
return ret;
}
guint
mapped_ring_buffer_create_source (MappedRingBuffer *self,
MappedRingBufferCallback source_func,
gpointer user_data)
{
return mapped_ring_buffer_create_source_full (self, source_func, user_data, NULL);
return headpos == tailpos;
}
/**
@ -648,7 +585,7 @@ mapped_ring_buffer_clear (MappedRingBuffer *self)
{
MappedRingHeader *header;
g_return_if_fail (self != NULL);
assert (self != NULL);
header = get_header (self);
header->head = 0;

View File

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

View File

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

View File

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

View File

@ -56,13 +56,19 @@
#pragma once
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include "sysprof-macros.h"
#include "sysprof-version-macros.h"
G_BEGIN_DECLS
SYSPROF_BEGIN_DECLS
typedef guint64 SysprofAddress;
typedef uint64_t SysprofAddress;
G_STATIC_ASSERT (sizeof (SysprofAddress) >= sizeof (gpointer));
static_assert (sizeof (SysprofAddress) >= sizeof (void *),
"Address space is too big");
typedef enum
{
@ -76,12 +82,12 @@ typedef enum
} SysprofAddressContext;
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_address_is_context_switch (SysprofAddress address,
bool sysprof_address_is_context_switch (SysprofAddress address,
SysprofAddressContext *context);
SYSPROF_AVAILABLE_IN_ALL
const gchar *sysprof_address_context_to_string (SysprofAddressContext context);
const char *sysprof_address_context_to_string (SysprofAddressContext context);
static inline gint
static inline int
sysprof_address_compare (SysprofAddress a,
SysprofAddress b)
{
@ -93,4 +99,4 @@ sysprof_address_compare (SysprofAddress a,
return 1;
}
G_END_DECLS
SYSPROF_END_DECLS

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -56,19 +56,20 @@
#pragma once
#include <stdbool.h>
#include "sysprof-capture-types.h"
#include "sysprof-macros.h"
#include "sysprof-version-macros.h"
G_BEGIN_DECLS
SYSPROF_BEGIN_DECLS
typedef struct _SysprofCaptureReader SysprofCaptureReader;
SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_reader_new (const gchar *filename,
GError **error);
SysprofCaptureReader *sysprof_capture_reader_new (const char *filename);
SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_reader_new_from_fd (int fd,
GError **error);
SysprofCaptureReader *sysprof_capture_reader_new_from_fd (int fd);
SYSPROF_AVAILABLE_IN_ALL
SysprofCaptureReader *sysprof_capture_reader_copy (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
@ -76,22 +77,22 @@ SysprofCaptureReader *sysprof_capture_reader_ref (
SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_reader_unref (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gint sysprof_capture_reader_get_byte_order (SysprofCaptureReader *self);
int sysprof_capture_reader_get_byte_order (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
const gchar *sysprof_capture_reader_get_filename (SysprofCaptureReader *self);
const char *sysprof_capture_reader_get_filename (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
const gchar *sysprof_capture_reader_get_time (SysprofCaptureReader *self);
const char *sysprof_capture_reader_get_time (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gint64 sysprof_capture_reader_get_start_time (SysprofCaptureReader *self);
int64_t sysprof_capture_reader_get_start_time (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gint64 sysprof_capture_reader_get_end_time (SysprofCaptureReader *self);
int64_t sysprof_capture_reader_get_end_time (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_skip (SysprofCaptureReader *self);
bool sysprof_capture_reader_skip (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_peek_type (SysprofCaptureReader *self,
bool sysprof_capture_reader_peek_type (SysprofCaptureReader *self,
SysprofCaptureFrameType *type);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_peek_frame (SysprofCaptureReader *self,
bool sysprof_capture_reader_peek_frame (SysprofCaptureReader *self,
SysprofCaptureFrame *frame);
SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureLog *sysprof_capture_reader_read_log (SysprofCaptureReader *self);
@ -112,7 +113,7 @@ const SysprofCaptureProcess *sysprof_capture_reader_read_process (
SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureSample *sysprof_capture_reader_read_sample (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
GHashTable *sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self);
const SysprofCaptureJitmap *sysprof_capture_reader_read_jitmap (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureCounterDefine *sysprof_capture_reader_read_counter_define (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
@ -122,31 +123,44 @@ const SysprofCaptureFileChunk *sysprof_capture_reader_read_file (
SYSPROF_AVAILABLE_IN_3_36
const SysprofCaptureAllocation *sysprof_capture_reader_read_allocation (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_reset (SysprofCaptureReader *self);
bool sysprof_capture_reader_reset (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_splice (SysprofCaptureReader *self,
SysprofCaptureWriter *dest,
GError **error);
bool sysprof_capture_reader_splice (SysprofCaptureReader *self,
SysprofCaptureWriter *dest);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_save_as (SysprofCaptureReader *self,
const gchar *filename,
GError **error);
bool sysprof_capture_reader_save_as (SysprofCaptureReader *self,
const char *filename);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_get_stat (SysprofCaptureReader *self,
bool sysprof_capture_reader_get_stat (SysprofCaptureReader *self,
SysprofCaptureStat *st_buf);
SYSPROF_AVAILABLE_IN_ALL
void sysprof_capture_reader_set_stat (SysprofCaptureReader *self,
const SysprofCaptureStat *st_buf);
SYSPROF_AVAILABLE_IN_ALL
const SysprofCaptureFileChunk *sysprof_capture_reader_find_file (SysprofCaptureReader *self,
const gchar *path);
const char *path);
SYSPROF_AVAILABLE_IN_ALL
gchar **sysprof_capture_reader_list_files (SysprofCaptureReader *self);
const char **sysprof_capture_reader_list_files (SysprofCaptureReader *self);
SYSPROF_AVAILABLE_IN_ALL
gboolean sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self,
const gchar *path,
gint fd);
bool sysprof_capture_reader_read_file_fd (SysprofCaptureReader *self,
const char *path,
int fd);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureReader, sysprof_capture_reader_unref)
typedef struct {
/*< private >*/
void *p1;
void *p2;
unsigned int u1;
void *p3;
void *p4;
} SysprofCaptureJitmapIter;
G_END_DECLS
SYSPROF_AVAILABLE_IN_3_38
void sysprof_capture_jitmap_iter_init (SysprofCaptureJitmapIter *iter,
const SysprofCaptureJitmap *jitmap);
SYSPROF_AVAILABLE_IN_3_38
bool sysprof_capture_jitmap_iter_next (SysprofCaptureJitmapIter *iter,
SysprofCaptureAddress *addr,
const char **path);
SYSPROF_END_DECLS

View File

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

View File

@ -56,14 +56,24 @@
#pragma once
#include <glib.h>
#ifdef __linux__
# include <sys/sendfile.h>
#endif
#include <stdlib.h>
#include <string.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__
# define _sysprof_getpagesize() getpagesize()
# define _sysprof_pread(a,b,c,d) pread(a,b,c,d)
@ -84,10 +94,17 @@ ssize_t _sysprof_pwrite (int fd,
ssize_t _sysprof_write (int fd,
const void *buf,
size_t count);
gint32 _sysprof_getpid (void);
int32_t _sysprof_getpid (void);
ssize_t _sysprof_sendfile (int out_fd,
int in_fd,
off_t *offset,
size_t count);
#endif
#ifdef HAVE_STRLCPY
# define _sysprof_strlcpy(d,s,ds) strlcpy(d,s,ds)
#else
size_t _sysprof_strlcpy (char *dest,
const char *src,
size_t dest_size);
#endif

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -54,56 +54,70 @@
* SPDX-License-Identifier: BSD-2-Clause-Patent
*/
#define G_LOG_DOMAIN "sysprof-collector"
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <glib-unix.h>
#include <gio/gio.h>
#include <gio/gunixconnection.h>
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <pthread.h>
#ifdef __linux__
# include <sched.h>
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include "mapped-ring-buffer.h"
#include "sysprof-capture-writer.h"
#include "sysprof-capture-util-private.h"
#include "sysprof-collector.h"
#include "sysprof-macros-internal.h"
#define MAX_UNWIND_DEPTH 128
#define CREATRING "CreatRing\0"
#define CREATRING_LEN 10
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
#ifndef MSG_CMSG_CLOEXEC
#define MSG_CMSG_CLOEXEC 0
#endif
typedef struct
{
MappedRingBuffer *buffer;
gboolean is_shared;
bool is_shared;
int tid;
int pid;
} SysprofCollector;
#define COLLECTOR_INVALID ((gpointer)&invalid)
#define COLLECTOR_INVALID ((void *)&invalid)
static MappedRingBuffer *request_writer (void);
static void sysprof_collector_free (gpointer data);
static void sysprof_collector_free (void *data);
static const SysprofCollector *sysprof_collector_get (void);
static G_LOCK_DEFINE (control_fd);
static GPrivate collector_key = G_PRIVATE_INIT (sysprof_collector_free);
static GPrivate single_trace_key = G_PRIVATE_INIT (NULL);
static pthread_mutex_t control_fd_lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t collector_key; /* initialised in sysprof_collector_init() */
static pthread_key_t single_trace_key; /* initialised in sysprof_collector_init() */
static pthread_once_t collector_init = PTHREAD_ONCE_INIT;
static SysprofCollector *shared_collector;
static SysprofCollector invalid;
static inline gboolean
static inline bool
use_single_trace (void)
{
return GPOINTER_TO_INT (g_private_get (&single_trace_key));
return (bool) pthread_getspecific (single_trace_key);
}
static inline int
@ -116,60 +130,218 @@ _do_getcpu (void)
#endif
}
static inline gsize
realign (gsize size)
static inline size_t
realign (size_t size)
{
return (size + SYSPROF_CAPTURE_ALIGN - 1) & ~(SYSPROF_CAPTURE_ALIGN - 1);
}
static bool
set_fd_blocking (int fd)
{
#ifdef F_GETFL
long fcntl_flags;
fcntl_flags = fcntl (peer_fd, F_GETFL);
if (fcntl_flags == -1)
return false;
#ifdef O_NONBLOCK
fcntl_flags &= ~O_NONBLOCK;
#else
fcntl_flags &= ~O_NDELAY;
#endif
if (fcntl (peer_fd, F_SETFL, fcntl_flags) == -1)
return false;
return true;
#else
return false;
#endif
}
static bool
block_on_poll (int fd,
int condition)
{
struct pollfd poll_fd;
poll_fd.fd = fd;
poll_fd.events = condition;
return (TEMP_FAILURE_RETRY (poll (&poll_fd, 1, -1)) == 1);
}
static ssize_t
send_blocking (int fd,
const uint8_t *buffer,
size_t buffer_len)
{
ssize_t res;
while ((res = TEMP_FAILURE_RETRY (send (fd, buffer, buffer_len, MSG_NOSIGNAL))) < 0)
{
int errsv = errno;
if (errsv == EWOULDBLOCK ||
errsv == EAGAIN)
{
if (!block_on_poll (fd, POLLOUT))
return -1;
}
else
{
return -1;
}
}
return res;
}
static bool
send_all_blocking (int fd,
const uint8_t *buffer,
size_t buffer_len,
size_t *bytes_written)
{
size_t _bytes_written;
_bytes_written = 0;
while (_bytes_written < buffer_len)
{
ssize_t res = send_blocking (fd, buffer + _bytes_written, buffer_len - _bytes_written);
if (res == -1)
{
if (bytes_written != NULL)
*bytes_written = _bytes_written;
return false;
}
assert (res > 0);
_bytes_written += res;
}
if (bytes_written != NULL)
*bytes_written = _bytes_written;
return true;
}
static int
receive_fd_blocking (int peer_fd)
{
ssize_t res;
struct msghdr msg;
struct iovec one_vector;
char one_byte;
uint8_t cmsg_buffer[CMSG_SPACE (sizeof (int))];
struct cmsghdr *cmsg;
const int *fds = NULL;
size_t n_fds = 0;
one_vector.iov_base = &one_byte;
one_vector.iov_len = 1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &one_vector;
msg.msg_iovlen = 1;
msg.msg_flags = MSG_CMSG_CLOEXEC;
msg.msg_control = &cmsg_buffer;
msg.msg_controllen = sizeof (cmsg_buffer);
while ((res = TEMP_FAILURE_RETRY (recvmsg (peer_fd, &msg, msg.msg_flags))) < 0)
{
int errsv = errno;
if (errsv == EWOULDBLOCK ||
errsv == EAGAIN)
{
if (!block_on_poll (peer_fd, POLLIN))
return -1;
}
else
{
return -1;
}
}
/* Decode the returned control message */
cmsg = CMSG_FIRSTHDR (&msg);
if (cmsg == NULL)
return -1;
if (cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS)
return -1;
/* non-integer number of FDs */
if ((cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) % 4 != 0)
return -1;
fds = (const int *) CMSG_DATA (cmsg);
n_fds = (cmsg->cmsg_len - ((char *)CMSG_DATA (cmsg) - (char *)cmsg)) / sizeof (*fds);
/* only expecting one FD */
if (n_fds != 1)
goto close_fds_err;
for (size_t i = 0; i < n_fds; i++)
{
if (fds[i] < 0)
goto close_fds_err;
}
/* only expecting one control message */
cmsg = CMSG_NXTHDR (&msg, cmsg);
if (cmsg != NULL)
goto close_fds_err;
return fds[0];
close_fds_err:
for (size_t i = 0; i < n_fds; i++)
close (fds[i]);
return -1;
}
/* Called with @control_fd_lock held. */
static MappedRingBuffer *
request_writer (void)
{
static GUnixConnection *conn;
static int peer_fd = -1;
MappedRingBuffer *buffer = NULL;
if (conn == NULL)
if (peer_fd == -1)
{
const gchar *fdstr = g_getenv ("SYSPROF_CONTROL_FD");
int peer_fd = -1;
const char *fdstr = getenv ("SYSPROF_CONTROL_FD");
if (fdstr != NULL)
peer_fd = atoi (fdstr);
g_unsetenv ("SYSPROF_CONTROL_FD");
unsetenv ("SYSPROF_CONTROL_FD");
if (peer_fd > 0)
{
g_autoptr(GSocket) sock = NULL;
(void) set_fd_blocking (peer_fd);
g_unix_set_fd_nonblocking (peer_fd, FALSE, NULL);
if ((sock = g_socket_new_from_fd (peer_fd, NULL)))
{
g_autoptr(GSocketConnection) scon = NULL;
g_socket_set_blocking (sock, TRUE);
if ((scon = g_socket_connection_factory_create_connection (sock)) &&
G_IS_UNIX_CONNECTION (scon))
conn = g_object_ref (G_UNIX_CONNECTION (scon));
}
#ifdef SO_NOSIGPIPE
{
int opt_value = 1;
(void) setsockopt (peer_fd, SOL_SOCKET, SO_NOSIGPIPE, &opt_value, sizeof (opt_value));
}
#endif
}
}
if (conn != NULL)
if (peer_fd >= 0)
{
GOutputStream *out_stream;
gsize len;
out_stream = g_io_stream_get_output_stream (G_IO_STREAM (conn));
if (g_output_stream_write_all (G_OUTPUT_STREAM (out_stream), CREATRING, CREATRING_LEN, &len, NULL, NULL) &&
len == CREATRING_LEN)
if (send_all_blocking (peer_fd, (const uint8_t *) CREATRING, CREATRING_LEN, NULL))
{
gint ring_fd = g_unix_connection_receive_fd (conn, NULL, NULL);
int ring_fd = receive_fd_blocking (peer_fd);
if (ring_fd > -1)
if (ring_fd >= 0)
{
buffer = mapped_ring_buffer_new_writer (ring_fd);
close (ring_fd);
@ -177,7 +349,7 @@ request_writer (void)
}
}
return g_steal_pointer (&buffer);
return sysprof_steal_pointer (&buffer);
}
static void
@ -185,7 +357,7 @@ write_final_frame (MappedRingBuffer *ring)
{
SysprofCaptureFrame *fr;
g_assert (ring != NULL);
assert (ring != NULL);
if ((fr = mapped_ring_buffer_allocate (ring, sizeof *fr)))
{
@ -199,13 +371,13 @@ write_final_frame (MappedRingBuffer *ring)
}
static void
sysprof_collector_free (gpointer data)
sysprof_collector_free (void *data)
{
SysprofCollector *collector = data;
if (collector != NULL && collector != COLLECTOR_INVALID)
{
MappedRingBuffer *buffer = g_steal_pointer (&collector->buffer);
MappedRingBuffer *buffer = sysprof_steal_pointer (&collector->buffer);
if (buffer != NULL)
{
@ -213,33 +385,41 @@ sysprof_collector_free (gpointer data)
mapped_ring_buffer_unref (buffer);
}
g_free (collector);
free (collector);
}
}
static const SysprofCollector *
sysprof_collector_get (void)
{
const SysprofCollector *collector = g_private_get (&collector_key);
const SysprofCollector *collector;
sysprof_collector_init ();
collector = pthread_getspecific (collector_key);
/* We might have gotten here recursively */
if G_UNLIKELY (collector == COLLECTOR_INVALID)
if SYSPROF_UNLIKELY (collector == COLLECTOR_INVALID)
return COLLECTOR_INVALID;
if G_LIKELY (collector != NULL)
if SYSPROF_LIKELY (collector != NULL)
return collector;
if (use_single_trace () && shared_collector != COLLECTOR_INVALID)
return shared_collector;
{
SysprofCollector *self;
SysprofCollector *self, *old_collector;
g_private_replace (&collector_key, COLLECTOR_INVALID);
/* First set the collector to invalid so anything recursive
* here fails instead of becoming re-entrant.
*/
pthread_setspecific (collector_key, COLLECTOR_INVALID);
G_LOCK (control_fd);
/* Now we can malloc without ending up here again */
self = sysprof_malloc0 (sizeof (SysprofCollector));
if (self == NULL)
return COLLECTOR_INVALID;
self = g_new0 (SysprofCollector, 1);
self->pid = getpid ();
#ifdef __linux__
self->tid = syscall (__NR_gettid, 0);
@ -247,66 +427,91 @@ sysprof_collector_get (void)
self->tid = self->pid;
#endif
if (g_getenv ("SYSPROF_CONTROL_FD") != NULL)
pthread_mutex_lock (&control_fd_lock);
if (getenv ("SYSPROF_CONTROL_FD") != NULL)
self->buffer = request_writer ();
if (self->is_shared)
shared_collector = self;
else
g_private_replace (&collector_key, self);
/* Update the stored collector */
old_collector = pthread_getspecific (collector_key);
G_UNLOCK (control_fd);
if (self->is_shared)
{
if (pthread_setspecific (collector_key, COLLECTOR_INVALID) != 0)
goto fail;
sysprof_collector_free (old_collector);
shared_collector = self;
}
else
{
if (pthread_setspecific (collector_key, self) != 0)
goto fail;
sysprof_collector_free (old_collector);
}
pthread_mutex_unlock (&control_fd_lock);
return self;
fail:
pthread_mutex_unlock (&control_fd_lock);
sysprof_collector_free (self);
return COLLECTOR_INVALID;
}
}
static void
collector_init_cb (void)
{
if (SYSPROF_UNLIKELY (pthread_key_create (&collector_key, sysprof_collector_free) != 0))
abort ();
if (SYSPROF_UNLIKELY (pthread_key_create (&single_trace_key, NULL) != 0))
abort ();
sysprof_clock_init ();
}
void
sysprof_collector_init (void)
{
static gsize once_init;
if (g_once_init_enter (&once_init))
{
sysprof_clock_init ();
(void)sysprof_collector_get ();
g_once_init_leave (&once_init, TRUE);
}
if SYSPROF_UNLIKELY (pthread_once (&collector_init, collector_init_cb) != 0)
abort ();
}
#define COLLECTOR_BEGIN \
G_STMT_START { \
do { \
const SysprofCollector *collector = sysprof_collector_get (); \
if G_LIKELY (collector->buffer) \
if SYSPROF_LIKELY (collector->buffer) \
{ \
if G_UNLIKELY (collector->is_shared) \
G_LOCK (control_fd); \
if SYSPROF_UNLIKELY (collector->is_shared) \
pthread_mutex_lock (&control_fd_lock); \
\
{
#define COLLECTOR_END \
} \
\
if G_UNLIKELY (collector->is_shared) \
G_UNLOCK (control_fd); \
if SYSPROF_UNLIKELY (collector->is_shared) \
pthread_mutex_unlock (&control_fd_lock); \
} \
} G_STMT_END
} while (0)
void
sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
gint64 alloc_size,
int64_t alloc_size,
SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data)
void *backtrace_data)
{
COLLECTOR_BEGIN {
SysprofCaptureAllocation *ev;
gsize len;
size_t len;
len = sizeof *ev + (sizeof (SysprofCaptureAllocation) * MAX_UNWIND_DEPTH);
if ((ev = mapped_ring_buffer_allocate (collector->buffer, len)))
{
gint n_addrs;
int n_addrs;
/* First take a backtrace, so that backtrace_func() can overwrite
* a little bit of data *BEFORE* ev->addrs as stratch space. This
@ -321,7 +526,7 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
else
n_addrs = 0;
ev->n_addrs = CLAMP (n_addrs, 0, MAX_UNWIND_DEPTH);
ev->n_addrs = ((n_addrs < 0) ? 0 : (n_addrs > MAX_UNWIND_DEPTH) ? MAX_UNWIND_DEPTH : n_addrs);
ev->frame.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs;
ev->frame.type = SYSPROF_CAPTURE_FRAME_ALLOCATION;
ev->frame.cpu = _do_getcpu ();
@ -339,18 +544,18 @@ sysprof_collector_allocate (SysprofCaptureAddress alloc_addr,
}
void
sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
gpointer backtrace_data)
sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
void *backtrace_data)
{
COLLECTOR_BEGIN {
SysprofCaptureSample *ev;
gsize len;
size_t len;
len = sizeof *ev + (sizeof (SysprofCaptureSample) * MAX_UNWIND_DEPTH);
if ((ev = mapped_ring_buffer_allocate (collector->buffer, len)))
{
gint n_addrs;
int n_addrs;
/* See comment from sysprof_collector_allocate(). */
if (backtrace_func)
@ -358,7 +563,7 @@ sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
else
n_addrs = 0;
ev->n_addrs = CLAMP (n_addrs, 0, MAX_UNWIND_DEPTH);
ev->n_addrs = ((n_addrs < 0) ? 0 : (n_addrs > MAX_UNWIND_DEPTH) ? MAX_UNWIND_DEPTH : n_addrs);
ev->frame.len = sizeof *ev + sizeof (SysprofCaptureAddress) * ev->n_addrs;
ev->frame.type = SYSPROF_CAPTURE_FRAME_SAMPLE;
ev->frame.cpu = _do_getcpu ();
@ -374,16 +579,16 @@ sysprof_collector_sample (SysprofBacktraceFunc backtrace_func,
}
void
sysprof_collector_mark (gint64 time,
gint64 duration,
const gchar *group,
const gchar *mark,
const gchar *message)
sysprof_collector_mark (int64_t time,
int64_t duration,
const char *group,
const char *mark,
const char *message)
{
COLLECTOR_BEGIN {
SysprofCaptureMark *ev;
gsize len;
gsize sl;
size_t len;
size_t sl;
if (group == NULL)
group = "";
@ -405,8 +610,8 @@ sysprof_collector_mark (gint64 time,
ev->frame.pid = collector->pid;
ev->frame.time = time;
ev->duration = duration;
g_strlcpy (ev->group, group, sizeof ev->group);
g_strlcpy (ev->name, mark, sizeof ev->name);
_sysprof_strlcpy (ev->group, group, sizeof ev->group);
_sysprof_strlcpy (ev->name, mark, sizeof ev->name);
memcpy (ev->message, message, sl);
ev->message[sl] = 0;
@ -417,14 +622,14 @@ sysprof_collector_mark (gint64 time,
}
void
sysprof_collector_log (GLogLevelFlags severity,
const gchar *domain,
const gchar *message)
sysprof_collector_log (int severity,
const char *domain,
const char *message)
{
COLLECTOR_BEGIN {
SysprofCaptureLog *ev;
gsize len;
gsize sl;
size_t len;
size_t sl;
if (domain == NULL)
domain = "";
@ -445,7 +650,7 @@ sysprof_collector_log (GLogLevelFlags severity,
ev->severity = severity & 0xFFFF;
ev->padding1 = 0;
ev->padding2 = 0;
g_strlcpy (ev->domain, domain, sizeof ev->domain);
_sysprof_strlcpy (ev->domain, domain, sizeof ev->domain);
memcpy (ev->message, message, sl);
ev->message[sl] = 0;
@ -456,20 +661,20 @@ sysprof_collector_log (GLogLevelFlags severity,
}
void
sysprof_collector_log_printf (GLogLevelFlags severity,
const gchar *domain,
const gchar *format,
sysprof_collector_log_printf (int severity,
const char *domain,
const char *format,
...)
{
COLLECTOR_BEGIN {
g_autofree gchar *formatted = NULL;
char formatted[2048];
SysprofCaptureLog *ev;
va_list args;
gsize len;
gsize sl;
size_t len;
size_t sl;
va_start (args, format);
formatted = g_strdup_vprintf (format, args);
vsnprintf (formatted, sizeof (formatted), format, args);
va_end (args);
if (domain == NULL)
@ -488,7 +693,7 @@ sysprof_collector_log_printf (GLogLevelFlags severity,
ev->severity = severity & 0xFFFF;
ev->padding1 = 0;
ev->padding2 = 0;
g_strlcpy (ev->domain, domain, sizeof ev->domain);
_sysprof_strlcpy (ev->domain, domain, sizeof ev->domain);
memcpy (ev->message, formatted, sl);
ev->message[sl] = 0;

View File

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

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
*/
#define G_LOG_DOMAIN "sysprof-platform"
#include "config.h"
#include <glib.h>
#include <glib/gstdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include "sysprof-capture-util-private.h"
#include "sysprof-platform.h"
#ifndef __NR_memfd_create
static const char *
get_tmpdir (void)
{
const char *tmpdir = NULL;
if (tmpdir == NULL || *tmpdir == '\0')
tmpdir = getenv ("TMPDIR");
#ifdef P_tmpdir
if (tmpdir == NULL || *tmpdir == '\0')
tmpdir = P_tmpdir;
#endif
if (tmpdir == NULL || *tmpdir == '\0')
tmpdir = "/tmp";
return tmpdir;
}
#endif /* !__NR_memfd_create */
/**
* sysprof_memfd_create:
* @name: (nullable): A descriptive name for the memfd or %NULL
@ -77,15 +95,17 @@
* Returns: An fd if successful; otherwise -1 and errno is set.
*/
int
sysprof_memfd_create (const gchar *name)
sysprof_memfd_create (const char *name)
{
#ifdef __NR_memfd_create
if (name == NULL)
name = "[sysprof]";
return syscall (__NR_memfd_create, name, 0);
#else
gchar *name_used = NULL;
int fd;
const char *tmpdir;
char *template = NULL;
size_t template_len = 0;
/*
* TODO: It would be nice to ensure tmpfs
@ -95,14 +115,28 @@ sysprof_memfd_create (const gchar *name)
* that the tmpfile we open is on tmpfs so that we get anonymous backed
* pages after unlinking.
*/
fd = g_file_open_tmp (NULL, &name_used, NULL);
if (name_used != NULL)
tmpdir = get_tmpdir ();
template_len = strlen (tmpdir) + 1 + strlen ("sysprof-XXXXXX") + 1;
template = sysprof_malloc0 (template_len);
if (template == NULL)
{
g_unlink (name_used);
g_free (name_used);
errno = ENOMEM;
return -1;
}
snprintf (template, template_len, "%s/sysprof-XXXXXX", tmpdir);
fd = TEMP_FAILURE_RETRY (mkostemp (template, O_BINARY | O_CLOEXEC));
if (fd < 0)
{
free (template);
return -1;
}
unlink (template);
free (template);
return fd;
#endif
}
@ -116,7 +150,7 @@ sysprof_memfd_create (const gchar *name)
*
* Since: 3.36
*/
gsize
size_t
sysprof_getpagesize (void)
{
return _sysprof_getpagesize ();

View File

@ -56,13 +56,17 @@
#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
int sysprof_memfd_create (const gchar *desc);
int sysprof_memfd_create (const char *desc);
SYSPROF_AVAILABLE_IN_3_36
gsize sysprof_getpagesize (void);
size_t sysprof_getpagesize (void);
G_END_DECLS
SYSPROF_END_DECLS

View File

@ -56,42 +56,54 @@
#pragma once
#include <glib.h>
#include "sysprof-version.h"
#ifndef _SYSPROF_EXTERN
#define _SYSPROF_EXTERN extern
#endif
#if defined(__GNUC__) || defined (__clang__)
#define _SYSPROF_DEPRECATED __attribute__((__deprecated__))
#define _SYSPROF_DEPRECATED_FOR(f) __attribute__((__deprecated__("Use '" #f "' instead")))
#define _SYSPROF_UNAVAILABLE(maj,min) __attribute__((__deprecated__("Not available before " #maj "." #min)))
#elif defined(_MSC_VER)
#define _SYSPROF_DEPRECATED __declspec(deprecated)
#define _SYSPROF_DEPRECATED_FOR(f) __declspec(deprecated("is deprecated. Use '" #f "' instead"))
#define _SYSPROF_UNAVAILABLE(maj,min) __declspec(deprecated("is not available before " #maj "." #min))
#else
#define _SYSPROF_DEPRECATED
#define _SYSPROF_DEPRECATED_FOR(f)
#define _SYSPROF_UNAVAILABLE(maj,min)
#endif
#ifdef SYSPROF_DISABLE_DEPRECATION_WARNINGS
#define SYSPROF_DEPRECATED _SYSPROF_EXTERN
#define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN
#define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN
#else
#define SYSPROF_DEPRECATED G_DEPRECATED _SYSPROF_EXTERN
#define SYSPROF_DEPRECATED_FOR(f) G_DEPRECATED_FOR(f) _SYSPROF_EXTERN
#define SYSPROF_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _SYSPROF_EXTERN
#define SYSPROF_DEPRECATED _SYSPROF_DEPRECATED _SYSPROF_EXTERN
#define SYSPROF_DEPRECATED_FOR(f) _SYSPROF_DEPRECATED_FOR(f) _SYSPROF_EXTERN
#define SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_UNAVAILABLE(maj,min) _SYSPROF_EXTERN
#endif
#define SYSPROF_VERSION_3_34 (G_ENCODE_VERSION (3, 34))
#define SYSPROF_VERSION_3_36 (G_ENCODE_VERSION (3, 36))
#define SYSPROF_VERSION_3_38 (G_ENCODE_VERSION (3, 38))
#define SYSPROF_VERSION_3_34 (SYSPROF_ENCODE_VERSION (3, 34, 0))
#define SYSPROF_VERSION_3_36 (SYSPROF_ENCODE_VERSION (3, 36, 0))
#define SYSPROF_VERSION_3_38 (SYSPROF_ENCODE_VERSION (3, 38, 0))
#if (SYSPROF_MINOR_VERSION == 99)
# define SYSPROF_VERSION_CUR_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0))
# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0, 0))
#elif (SYSPROF_MINOR_VERSION % 2)
# define SYSPROF_VERSION_CUR_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION + 1))
# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION + 1, 0))
#else
# define SYSPROF_VERSION_CUR_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION))
# define SYSPROF_VERSION_CUR_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION, 0))
#endif
#if (SYSPROF_MINOR_VERSION == 99)
# define SYSPROF_VERSION_PREV_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0))
# define SYSPROF_VERSION_PREV_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION + 1, 0, 0))
#elif (SYSPROF_MINOR_VERSION % 2)
# define SYSPROF_VERSION_PREV_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 1))
# define SYSPROF_VERSION_PREV_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 1, 0))
#else
# define SYSPROF_VERSION_PREV_STABLE (G_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 2))
# define SYSPROF_VERSION_PREV_STABLE (SYSPROF_ENCODE_VERSION (SYSPROF_MAJOR_VERSION, SYSPROF_MINOR_VERSION - 2, 0))
#endif
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -143,7 +143,7 @@ sysprof_display_profiler_stopped_cb (SysprofDisplay *self,
g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(GError) error = NULL;
if (!(reader = sysprof_capture_writer_create_reader (writer, &error)))
if (!(reader = sysprof_capture_writer_create_reader_with_error (writer, &error)))
{
g_warning ("Failed to create capture creader: %s\n", error->message);
gtk_stack_set_visible_child (priv->stack, GTK_WIDGET (priv->failed_view));
@ -1071,7 +1071,7 @@ sysprof_display_open (SysprofDisplay *self,
g_set_object (&priv->file, file);
if (!(reader = sysprof_capture_reader_new (path, &error)))
if (!(reader = sysprof_capture_reader_new_with_error (path, &error)))
{
GtkWidget *dialog;
GtkWidget *window;
@ -1229,7 +1229,7 @@ sysprof_display_save (SysprofDisplay *self)
g_autofree gchar *path = g_file_get_path (file);
g_autoptr(GError) error = NULL;
if (!sysprof_capture_reader_save_as (priv->reader, path, &error))
if (!sysprof_capture_reader_save_as_with_error (priv->reader, path, &error))
{
GtkWidget *msg;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -24,6 +24,7 @@
#include <dlfcn.h>
#include <fcntl.h>
#include <glib.h>
#include <stdlib.h>
#include <sys/mman.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 "sysprof-capture-gobject.h"
#include <errno.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 (SysprofCaptureWriter, sysprof_capture_writer, (GBoxedCopyFunc)sysprof_capture_writer_ref, (GBoxedFreeFunc)sysprof_capture_writer_unref)
G_DEFINE_BOXED_TYPE (SysprofCaptureCursor, sysprof_capture_cursor, (GBoxedCopyFunc)sysprof_capture_cursor_ref, (GBoxedFreeFunc)sysprof_capture_cursor_unref)
SysprofCaptureReader *
sysprof_capture_reader_new_with_error (const char *filename,
GError **error)
{
SysprofCaptureReader *ret;
if (!(ret = sysprof_capture_reader_new (filename)))
g_set_error_literal (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
g_strerror (errno));
return ret;
}
SysprofCaptureReader *
sysprof_capture_reader_new_from_fd_with_error (int fd,
GError **error)
{
SysprofCaptureReader *ret;
if (!(ret = sysprof_capture_reader_new_from_fd (fd)))
g_set_error_literal (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
g_strerror (errno));
return ret;
}
SysprofCaptureReader *
sysprof_capture_writer_create_reader_with_error (SysprofCaptureWriter *self,
GError **error)
{
SysprofCaptureReader *ret;
if (!(ret = sysprof_capture_writer_create_reader (self)))
g_set_error_literal (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
g_strerror (errno));
return ret;
}
bool
sysprof_capture_reader_save_as_with_error (SysprofCaptureReader *self,
const char *filename,
GError **error)
{
if (!sysprof_capture_reader_save_as (self, filename))
{
g_set_error_literal (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
g_strerror (errno));
return false;
}
return true;
}

View File

@ -41,4 +41,18 @@ GType sysprof_capture_writer_get_type (void);
SYSPROF_AVAILABLE_IN_ALL
GType sysprof_capture_cursor_get_type (void);
SYSPROF_AVAILABLE_IN_3_38
SysprofCaptureReader *sysprof_capture_reader_new_with_error (const char *filename,
GError **error);
SYSPROF_AVAILABLE_IN_3_38
SysprofCaptureReader *sysprof_capture_reader_new_from_fd_with_error (int fd,
GError **error);
SYSPROF_AVAILABLE_IN_3_38
SysprofCaptureReader *sysprof_capture_writer_create_reader_with_error (SysprofCaptureWriter *self,
GError **error);
SYSPROF_AVAILABLE_IN_3_38
bool sysprof_capture_reader_save_as_with_error (SysprofCaptureReader *self,
const char *filename,
GError **error);
G_END_DECLS

View File

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

View File

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

View File

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

View File

@ -34,6 +34,7 @@
#include "sysprof-local-profiler.h"
#include "sysprof-platform.h"
#include "sysprof-capture-autocleanups.h"
#include "sysprof-control-source.h"
#include "sysprof-gjs-source.h"
#include "sysprof-hostinfo-source.h"
@ -197,7 +198,8 @@ sysprof_local_profiler_finish_stopping (SysprofLocalProfiler *self)
g_assert (priv->is_stopping == TRUE);
g_assert (priv->stopping->len == 0);
reader = sysprof_capture_writer_create_reader (priv->writer, 0);
reader = sysprof_capture_writer_create_reader (priv->writer);
g_assert (reader != NULL);
for (guint i = 0; i < priv->sources->len; i++)
{
@ -982,9 +984,9 @@ profiler_iface_init (SysprofProfilerInterface *iface)
iface->stopped = sysprof_local_profiler_real_stopped;
}
static gboolean
static bool
find_profiler_meta_cb (const SysprofCaptureFrame *frame,
gpointer user_data)
void *user_data)
{
const SysprofCaptureMetadata *meta = (const SysprofCaptureMetadata *)frame;
GKeyFile **keyfile = user_data;
@ -1005,7 +1007,7 @@ find_profiler_meta_cb (const SysprofCaptureFrame *frame,
return *keyfile == NULL;
}
return TRUE;
return true;
}
SysprofProfiler *

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -134,9 +134,10 @@ main (gint argc,
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
if (!(reader = sysprof_capture_reader_new (filename, &error)))
if (!(reader = sysprof_capture_reader_new (filename)))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}

View File

@ -205,9 +205,10 @@ main (gint argc,
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
if (!(reader = sysprof_capture_reader_new (filename, &error)))
if (!(reader = sysprof_capture_reader_new (filename)))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}

View File

@ -20,6 +20,7 @@
#include "config.h"
#include <glib.h>
#include <stddef.h>
#include <rax.h>
#include <sysprof.h>
@ -115,7 +116,6 @@ main (gint argc,
{
SysprofCaptureReader *reader;
const gchar *filename = argv[1];
g_autoptr(GError) error = NULL;
if (argc < 2)
{
@ -123,9 +123,10 @@ main (gint argc,
return EXIT_FAILURE;
}
if (!(reader = sysprof_capture_reader_new (filename, &error)))
if (!(reader = sysprof_capture_reader_new (filename)))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}

View File

@ -20,6 +20,7 @@
#include "config.h"
#include <glib.h>
#include <sysprof-capture.h>
static struct {
@ -140,7 +141,6 @@ main (gint argc,
{
SysprofCaptureReader *reader;
const gchar *filename = argv[1];
g_autoptr(GError) error = NULL;
if (argc < 2)
{
@ -148,9 +148,10 @@ main (gint argc,
return EXIT_FAILURE;
}
if (!(reader = sysprof_capture_reader_new (filename, &error)))
if (!(reader = sysprof_capture_reader_new (filename)))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}

View File

@ -77,9 +77,10 @@ main (gint argc,
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
if (!(reader = sysprof_capture_reader_new (filename, &error)))
if (!(reader = sysprof_capture_reader_new (filename)))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}

View File

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

View File

@ -21,6 +21,7 @@
#include "config.h"
#include <cairo.h>
#include <glib.h>
#include <stddef.h>
#include <rax.h>
#include <sysprof.h>
@ -167,7 +168,6 @@ main (gint argc,
SysprofCaptureReader *reader;
const gchar *filename = argv[1];
g_autoptr(SysprofProfile) memprof = NULL;
g_autoptr(GError) error = NULL;
if (argc < 2)
{
@ -177,9 +177,10 @@ main (gint argc,
main_loop = g_main_loop_new (NULL, FALSE);
if (!(reader = sysprof_capture_reader_new (filename, &error)))
if (!(reader = sysprof_capture_reader_new (filename)))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}

View File

@ -1,4 +1,5 @@
#include <fcntl.h>
#include <glib.h>
#include <sysprof.h>
#include "sysprof-platform.h"
@ -10,7 +11,6 @@ main (gint argc,
{
g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(SysprofSymbolResolver) resolver = NULL;
g_autoptr(GError) error = NULL;
SysprofCaptureFrameType type;
if (argc != 2)
@ -19,9 +19,10 @@ main (gint argc,
return 1;
}
if (!(reader = sysprof_capture_reader_new (argv[1], &error)))
if (!(reader = sysprof_capture_reader_new (argv[1])))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return 1;
}

View File

@ -1,4 +1,5 @@
#include <fcntl.h>
#include <glib.h>
#include <sysprof.h>
#include "sysprof-platform.h"
@ -91,9 +92,10 @@ main (gint argc,
return 1;
}
if (!(reader = sysprof_capture_reader_new (argv[1], &error)))
if (!(reader = sysprof_capture_reader_new (argv[1])))
{
g_printerr ("%s\n", error->message);
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return 1;
}

View File

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

View File

@ -37,7 +37,7 @@ main (gint argc,
return 1;
}
if (!(reader = sysprof_capture_reader_new (argv[1], &error)))
if (!(reader = sysprof_capture_reader_new_with_error (argv[1], &error)))
{
g_printerr ("Failed to load reader: %s\n", error->message);
return 1;

View File

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

View File

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

View File

@ -1,3 +1,4 @@
#include <glib.h>
#include <sysprof.h>
static const SysprofCaptureSample *
@ -42,8 +43,12 @@ main (gint argc,
g_ptr_array_add (resolvers, sysprof_jitmap_symbol_resolver_new ());
g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ());
if (!(reader = sysprof_capture_reader_new (filename, &error)))
g_error ("%s", error->message);
if (!(reader = sysprof_capture_reader_new (filename)))
{
int errsv = errno;
g_error ("%s", g_strerror (errsv));
return 1;
}
for (guint r = 0; r < resolvers->len; r++)
{

View File

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

View File

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

View File

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

View File

@ -134,19 +134,20 @@ merge_files (gint argc,
for (guint i = 1; i < argc; i++)
{
g_autoptr(SysprofCaptureReader) reader = NULL;
g_autoptr(GError) error = NULL;
if (!(reader = sysprof_capture_reader_new (argv[i], &error)))
if (!(reader = sysprof_capture_reader_new (argv[i])))
{
int errsv = errno;
g_printerr ("Failed to create reader for \"%s\": %s\n",
argv[i], error->message);
argv[i], g_strerror (errsv));
return EXIT_FAILURE;
}
if (!sysprof_capture_writer_cat (writer, reader, &error))
if (!sysprof_capture_writer_cat (writer, reader))
{
int errsv = errno;
g_printerr ("Failed to join \"%s\": %s\n",
argv[i], error->message);
argv[i], g_strerror (errsv));
return EXIT_FAILURE;
}
}

View File

@ -20,6 +20,7 @@
#include "config.h"
#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <sysprof-capture.h>
@ -55,13 +56,18 @@ main (gint argc,
return EXIT_FAILURE;
}
reader = sysprof_capture_reader_new (argv[1], &error);
if ((reader = sysprof_capture_reader_new (argv[1])) == NULL)
{
int errsv = errno;
g_printerr ("%s\n", g_strerror (errsv));
return EXIT_FAILURE;
}
if (list_files)
{
g_auto(GStrv) files = sysprof_capture_reader_list_files (reader);
g_autofree const gchar **files = sysprof_capture_reader_list_files (reader);
for (guint i = 0; files[i]; i++)
for (gsize i = 0; files[i]; i++)
g_print ("%s\n", files[i]);
return EXIT_SUCCESS;
@ -74,12 +80,6 @@ main (gint argc,
#define SET_CTR_TYPE(i,t) g_hash_table_insert(ctrtypes, GINT_TO_POINTER(i), GINT_TO_POINTER(t))
#define GET_CTR_TYPE(i) GPOINTER_TO_INT(g_hash_table_lookup(ctrtypes, GINT_TO_POINTER(i)))
if (reader == NULL)
{
g_printerr ("%s\n", error->message);
return EXIT_FAILURE;
}
begin_time = sysprof_capture_reader_get_start_time (reader);
end_time = sysprof_capture_reader_get_end_time (reader);
@ -116,18 +116,18 @@ main (gint argc,
case SYSPROF_CAPTURE_FRAME_JITMAP:
{
g_autoptr(GHashTable) ret = sysprof_capture_reader_read_jitmap (reader);
GHashTableIter iter;
const SysprofCaptureJitmap *jitmap = sysprof_capture_reader_read_jitmap (reader);
SysprofCaptureJitmapIter iter;
SysprofCaptureAddress addr;
const gchar *str;
if (ret == NULL)
if (jitmap == NULL)
return EXIT_FAILURE;
g_print ("JITMAP:\n");
g_hash_table_iter_init (&iter, ret);
while (g_hash_table_iter_next (&iter, (gpointer *)&addr, (gpointer *)&str))
sysprof_capture_jitmap_iter_init (&iter, jitmap);
while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str))
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " : %s\n", addr, str);
break;