mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Merge branch 'drop-glib' into 'master'
Drop GLib from libsysprof-capture Closes #40 See merge request GNOME/sysprof!30
This commit is contained in:
@ -11,6 +11,7 @@
|
||||
# include <sched.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <signal.h>
|
||||
#include <sysprof-capture.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
app = executable('example-app', 'app.c',
|
||||
dependencies: [libsysprof_capture_dep],
|
||||
dependencies: [dependency('glib-2.0'), libsysprof_capture_dep],
|
||||
)
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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,
|
||||
],
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 it’s constructed.
|
||||
*
|
||||
* FIXME: There’s currently no error reporting from this function, so ENOMEM
|
||||
* results in an abort. */
|
||||
self->conditions = reallocarray (self->conditions, ++self->n_conditions, sizeof (*self->conditions));
|
||||
assert (self->conditions != NULL);
|
||||
|
||||
self->conditions[self->n_conditions - 1] = sysprof_steal_pointer (&condition);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -292,7 +310,7 @@ sysprof_capture_cursor_new (SysprofCaptureReader *reader)
|
||||
{
|
||||
SysprofCaptureCursor *self;
|
||||
|
||||
g_return_val_if_fail (reader != NULL, NULL);
|
||||
assert (reader != NULL);
|
||||
|
||||
self = sysprof_capture_cursor_init ();
|
||||
self->reader = sysprof_capture_reader_copy (reader);
|
||||
@ -311,7 +329,7 @@ sysprof_capture_cursor_new (SysprofCaptureReader *reader)
|
||||
SysprofCaptureReader *
|
||||
sysprof_capture_cursor_get_reader (SysprofCaptureCursor *self)
|
||||
{
|
||||
g_return_val_if_fail (self != NULL, NULL);
|
||||
assert (self != NULL);
|
||||
|
||||
return self->reader;
|
||||
}
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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 can’t be used to determine sizeof(void*) at compile time");
|
||||
#if UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu
|
||||
# define SYSPROF_CAPTURE_JITMAP_MARK SYSPROF_UINT64_CONSTANT(0xE000000000000000)
|
||||
#elif UINTPTR_MAX == 0xFFFFFFFF
|
||||
# define SYSPROF_CAPTURE_JITMAP_MARK SYSPROF_UINT64_CONSTANT(0xE0000000)
|
||||
#else
|
||||
#error Unknown GLIB_SIZEOF_VOID_P
|
||||
#error Unknown UINTPTR_MAX
|
||||
#endif
|
||||
|
||||
#define SYSPROF_CAPTURE_CURRENT_TIME (sysprof_clock_get_current_time())
|
||||
@ -92,25 +99,25 @@ typedef struct _SysprofCaptureWriter SysprofCaptureWriter;
|
||||
typedef struct _SysprofCaptureCursor SysprofCaptureCursor;
|
||||
typedef struct _SysprofCaptureCondition SysprofCaptureCondition;
|
||||
|
||||
typedef guint64 SysprofCaptureAddress;
|
||||
typedef uint64_t SysprofCaptureAddress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*
|
||||
* The number of frames indexed by SysprofCaptureFrameType
|
||||
*/
|
||||
gsize frame_count[16];
|
||||
size_t frame_count[16];
|
||||
|
||||
/*
|
||||
* Padding for future expansion.
|
||||
*/
|
||||
gsize padding[48];
|
||||
size_t padding[48];
|
||||
} SysprofCaptureStat;
|
||||
|
||||
typedef union
|
||||
{
|
||||
gint64 v64;
|
||||
gdouble vdbl;
|
||||
int64_t v64;
|
||||
double vdbl;
|
||||
} SysprofCaptureCounterValue;
|
||||
|
||||
typedef enum
|
||||
@ -137,28 +144,28 @@ typedef enum
|
||||
SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
guint32 magic;
|
||||
guint32 version : 8;
|
||||
guint32 little_endian : 1;
|
||||
guint32 padding : 23;
|
||||
gchar capture_time[64];
|
||||
gint64 time;
|
||||
gint64 end_time;
|
||||
gchar suffix[168];
|
||||
uint32_t magic;
|
||||
uint32_t version : 8;
|
||||
uint32_t little_endian : 1;
|
||||
uint32_t padding : 23;
|
||||
char capture_time[64];
|
||||
int64_t time;
|
||||
int64_t end_time;
|
||||
char suffix[168];
|
||||
} SysprofCaptureFileHeader
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
guint16 len;
|
||||
gint16 cpu;
|
||||
gint32 pid;
|
||||
gint64 time;
|
||||
guint32 type : 8;
|
||||
guint32 padding1 : 24;
|
||||
guint32 padding2;
|
||||
guint8 data[0];
|
||||
uint16_t len;
|
||||
int16_t cpu;
|
||||
int32_t pid;
|
||||
int64_t time;
|
||||
uint32_t type : 8;
|
||||
uint32_t padding1 : 24;
|
||||
uint32_t padding2;
|
||||
uint8_t data[0];
|
||||
} SysprofCaptureFrame
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -166,11 +173,11 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint64 start;
|
||||
guint64 end;
|
||||
guint64 offset;
|
||||
guint64 inode;
|
||||
gchar filename[0];
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
uint64_t offset;
|
||||
uint64_t inode;
|
||||
char filename[0];
|
||||
} SysprofCaptureMap
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -178,8 +185,8 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint32 n_jitmaps;
|
||||
guint8 data[0];
|
||||
uint32_t n_jitmaps;
|
||||
uint8_t data[0];
|
||||
} SysprofCaptureJitmap
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -187,7 +194,7 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
gchar cmdline[0];
|
||||
char cmdline[0];
|
||||
} SysprofCaptureProcess
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -195,9 +202,9 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint32 n_addrs : 16;
|
||||
guint32 padding1 : 16;
|
||||
gint32 tid;
|
||||
uint32_t n_addrs : 16;
|
||||
uint32_t padding1 : 16;
|
||||
int32_t tid;
|
||||
SysprofCaptureAddress addrs[0];
|
||||
} SysprofCaptureSample
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
@ -206,7 +213,7 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
gint32 child_pid;
|
||||
int32_t child_pid;
|
||||
} SysprofCaptureFork
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -227,11 +234,11 @@ SYSPROF_ALIGNED_END(1);
|
||||
SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
gchar category[32];
|
||||
gchar name[32];
|
||||
gchar description[52];
|
||||
guint32 id : 24;
|
||||
guint32 type : 8;
|
||||
char category[32];
|
||||
char name[32];
|
||||
char description[52];
|
||||
uint32_t id : 24;
|
||||
uint32_t type : 8;
|
||||
SysprofCaptureCounterValue value;
|
||||
} SysprofCaptureCounter
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
@ -240,9 +247,9 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint32 n_counters : 16;
|
||||
guint32 padding1 : 16;
|
||||
guint32 padding2;
|
||||
uint32_t n_counters : 16;
|
||||
uint32_t padding1 : 16;
|
||||
uint32_t padding2;
|
||||
SysprofCaptureCounter counters[0];
|
||||
} SysprofCaptureCounterDefine
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
@ -255,7 +262,7 @@ typedef struct
|
||||
* bytes. So this makes a nice 2-cacheline aligned size which is
|
||||
* useful when the number of counters is rather small.
|
||||
*/
|
||||
guint32 ids[8];
|
||||
uint32_t ids[8];
|
||||
SysprofCaptureCounterValue values[8];
|
||||
} SysprofCaptureCounterValues
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
@ -264,9 +271,9 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint32 n_values : 16;
|
||||
guint32 padding1 : 16;
|
||||
guint32 padding2;
|
||||
uint32_t n_values : 16;
|
||||
uint32_t padding1 : 16;
|
||||
uint32_t padding2;
|
||||
SysprofCaptureCounterValues values[0];
|
||||
} SysprofCaptureCounterSet
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
@ -275,10 +282,10 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
gint64 duration;
|
||||
gchar group[24];
|
||||
gchar name[40];
|
||||
gchar message[0];
|
||||
int64_t duration;
|
||||
char group[24];
|
||||
char name[40];
|
||||
char message[0];
|
||||
} SysprofCaptureMark
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -286,8 +293,8 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
gchar id[40];
|
||||
gchar metadata[0];
|
||||
char id[40];
|
||||
char metadata[0];
|
||||
} SysprofCaptureMetadata
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -295,11 +302,11 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint32 severity : 16;
|
||||
guint32 padding1 : 16;
|
||||
guint32 padding2 : 32;
|
||||
gchar domain[32];
|
||||
gchar message[0];
|
||||
uint32_t severity : 16;
|
||||
uint32_t padding1 : 16;
|
||||
uint32_t padding2 : 32;
|
||||
char domain[32];
|
||||
char message[0];
|
||||
} SysprofCaptureLog
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -307,11 +314,11 @@ SYSPROF_ALIGNED_BEGIN(1)
|
||||
typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
guint32 is_last : 1;
|
||||
guint32 padding1 : 15;
|
||||
guint32 len : 16;
|
||||
gchar path[256];
|
||||
guint8 data[0];
|
||||
uint32_t is_last : 1;
|
||||
uint32_t padding1 : 15;
|
||||
uint32_t len : 16;
|
||||
char path[256];
|
||||
uint8_t data[0];
|
||||
} SysprofCaptureFileChunk
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
@ -320,37 +327,37 @@ typedef struct
|
||||
{
|
||||
SysprofCaptureFrame frame;
|
||||
SysprofCaptureAddress alloc_addr;
|
||||
gint64 alloc_size;
|
||||
gint32 tid;
|
||||
guint32 n_addrs : 16;
|
||||
guint32 padding1 : 16;
|
||||
int64_t alloc_size;
|
||||
int32_t tid;
|
||||
uint32_t n_addrs : 16;
|
||||
uint32_t padding1 : 16;
|
||||
SysprofCaptureAddress addrs[0];
|
||||
} SysprofCaptureAllocation
|
||||
SYSPROF_ALIGNED_END(1);
|
||||
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureJitmap) == 28);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureProcess) == 24);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureSample) == 32);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureFork) == 28);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureExit) == 24);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureTimestamp) == 24);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureCounter) == 128);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureCounterValues) == 96);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureCounterDefine) == 32);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureCounterSet) == 32);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureMark) == 96);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureMetadata) == 64);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureLog) == 64);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureFileChunk) == 284);
|
||||
G_STATIC_ASSERT (sizeof (SysprofCaptureAllocation) == 48);
|
||||
static_assert (sizeof (SysprofCaptureFileHeader) == 256, "SysprofCaptureFileHeader changed size");
|
||||
static_assert (sizeof (SysprofCaptureFrame) == 24, "SysprofCaptureFrame changed size");
|
||||
static_assert (sizeof (SysprofCaptureMap) == 56, "SysprofCaptureMap changed size");
|
||||
static_assert (sizeof (SysprofCaptureJitmap) == 28, "SysprofCaptureJitmap changed size");
|
||||
static_assert (sizeof (SysprofCaptureProcess) == 24, "SysprofCaptureProcess changed size");
|
||||
static_assert (sizeof (SysprofCaptureSample) == 32, "SysprofCaptureSample changed size");
|
||||
static_assert (sizeof (SysprofCaptureFork) == 28, "SysprofCaptureFork changed size");
|
||||
static_assert (sizeof (SysprofCaptureExit) == 24, "SysprofCaptureExit changed size");
|
||||
static_assert (sizeof (SysprofCaptureTimestamp) == 24, "SysprofCaptureTimestamp changed size");
|
||||
static_assert (sizeof (SysprofCaptureCounter) == 128, "SysprofCaptureCounter changed size");
|
||||
static_assert (sizeof (SysprofCaptureCounterValues) == 96, "SysprofCaptureCounterValues changed size");
|
||||
static_assert (sizeof (SysprofCaptureCounterDefine) == 32, "SysprofCaptureCounterDefine changed size");
|
||||
static_assert (sizeof (SysprofCaptureCounterSet) == 32, "SysprofCaptureCounterSet changed size");
|
||||
static_assert (sizeof (SysprofCaptureMark) == 96, "SysprofCaptureMark changed size");
|
||||
static_assert (sizeof (SysprofCaptureMetadata) == 64, "SysprofCaptureMetadata changed size");
|
||||
static_assert (sizeof (SysprofCaptureLog) == 64, "SysprofCaptureLog changed size");
|
||||
static_assert (sizeof (SysprofCaptureFileChunk) == 284, "SysprofCaptureFileChunk changed size");
|
||||
static_assert (sizeof (SysprofCaptureAllocation) == 48, "SysprofCaptureAllocation changed size");
|
||||
|
||||
G_STATIC_ASSERT ((G_STRUCT_OFFSET (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0);
|
||||
G_STATIC_ASSERT ((G_STRUCT_OFFSET (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0);
|
||||
static_assert ((offsetof (SysprofCaptureAllocation, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureAllocation.addrs is not aligned");
|
||||
static_assert ((offsetof (SysprofCaptureSample, addrs) % SYSPROF_CAPTURE_ALIGN) == 0, "SysprofCaptureSample.addrs is not aligned");
|
||||
|
||||
static inline gint
|
||||
static inline int
|
||||
sysprof_capture_address_compare (SysprofCaptureAddress a,
|
||||
SysprofCaptureAddress b)
|
||||
{
|
||||
@ -362,4 +369,17 @@ sysprof_capture_address_compare (SysprofCaptureAddress a,
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
/**
|
||||
* SysprofBacktraceFunc:
|
||||
* @addrs: (inout) (array length=n_addrs): an array to place addresses
|
||||
* into the capture frame
|
||||
* @n_addrs: the length of @addrs
|
||||
* @user_data: (scope call): closure data for the callback
|
||||
*
|
||||
* Returns: the number of addresses filled in @addrs
|
||||
*/
|
||||
typedef int (*SysprofBacktraceFunc) (SysprofCaptureAddress *addrs,
|
||||
unsigned int n_addrs,
|
||||
void *user_data);
|
||||
|
||||
SYSPROF_END_DECLS
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 ();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
77
src/libsysprof-capture/sysprof-macros-internal.h
Normal file
77
src/libsysprof-capture/sysprof-macros-internal.h
Normal 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)
|
||||
98
src/libsysprof-capture/sysprof-macros.h
Normal file
98
src/libsysprof-capture/sysprof-macros.h
Normal 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
|
||||
@ -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 ();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -81,7 +81,7 @@ sysprof_battery_aid_prepare (SysprofAid *self,
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static bool
|
||||
collect_battery_counters (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
||||
@ -114,7 +114,7 @@ sysprof_callgraph_aid_prepare (SysprofAid *self,
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static bool
|
||||
discover_samples_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -85,7 +85,7 @@ sysprof_cpu_aid_prepare (SysprofAid *self,
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static bool
|
||||
collect_info (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -87,7 +87,7 @@ sysprof_memprof_aid_prepare (SysprofAid *self,
|
||||
#endif
|
||||
}
|
||||
|
||||
static gboolean
|
||||
static bool
|
||||
discover_samples_cb (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
121
src/libsysprof/mapped-ring-buffer-source.c
Normal file
121
src/libsysprof/mapped-ring-buffer-source.c
Normal 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);
|
||||
}
|
||||
47
src/libsysprof/mapped-ring-buffer-source.h
Normal file
47
src/libsysprof/mapped-ring-buffer-source.h
Normal 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
|
||||
@ -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',
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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 *
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
41
src/libsysprof/sysprof-capture-autocleanups.h
Normal file
41
src/libsysprof/sysprof-capture-autocleanups.h
Normal 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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,8 @@
|
||||
# error "Only <sysprof.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "sysprof-capture-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -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 *
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "sysprof-map-lookaside.h"
|
||||
|
||||
struct _SysprofMapLookaside
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "sysprof-capture-types.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
# error "Only <sysprof.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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++)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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++)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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++)
|
||||
{
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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,
|
||||
)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user