diff options
-rw-r--r-- | config.h.meson | 3 | ||||
-rw-r--r-- | gdk/capture/sp-capture-types.h | 224 | ||||
-rw-r--r-- | gdk/capture/sp-capture-writer.c | 1123 | ||||
-rw-r--r-- | gdk/capture/sp-capture-writer.h | 132 | ||||
-rw-r--r-- | gdk/capture/sp-clock.c | 52 | ||||
-rw-r--r-- | gdk/capture/sp-clock.h | 55 | ||||
-rw-r--r-- | gdk/gdk.c | 4 | ||||
-rw-r--r-- | gdk/gdkprofiler.c | 64 | ||||
-rw-r--r-- | gdk/meson.build | 13 | ||||
-rw-r--r-- | meson.build | 11 | ||||
-rw-r--r-- | meson_options.txt | 2 |
11 files changed, 56 insertions, 1627 deletions
diff --git a/config.h.meson b/config.h.meson index 436e1a1501..e52badaede 100644 --- a/config.h.meson +++ b/config.h.meson @@ -130,6 +130,9 @@ /* Define to 1 if you have the <sys/param.h> header file. */ #mesondefine HAVE_SYS_PARAM_H +# +/* Have the sysprof-capture library */ +#mesondefine HAVE_SYSPROF_CAPTURE /* Define to 1 if you have the <sys/stat.h> header file. */ #mesondefine HAVE_SYS_STAT_H diff --git a/gdk/capture/sp-capture-types.h b/gdk/capture/sp-capture-types.h deleted file mode 100644 index 11be4de154..0000000000 --- a/gdk/capture/sp-capture-types.h +++ /dev/null @@ -1,224 +0,0 @@ -/* sp-capture-types.h - * - * Copyright © 2016 Christian Hergert <chergert@redhat.com> - * - * This file is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This file 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 Lesser 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/>. - */ - -#ifndef SP_CAPTURE_FORMAT_H -#define SP_CAPTURE_FORMAT_H - -#include <glib.h> - -#ifndef SP_DISABLE_GOBJECT -# include <glib-object.h> -#endif - -#include "sp-clock.h" - -G_BEGIN_DECLS - -#define SP_CAPTURE_MAGIC (GUINT32_TO_LE(0xFDCA975E)) -#define SP_CAPTURE_ALIGN (sizeof(SpCaptureAddress)) - -#if __WORDSIZE == 64 -# define SP_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE000000000000000) -# define SP_CAPTURE_ADDRESS_FORMAT "0x%016lx" -#else -# define SP_CAPTURE_JITMAP_MARK G_GUINT64_CONSTANT(0xE0000000) -# define SP_CAPTURE_ADDRESS_FORMAT "0x%016llx" -#endif - -#define SP_CAPTURE_CURRENT_TIME (sp_clock_get_current_time()) -#define SP_CAPTURE_COUNTER_INT64 0 -#define SP_CAPTURE_COUNTER_DOUBLE 1 - -typedef struct _SpCaptureReader SpCaptureReader; -typedef struct _SpCaptureWriter SpCaptureWriter; -typedef struct _SpCaptureCursor SpCaptureCursor; -typedef struct _SpCaptureCondition SpCaptureCondition; - -typedef guint64 SpCaptureAddress; - -typedef union -{ - gint64 v64; - gdouble vdbl; -} SpCaptureCounterValue; - -typedef enum -{ - SP_CAPTURE_FRAME_TIMESTAMP = 1, - SP_CAPTURE_FRAME_SAMPLE = 2, - SP_CAPTURE_FRAME_MAP = 3, - SP_CAPTURE_FRAME_PROCESS = 4, - SP_CAPTURE_FRAME_FORK = 5, - SP_CAPTURE_FRAME_EXIT = 6, - SP_CAPTURE_FRAME_JITMAP = 7, - SP_CAPTURE_FRAME_CTRDEF = 8, - SP_CAPTURE_FRAME_CTRSET = 9, - SP_CAPTURE_FRAME_MARK = 10, -} SpCaptureFrameType; - -#pragma pack(push, 1) - -typedef struct -{ - guint32 magic; - guint8 version; - guint32 little_endian : 1; - guint32 padding : 23; - gchar capture_time[64]; - gint64 time; - gint64 end_time; - gchar suffix[168]; -} SpCaptureFileHeader; - -typedef struct -{ - guint16 len; - gint16 cpu; - gint32 pid; - gint64 time; - guint8 type; - guint64 padding : 56; - guint8 data[0]; -} SpCaptureFrame; - -typedef struct -{ - SpCaptureFrame frame; - guint64 start; - guint64 end; - guint64 offset; - guint64 inode; - gchar filename[0]; -} SpCaptureMap; - -typedef struct -{ - SpCaptureFrame frame; - guint32 n_jitmaps; - guint8 data[0]; -} SpCaptureJitmap; - -typedef struct -{ - SpCaptureFrame frame; - gchar cmdline[0]; -} SpCaptureProcess; - -typedef struct -{ - SpCaptureFrame frame; - guint16 n_addrs; - guint64 padding : 48; - SpCaptureAddress addrs[0]; -} SpCaptureSample; - -typedef struct -{ - SpCaptureFrame frame; - GPid child_pid; -} SpCaptureFork; - -typedef struct -{ - SpCaptureFrame frame; -} SpCaptureExit; - -typedef struct -{ - SpCaptureFrame frame; -} SpCaptureTimestamp; - -typedef struct -{ - gchar category[32]; - gchar name[32]; - gchar description[52]; - guint32 id : 24; - guint8 type; - SpCaptureCounterValue value; -} SpCaptureCounter; - -typedef struct -{ - SpCaptureFrame frame; - guint16 n_counters; - guint64 padding : 48; - SpCaptureCounter counters[0]; -} SpCaptureFrameCounterDefine; - -typedef struct -{ - /* - * 96 bytes might seem a bit odd, but the counter frame header is 32 - * bytes. So this makes a nice 2-cacheline aligned size which is - * useful when the number of counters is rather small. - */ - guint32 ids[8]; - SpCaptureCounterValue values[8]; -} SpCaptureCounterValues; - -typedef struct -{ - SpCaptureFrame frame; - guint16 n_values; - guint64 padding : 48; - SpCaptureCounterValues values[0]; -} SpCaptureFrameCounterSet; - -typedef struct -{ - SpCaptureFrame frame; - gint64 duration; - gchar group[24]; - gchar name[40]; - gchar message[0]; -} SpCaptureMark; - -#pragma pack(pop) - -G_STATIC_ASSERT (sizeof (SpCaptureFileHeader) == 256); -G_STATIC_ASSERT (sizeof (SpCaptureFrame) == 24); -G_STATIC_ASSERT (sizeof (SpCaptureMap) == 56); -G_STATIC_ASSERT (sizeof (SpCaptureJitmap) == 28); -G_STATIC_ASSERT (sizeof (SpCaptureProcess) == 24); -G_STATIC_ASSERT (sizeof (SpCaptureSample) == 32); -G_STATIC_ASSERT (sizeof (SpCaptureFork) == 28); -G_STATIC_ASSERT (sizeof (SpCaptureExit) == 24); -G_STATIC_ASSERT (sizeof (SpCaptureTimestamp) == 24); -G_STATIC_ASSERT (sizeof (SpCaptureCounter) == 128); -G_STATIC_ASSERT (sizeof (SpCaptureCounterValues) == 96); -G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterDefine) == 32); -G_STATIC_ASSERT (sizeof (SpCaptureFrameCounterSet) == 32); -G_STATIC_ASSERT (sizeof (SpCaptureMark) == 96); - -static inline gint -sp_capture_address_compare (SpCaptureAddress a, - SpCaptureAddress b) -{ - if (a < b) - return -1; - if (a > b) - return 1; - else - return 0; -} - -G_END_DECLS - -#endif /* SP_CAPTURE_FORMAT_H */ - diff --git a/gdk/capture/sp-capture-writer.c b/gdk/capture/sp-capture-writer.c deleted file mode 100644 index 5f53379f87..0000000000 --- a/gdk/capture/sp-capture-writer.c +++ /dev/null @@ -1,1123 +0,0 @@ -/* sp-capture-writer.c - * - * Copyright © 2016 Christian Hergert <chergert@redhat.com> - * - * This file is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This file 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 Lesser 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/>. - */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE -#endif - -#include <errno.h> -#include <fcntl.h> -#include <glib/gstdio.h> -#include <string.h> -#include <sys/sendfile.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "capture/sp-capture-writer.h" - -#define DEFAULT_BUFFER_SIZE (getpagesize() * 64L) -#define INVALID_ADDRESS (G_GUINT64_CONSTANT(0)) - -typedef struct -{ - /* A pinter into the string buffer */ - const gchar *str; - - /* The unique address for the string */ - guint64 addr; -} SpCaptureJitmapBucket; - -struct _SpCaptureWriter -{ - /* - * This is our buffer location for incoming strings. This is used - * similarly to GStringChunk except there is only one-page, and after - * it fills, we flush to disk. - * - * This is paired with a closed hash table for deduplication. - */ - gchar addr_buf[4096*4]; - - /* Our hashtable for deduplication. */ - SpCaptureJitmapBucket addr_hash[512]; - - /* We keep the large fields above so that our allocation will be page - * alinged for the write buffer. This improves the performance of large - * writes to the target file-descriptor. - */ - volatile gint ref_count; - - /* - * Our address sequence counter. The value that comes from - * monotonically increasing this is OR'd with JITMAP_MARK to denote - * the address name should come from the JIT map. - */ - gsize addr_seq; - - /* Our position in addr_buf. */ - gsize addr_buf_pos; - - /* - * The number of hash table items in @addr_hash. This is an - * optimization so that we can avoid calculating the number of strings - * when flushing out the jitmap. - */ - guint addr_hash_size; - - /* Capture file handle */ - int fd; - - /* Our write buffer for fd */ - guint8 *buf; - gsize pos; - gsize len; - - /* counter id sequence */ - gint next_counter_id; - - /* Statistics while recording */ - SpCaptureStat stat; -}; - -#ifndef SP_DISABLE_GOBJECT -G_DEFINE_BOXED_TYPE (SpCaptureWriter, sp_capture_writer, - sp_capture_writer_ref, sp_capture_writer_unref) -#endif - -static inline void -sp_capture_writer_frame_init (SpCaptureFrame *frame_, - gint len, - gint cpu, - GPid pid, - gint64 time_, - SpCaptureFrameType type) -{ - g_assert (frame_ != NULL); - - frame_->len = len; - frame_->cpu = cpu; - frame_->pid = pid; - frame_->time = time_; - frame_->type = type; - frame_->padding = 0; -} - -static void -sp_capture_writer_finalize (SpCaptureWriter *self) -{ - if (self != NULL) - { - sp_capture_writer_flush (self); - close (self->fd); - g_free (self->buf); - g_free (self); - } -} - -SpCaptureWriter * -sp_capture_writer_ref (SpCaptureWriter *self) -{ - g_assert (self != NULL); - g_assert (self->ref_count > 0); - - g_atomic_int_inc (&self->ref_count); - - return self; -} - -void -sp_capture_writer_unref (SpCaptureWriter *self) -{ - g_assert (self != NULL); - g_assert (self->ref_count > 0); - - if (g_atomic_int_dec_and_test (&self->ref_count)) - sp_capture_writer_finalize (self); -} - -static gboolean -sp_capture_writer_flush_data (SpCaptureWriter *self) -{ - const guint8 *buf; - gssize written; - gsize to_write; - - g_assert (self != NULL); - g_assert (self->pos <= self->len); - g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0); - - buf = self->buf; - to_write = self->pos; - - while (to_write > 0) - { - written = write (self->fd, buf, to_write); - if (written < 0) - return FALSE; - - if (written == 0 && errno != EAGAIN) - return FALSE; - - g_assert (written <= (gssize)to_write); - - buf += written; - to_write -= written; - } - - self->pos = 0; - - return TRUE; -} - -static inline void -sp_capture_writer_realign (gsize *pos) -{ - *pos = (*pos + SP_CAPTURE_ALIGN - 1) & ~(SP_CAPTURE_ALIGN - 1); -} - -static inline gboolean -sp_capture_writer_ensure_space_for (SpCaptureWriter *self, - gsize len) -{ - /* Check for max frame size */ - if (len > G_MAXUSHORT) - return FALSE; - - if ((self->len - self->pos) < len) - { - if (!sp_capture_writer_flush_data (self)) - return FALSE; - } - - return TRUE; -} - -static inline gpointer -sp_capture_writer_allocate (SpCaptureWriter *self, - gsize *len) -{ - gpointer p; - - g_assert (self != NULL); - g_assert (len != NULL); - g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0); - - sp_capture_writer_realign (len); - - if (!sp_capture_writer_ensure_space_for (self, *len)) - return NULL; - - p = (gpointer)&self->buf[self->pos]; - - self->pos += *len; - - g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0); - - return p; -} - -static gboolean -sp_capture_writer_flush_jitmap (SpCaptureWriter *self) -{ - SpCaptureJitmap jitmap; - gssize r; - gsize len; - - g_assert (self != NULL); - - if (self->addr_hash_size == 0) - return TRUE; - - g_assert (self->addr_buf_pos > 0); - - len = sizeof jitmap + self->addr_buf_pos; - - sp_capture_writer_realign (&len); - - sp_capture_writer_frame_init (&jitmap.frame, - len, - -1, - getpid (), - SP_CAPTURE_CURRENT_TIME, - SP_CAPTURE_FRAME_JITMAP); - jitmap.n_jitmaps = self->addr_hash_size; - - if (sizeof jitmap != write (self->fd, &jitmap, sizeof jitmap)) - return FALSE; - - r = write (self->fd, self->addr_buf, len - sizeof jitmap); - if (r < 0 || (gsize)r != (len - sizeof jitmap)) - return FALSE; - - self->addr_buf_pos = 0; - self->addr_hash_size = 0; - memset (self->addr_hash, 0, sizeof self->addr_hash); - - self->stat.frame_count[SP_CAPTURE_FRAME_JITMAP]++; - - return TRUE; -} - -static gboolean -sp_capture_writer_lookup_jitmap (SpCaptureWriter *self, - const gchar *name, - SpCaptureAddress *addr) -{ - guint hash; - guint i; - - g_assert (self != NULL); - g_assert (name != NULL); - g_assert (addr != NULL); - - hash = g_str_hash (name) % G_N_ELEMENTS (self->addr_hash); - - for (i = hash; i < G_N_ELEMENTS (self->addr_hash); i++) - { - SpCaptureJitmapBucket *bucket = &self->addr_hash[i]; - - if (bucket->str == NULL) - return FALSE; - - if (strcmp (bucket->str, name) == 0) - { - *addr = bucket->addr; - return TRUE; - } - } - - for (i = 0; i < hash; i++) - { - SpCaptureJitmapBucket *bucket = &self->addr_hash[i]; - - if (bucket->str == NULL) - return FALSE; - - if (strcmp (bucket->str, name) == 0) - { - *addr = bucket->addr; - return TRUE; - } - } - - return FALSE; -} - -static SpCaptureAddress -sp_capture_writer_insert_jitmap (SpCaptureWriter *self, - const gchar *str) -{ - SpCaptureAddress addr; - gchar *dst; - gsize len; - guint hash; - guint i; - - g_assert (self != NULL); - g_assert (str != NULL); - g_assert ((self->pos % SP_CAPTURE_ALIGN) == 0); - - len = sizeof addr + strlen (str) + 1; - - if ((self->addr_hash_size == G_N_ELEMENTS (self->addr_hash)) || - ((sizeof self->addr_buf - self->addr_buf_pos) < len)) - { - if (!sp_capture_writer_flush_jitmap (self)) - return INVALID_ADDRESS; - - g_assert (self->addr_hash_size == 0); - g_assert (self->addr_buf_pos == 0); - } - - g_assert (self->addr_hash_size < G_N_ELEMENTS (self->addr_hash)); - g_assert (len > sizeof addr); - - /* Allocate the next unique address */ - addr = SP_CAPTURE_JITMAP_MARK | ++self->addr_seq; - - /* Copy the address into the buffer */ - dst = (gchar *)&self->addr_buf[self->addr_buf_pos]; - memcpy (dst, &addr, sizeof addr); - - /* - * Copy the string into the buffer, keeping dst around for - * when we insert into the hashtable. - */ - dst += sizeof addr; - memcpy (dst, str, len - sizeof addr); - - /* Advance our string cache position */ - self->addr_buf_pos += len; - g_assert (self->addr_buf_pos <= sizeof self->addr_buf); - - /* Now place the address into the hashtable */ - hash = g_str_hash (str) % G_N_ELEMENTS (self->addr_hash); - - /* Start from the current hash bucket and go forward */ - for (i = hash; i < G_N_ELEMENTS (self->addr_hash); i++) - { - SpCaptureJitmapBucket *bucket = &self->addr_hash[i]; - - if (G_LIKELY (bucket->str == NULL)) - { - bucket->str = dst; - bucket->addr = addr; - self->addr_hash_size++; - return addr; - } - } - - /* Wrap around to the beginning */ - for (i = 0; i < hash; i++) - { - SpCaptureJitmapBucket *bucket = &self->addr_hash[i]; - - if (G_LIKELY (bucket->str == NULL)) - { - bucket->str = dst; - bucket->addr = addr; - self->addr_hash_size++; - return addr; - } - } - - g_assert_not_reached (); - - return INVALID_ADDRESS; -} - -SpCaptureWriter * -sp_capture_writer_new_from_fd (int fd, - gsize buffer_size) -{ - g_autofree gchar *nowstr = NULL; - SpCaptureWriter *self; - SpCaptureFileHeader *header; - GTimeVal tv; - gsize header_len = sizeof(*header); - - if (buffer_size == 0) - buffer_size = DEFAULT_BUFFER_SIZE; - - g_assert (fd != -1); - g_assert (buffer_size % getpagesize() == 0); - - if (ftruncate (fd, 0) != 0) - return NULL; - - self = g_new0 (SpCaptureWriter, 1); - self->ref_count = 1; - self->fd = fd; - self->buf = (guint8 *)g_malloc0 (buffer_size); - self->len = buffer_size; - self->next_counter_id = 1; - - g_get_current_time (&tv); - nowstr = g_time_val_to_iso8601 (&tv); - - header = sp_capture_writer_allocate (self, &header_len); - - if (header == NULL) - { - sp_capture_writer_finalize (self); - return NULL; - } - - header->magic = SP_CAPTURE_MAGIC; - header->version = 1; -#ifdef G_LITTLE_ENDIAN - header->little_endian = TRUE; -#else - header->little_endian = FALSE; -#endif - header->padding = 0; - g_strlcpy (header->capture_time, nowstr, sizeof header->capture_time); - header->time = SP_CAPTURE_CURRENT_TIME; - header->end_time = 0; - memset (header->suffix, 0, sizeof header->suffix); - - if (!sp_capture_writer_flush_data (self)) - { - sp_capture_writer_finalize (self); - return NULL; - } - - g_assert (self->pos == 0); - g_assert (self->len > 0); - g_assert (self->len % getpagesize() == 0); - g_assert (self->buf != NULL); - g_assert (self->addr_hash_size == 0); - g_assert (self->fd != -1); - - return self; -} - -SpCaptureWriter * -sp_capture_writer_new (const gchar *filename, - gsize buffer_size) -{ - SpCaptureWriter *self; - int fd; - - g_assert (filename != NULL); - g_assert (buffer_size % getpagesize() == 0); - - if ((-1 == (fd = open (filename, O_CREAT | O_RDWR, 0640))) || - (-1 == ftruncate (fd, 0L))) - return NULL; - - self = sp_capture_writer_new_from_fd (fd, buffer_size); - - if (self == NULL) - close (fd); - - return self; -} - -gboolean -sp_capture_writer_add_map (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - guint64 start, - guint64 end, - guint64 offset, - guint64 inode, - const gchar *filename) -{ - SpCaptureMap *ev; - gsize len; - - if (filename == NULL) - filename = ""; - - g_assert (self != NULL); - g_assert (filename != NULL); - - len = sizeof *ev + strlen (filename) + 1; - - ev = (SpCaptureMap *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_MAP); - ev->start = start; - ev->end = end; - ev->offset = offset; - ev->inode = inode; - - g_strlcpy (ev->filename, filename, len - sizeof *ev); - ev->filename[len - sizeof *ev - 1] = '\0'; - - self->stat.frame_count[SP_CAPTURE_FRAME_MAP]++; - - return TRUE; -} - -gboolean -sp_capture_writer_add_mark (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - guint64 duration, - const gchar *group, - const gchar *name, - const gchar *message) -{ - SpCaptureMark *ev; - gsize message_len; - gsize len; - - g_assert (self != NULL); - g_assert (name != NULL); - g_assert (group != NULL); - - if (message == NULL) - message = ""; - message_len = strlen (message) + 1; - - len = sizeof *ev + message_len; - ev = (SpCaptureMark *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_MARK); - - ev->duration = duration; - g_strlcpy (ev->group, group, sizeof ev->group); - g_strlcpy (ev->name, name, sizeof ev->name); - memcpy (ev->message, message, message_len); - - self->stat.frame_count[SP_CAPTURE_FRAME_MARK]++; - - return TRUE; -} - -SpCaptureAddress -sp_capture_writer_add_jitmap (SpCaptureWriter *self, - const gchar *name) -{ - SpCaptureAddress addr = INVALID_ADDRESS; - - if (name == NULL) - name = ""; - - g_assert (self != NULL); - g_assert (name != NULL); - - if (!sp_capture_writer_lookup_jitmap (self, name, &addr)) - addr = sp_capture_writer_insert_jitmap (self, name); - - return addr; -} - -gboolean -sp_capture_writer_add_process (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const gchar *cmdline) -{ - SpCaptureProcess *ev; - gsize len; - - if (cmdline == NULL) - cmdline = ""; - - g_assert (self != NULL); - g_assert (cmdline != NULL); - - len = sizeof *ev + strlen (cmdline) + 1; - - ev = (SpCaptureProcess *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_PROCESS); - - g_strlcpy (ev->cmdline, cmdline, len - sizeof *ev); - ev->cmdline[len - sizeof *ev - 1] = '\0'; - - self->stat.frame_count[SP_CAPTURE_FRAME_PROCESS]++; - - return TRUE; -} - -gboolean -sp_capture_writer_add_sample (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const SpCaptureAddress *addrs, - guint n_addrs) -{ - SpCaptureSample *ev; - gsize len; - - g_assert (self != NULL); - - len = sizeof *ev + (n_addrs * sizeof (SpCaptureAddress)); - - ev = (SpCaptureSample *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_SAMPLE); - ev->n_addrs = n_addrs; - - memcpy (ev->addrs, addrs, (n_addrs * sizeof (SpCaptureAddress))); - - self->stat.frame_count[SP_CAPTURE_FRAME_SAMPLE]++; - - return TRUE; -} - -gboolean -sp_capture_writer_add_fork (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - GPid child_pid) -{ - SpCaptureFork *ev; - gsize len = sizeof *ev; - - g_assert (self != NULL); - - ev = (SpCaptureFork *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_FORK); - ev->child_pid = child_pid; - - self->stat.frame_count[SP_CAPTURE_FRAME_FORK]++; - - return TRUE; -} - -gboolean -sp_capture_writer_add_exit (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid) -{ - SpCaptureExit *ev; - gsize len = sizeof *ev; - - g_assert (self != NULL); - - ev = (SpCaptureExit *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_EXIT); - - self->stat.frame_count[SP_CAPTURE_FRAME_EXIT]++; - - return TRUE; -} - -gboolean -sp_capture_writer_add_timestamp (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid) -{ - SpCaptureTimestamp *ev; - gsize len = sizeof *ev; - - g_assert (self != NULL); - - ev = (SpCaptureTimestamp *)sp_capture_writer_allocate (self, &len); - if (!ev) - return FALSE; - - sp_capture_writer_frame_init (&ev->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_TIMESTAMP); - - self->stat.frame_count[SP_CAPTURE_FRAME_TIMESTAMP]++; - - return TRUE; -} - -static gboolean -sp_capture_writer_flush_end_time (SpCaptureWriter *self) -{ - gint64 end_time = SP_CAPTURE_CURRENT_TIME; - ssize_t ret; - - g_assert (self != NULL); - - /* This field is opportunistic, so a failure is okay. */ - -again: - ret = pwrite (self->fd, - &end_time, - sizeof (end_time), - G_STRUCT_OFFSET (SpCaptureFileHeader, end_time)); - - if (ret < 0 && errno == EAGAIN) - goto again; - - return TRUE; -} - -gboolean -sp_capture_writer_flush (SpCaptureWriter *self) -{ - g_assert (self != NULL); - - return (sp_capture_writer_flush_jitmap (self) && - sp_capture_writer_flush_data (self) && - sp_capture_writer_flush_end_time (self)); -} - -/** - * sp_capture_writer_save_as: - * @self: A #SpCaptureWriter - * @filename: the file to save the capture as - * @error: a location for a #GError or %NULL. - * - * Saves the captured data as the file @filename. - * - * This is primarily useful if the writer was created with a memory-backed - * file-descriptor such as a memfd or tmpfs file on Linux. - * - * Returns: %TRUE if successful, otherwise %FALSE and @error is set. - */ -gboolean -sp_capture_writer_save_as (SpCaptureWriter *self, - const gchar *filename, - GError **error) -{ - gsize to_write; - off_t in_off; - off_t pos; - int fd = -1; - - g_assert (self != NULL); - g_assert (self->fd != -1); - g_assert (filename != NULL); - - if (-1 == (fd = open (filename, O_CREAT | O_RDWR, 0640))) - goto handle_errno; - - if (!sp_capture_writer_flush (self)) - goto handle_errno; - - if (-1 == (pos = lseek (self->fd, 0L, SEEK_CUR))) - goto handle_errno; - - to_write = pos; - in_off = 0; - - while (to_write > 0) - { - gssize written; - - written = sendfile (fd, self->fd, &in_off, pos); - - if (written < 0) - goto handle_errno; - - if (written == 0 && errno != EAGAIN) - goto handle_errno; - - g_assert (written <= (gssize)to_write); - - to_write -= written; - } - - close (fd); - - return TRUE; - -handle_errno: - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - - if (fd != -1) - { - close (fd); - g_unlink (filename); - } - - return FALSE; -} - -/** - * _sp_capture_writer_splice_from_fd: - * @self: An #SpCaptureWriter - * @fd: the fd to read from. - * @error: A location for a #GError, or %NULL. - * - * This is internal API for SpCaptureWriter and SpCaptureReader to - * communicate when splicing a reader into a writer. - * - * This should not be used outside of #SpCaptureReader or - * #SpCaptureWriter. - * - * This will not advance the position of @fd. - * - * Returns: %TRUE if successful; otherwise %FALSE and @error is set. - */ -gboolean -_sp_capture_writer_splice_from_fd (SpCaptureWriter *self, - int fd, - GError **error) -{ - struct stat stbuf; - off_t in_off; - gsize to_write; - - g_assert (self != NULL); - g_assert (self->fd != -1); - - if (-1 == fstat (fd, &stbuf)) - goto handle_errno; - - if (stbuf.st_size < 256) - { - g_set_error (error, - G_FILE_ERROR, - G_FILE_ERROR_INVAL, - "Cannot splice, possibly corrupt file."); - return FALSE; - } - - in_off = 256; - to_write = stbuf.st_size - in_off; - - while (to_write > 0) - { - gssize written; - - written = sendfile (self->fd, fd, &in_off, to_write); - - if (written < 0) - goto handle_errno; - - if (written == 0 && errno != EAGAIN) - goto handle_errno; - - g_assert (written <= (gssize)to_write); - - to_write -= written; - } - - return TRUE; - -handle_errno: - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - - return FALSE; -} - -/** - * sp_capture_writer_splice: - * @self: An #SpCaptureWriter - * @dest: An #SpCaptureWriter - * @error: A location for a #GError, or %NULL. - * - * This function will copy the capture @self into the capture @dest. This - * tries to be semi-efficient by using sendfile() to copy the contents between - * the captures. @self and @dest will be flushed before the contents are copied - * into the @dest file-descriptor. - * - * Returns: %TRUE if successful, otherwise %FALSE and and @error is set. - */ -gboolean -sp_capture_writer_splice (SpCaptureWriter *self, - SpCaptureWriter *dest, - GError **error) -{ - gboolean ret; - off_t pos; - - g_assert (self != NULL); - g_assert (self->fd != -1); - g_assert (dest != NULL); - g_assert (dest->fd != -1); - - /* Flush before writing anything to ensure consistency */ - if (!sp_capture_writer_flush (self) || !sp_capture_writer_flush (dest)) - goto handle_errno; - - /* Track our current position so we can reset */ - if ((off_t)-1 == (pos = lseek (self->fd, 0L, SEEK_CUR))) - goto handle_errno; - - /* Perform the splice */ - ret = _sp_capture_writer_splice_from_fd (dest, self->fd, error); - - /* Now reset or file-descriptor position (it should be the same */ - if (pos != lseek (self->fd, pos, SEEK_SET)) - { - ret = FALSE; - goto handle_errno; - } - - return ret; - -handle_errno: - g_set_error (error, - G_FILE_ERROR, - g_file_error_from_errno (errno), - "%s", g_strerror (errno)); - - return FALSE; -} - -/** - * sp_capture_writer_stat: - * @self: A #SpCaptureWriter - * @stat: (out): A location for an #SpCaptureStat - * - * This function will fill @stat with statistics generated while capturing - * the profiler session. - */ -void -sp_capture_writer_stat (SpCaptureWriter *self, - SpCaptureStat *stat) -{ - g_return_if_fail (self != NULL); - g_return_if_fail (stat != NULL); - - *stat = self->stat; -} - -gboolean -sp_capture_writer_define_counters (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const SpCaptureCounter *counters, - guint n_counters) -{ - SpCaptureFrameCounterDefine *def; - gsize len; - guint i; - - g_assert (self != NULL); - g_assert (counters != NULL); - - if (n_counters == 0) - return TRUE; - - len = sizeof *def + (sizeof *counters * n_counters); - - def = (SpCaptureFrameCounterDefine *)sp_capture_writer_allocate (self, &len); - if (!def) - return FALSE; - - sp_capture_writer_frame_init (&def->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_CTRDEF); - def->padding = 0; - def->n_counters = n_counters; - - for (i = 0; i < n_counters; i++) - def->counters[i] = counters[i]; - - self->stat.frame_count[SP_CAPTURE_FRAME_CTRDEF]++; - - return TRUE; -} - -gboolean -sp_capture_writer_set_counters (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const guint *counters_ids, - const SpCaptureCounterValue *values, - guint n_counters) -{ - SpCaptureFrameCounterSet *set; - gsize len; - guint n_groups; - guint group; - guint field; - guint i; - - g_assert (self != NULL); - g_assert (counters_ids != NULL); - g_assert (values != NULL || !n_counters); - - if (n_counters == 0) - return TRUE; - - /* Determine how many value groups we need */ - n_groups = n_counters / G_N_ELEMENTS (set->values[0].values); - if ((n_groups * G_N_ELEMENTS (set->values[0].values)) != n_counters) - n_groups++; - - len = sizeof *set + (n_groups * sizeof (SpCaptureCounterValues)); - - set = (SpCaptureFrameCounterSet *)sp_capture_writer_allocate (self, &len); - if (!set) - return FALSE; - - memset (set, 0, len); - - sp_capture_writer_frame_init (&set->frame, - len, - cpu, - pid, - time, - SP_CAPTURE_FRAME_CTRSET); - set->padding = 0; - set->n_values = n_groups; - - for (i = 0, group = 0, field = 0; i < n_counters; i++) - { - set->values[group].ids[field] = counters_ids[i]; - set->values[group].values[field] = values[i]; - - field++; - - if (field == G_N_ELEMENTS (set->values[0].values)) - { - field = 0; - group++; - } - } - - self->stat.frame_count[SP_CAPTURE_FRAME_CTRSET]++; - - return TRUE; -} - -gint -sp_capture_writer_request_counter (SpCaptureWriter *self, - guint n_counters) -{ - gint ret; - - g_assert (self != NULL); - - ret = self->next_counter_id; - self->next_counter_id += n_counters; - - return ret; -} - diff --git a/gdk/capture/sp-capture-writer.h b/gdk/capture/sp-capture-writer.h deleted file mode 100644 index f29b18a798..0000000000 --- a/gdk/capture/sp-capture-writer.h +++ /dev/null @@ -1,132 +0,0 @@ -/* sp-capture-writer.h - * - * Copyright © 2016 Christian Hergert <chergert@redhat.com> - * - * This file is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This file 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 Lesser 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/>. - */ - -#ifndef SP_CAPTURE_WRITER_H -#define SP_CAPTURE_WRITER_H - -#include "capture/sp-capture-types.h" - -G_BEGIN_DECLS - -typedef struct _SpCaptureWriter SpCaptureWriter; - -typedef struct -{ - /* - * The number of frames indexed by SpCaptureFrameType - */ - gsize frame_count[16]; - - /* - * Padding for future expansion. - */ - gsize padding[48]; -} SpCaptureStat; - -SpCaptureWriter *sp_capture_writer_new (const gchar *filename, - gsize buffer_size); -SpCaptureWriter *sp_capture_writer_new_from_fd (int fd, - gsize buffer_size); -SpCaptureWriter *sp_capture_writer_ref (SpCaptureWriter *self); -void sp_capture_writer_unref (SpCaptureWriter *self); -void sp_capture_writer_stat (SpCaptureWriter *self, - SpCaptureStat *stat); -gboolean sp_capture_writer_add_map (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - guint64 start, - guint64 end, - guint64 offset, - guint64 inode, - const gchar *filename); -gboolean sp_capture_writer_add_mark (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - guint64 duration, - const gchar *group, - const gchar *name, - const gchar *message); -guint64 sp_capture_writer_add_jitmap (SpCaptureWriter *self, - const gchar *name); -gboolean sp_capture_writer_add_process (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const gchar *cmdline); -gboolean sp_capture_writer_add_sample (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const SpCaptureAddress *addrs, - guint n_addrs); -gboolean sp_capture_writer_add_fork (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - GPid child_pid); -gboolean sp_capture_writer_add_exit (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid); -gboolean sp_capture_writer_add_timestamp (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid); -gboolean sp_capture_writer_define_counters (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const SpCaptureCounter *counters, - guint n_counters); -gboolean sp_capture_writer_set_counters (SpCaptureWriter *self, - gint64 time, - gint cpu, - GPid pid, - const guint *counters_ids, - const SpCaptureCounterValue *values, - guint n_counters); -gboolean sp_capture_writer_flush (SpCaptureWriter *self); -gboolean sp_capture_writer_save_as (SpCaptureWriter *self, - const gchar *filename, - GError **error); -gint sp_capture_writer_request_counter (SpCaptureWriter *self, - guint n_counters); -SpCaptureReader *sp_capture_writer_create_reader (SpCaptureWriter *self, - GError **error); -gboolean sp_capture_writer_splice (SpCaptureWriter *self, - SpCaptureWriter *dest, - GError **error); -gboolean _sp_capture_writer_splice_from_fd (SpCaptureWriter *self, - int fd, - GError **error) G_GNUC_INTERNAL; - -#ifndef SP_DISABLE_GOBJECT -# define SP_TYPE_CAPTURE_WRITER (sp_capture_writer_get_type()) - GType sp_capture_writer_get_type (void); -#endif - -#if GLIB_CHECK_VERSION(2, 44, 0) - G_DEFINE_AUTOPTR_CLEANUP_FUNC (SpCaptureWriter, sp_capture_writer_unref) -#endif - -G_END_DECLS - -#endif /* SP_CAPTURE_WRITER_H */ - diff --git a/gdk/capture/sp-clock.c b/gdk/capture/sp-clock.c deleted file mode 100644 index b53dafb741..0000000000 --- a/gdk/capture/sp-clock.c +++ /dev/null @@ -1,52 +0,0 @@ -/* sp-clock.c - * - * Copyright © 2016 Christian Hergert <chergert@redhat.com> - * - * This file is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This file 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 Lesser 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/>. - */ - -#include "sp-clock.h" - -gint sp_clock = -1; - -void -sp_clock_init (void) -{ - static const gint clock_ids[] = { - CLOCK_MONOTONIC, - CLOCK_MONOTONIC_RAW, - CLOCK_MONOTONIC_COARSE, - CLOCK_REALTIME_COARSE, - CLOCK_REALTIME, - }; - guint i; - - if (sp_clock != -1) - return; - - for (i = 0; i < G_N_ELEMENTS (clock_ids); i++) - { - struct timespec ts; - int clock_id = clock_ids [i]; - - if (0 == clock_gettime (clock_id, &ts)) - { - sp_clock = clock_id; - return; - } - } - - g_assert_not_reached (); -} - diff --git a/gdk/capture/sp-clock.h b/gdk/capture/sp-clock.h deleted file mode 100644 index 09dd11809f..0000000000 --- a/gdk/capture/sp-clock.h +++ /dev/null @@ -1,55 +0,0 @@ -/* sp-clock.h - * - * Copyright © 2016 Christian Hergert <chergert@redhat.com> - * - * This file is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This file 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 Lesser 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/>. - */ - -#ifndef SP_CLOCK_H -#define SP_CLOCK_H - -#include <glib.h> -#include <time.h> - -G_BEGIN_DECLS - -typedef gint SpClock; -typedef gint64 SpTimeStamp; -typedef gint32 SpTimeSpan; - -extern SpClock sp_clock; - -static inline SpTimeStamp -sp_clock_get_current_time (void) -{ - struct timespec ts; - - clock_gettime (sp_clock, &ts); - - return (ts.tv_sec * G_GINT64_CONSTANT (1000000000)) + ts.tv_nsec; -} - -static inline SpTimeSpan -sp_clock_get_relative_time (SpTimeStamp epoch) -{ - return sp_clock_get_current_time () - epoch; -} - -void sp_clock_init (void); - -G_END_DECLS - -#endif /* SP_CLOCK_H */ - - @@ -213,8 +213,8 @@ gdk_pre_parse (void) (GDebugKey *) gdk_debug_keys, G_N_ELEMENTS (gdk_debug_keys)); - if (g_getenv ("SYSPROF_TRACE_FD")) - gdk_profiler_start (atoi (g_getenv ("SYSPROF_TRACE_FD"))); + if (g_getenv ("GTK_TRACE_FD")) + gdk_profiler_start (atoi (g_getenv ("GTK_TRACE_FD"))); else if (g_getenv ("GTK_TRACE")) gdk_profiler_start (-1); } diff --git a/gdk/gdkprofiler.c b/gdk/gdkprofiler.c index 15a54ad05f..93055ac9a8 100644 --- a/gdk/gdkprofiler.c +++ b/gdk/gdkprofiler.c @@ -30,18 +30,18 @@ #include "gdkprofilerprivate.h" #include "gdkframeclockprivate.h" -#ifndef G_OS_WIN32 +#ifdef HAVE_SYSPROF_CAPTURE -#include "capture/sp-capture-writer.h" +#include <sysprof-capture.h> -static SpCaptureWriter *writer = NULL; +static SysprofCaptureWriter *writer = NULL; static gboolean running = FALSE; static void profiler_stop (void) { if (writer) - sp_capture_writer_unref (writer); + sysprof_capture_writer_unref (writer); } void @@ -50,7 +50,7 @@ gdk_profiler_start (int fd) if (writer) return; - sp_clock_init (); + sysprof_clock_init (); if (fd == -1) { @@ -58,11 +58,11 @@ gdk_profiler_start (int fd) filename = g_strdup_printf ("gtk.%d.syscap", getpid ()); g_print ("Writing profiling data to %s\n", filename); - writer = sp_capture_writer_new (filename, 16*1024); + writer = sysprof_capture_writer_new (filename, 16*1024); g_free (filename); } else if (fd > 2) - writer = sp_capture_writer_new_from_fd (fd, 16*1024); + writer = sysprof_capture_writer_new_from_fd (fd, 16*1024); if (writer) running = TRUE; @@ -91,11 +91,11 @@ gdk_profiler_add_mark (gint64 start, if (!running) return; - sp_capture_writer_add_mark (writer, - start, - -1, getpid (), - duration, - "gtk", name, message); + sysprof_capture_writer_add_mark (writer, + start, + -1, getpid (), + duration, + "gtk", name, message); } static guint @@ -103,24 +103,24 @@ define_counter (const char *name, const char *description, int type) { - SpCaptureCounter counter; + SysprofCaptureCounter counter; if (!writer) return 0; - counter.id = (guint) sp_capture_writer_request_counter (writer, 1); + counter.id = (guint) sysprof_capture_writer_request_counter (writer, 1); counter.type = type; counter.value.vdbl = 0; g_strlcpy (counter.category, "gtk", sizeof counter.category); g_strlcpy (counter.name, name, sizeof counter.name); g_strlcpy (counter.description, description, sizeof counter.name); - sp_capture_writer_define_counters (writer, - SP_CAPTURE_CURRENT_TIME, - -1, - getpid (), - &counter, - 1); + sysprof_capture_writer_define_counters (writer, + SYSPROF_CAPTURE_CURRENT_TIME, + -1, + getpid (), + &counter, + 1); return counter.id; } @@ -129,14 +129,14 @@ guint gdk_profiler_define_counter (const char *name, const char *description) { - return define_counter (name, description, SP_CAPTURE_COUNTER_DOUBLE); + return define_counter (name, description, SYSPROF_CAPTURE_COUNTER_DOUBLE); } guint gdk_profiler_define_int_counter (const char *name, const char *description) { - return define_counter (name, description, SP_CAPTURE_COUNTER_INT64); + return define_counter (name, description, SYSPROF_CAPTURE_COUNTER_INT64); } void @@ -144,16 +144,16 @@ gdk_profiler_set_counter (guint id, gint64 time, double val) { - SpCaptureCounterValue value; + SysprofCaptureCounterValue value; if (!running) return; value.vdbl = val; - sp_capture_writer_set_counters (writer, - time, - -1, getpid (), - &id, &value, 1); + sysprof_capture_writer_set_counters (writer, + time, + -1, getpid (), + &id, &value, 1); } void @@ -161,16 +161,16 @@ gdk_profiler_set_int_counter (guint id, gint64 time, gint64 val) { - SpCaptureCounterValue value; + SysprofCaptureCounterValue value; if (!running) return; value.v64 = val; - sp_capture_writer_set_counters (writer, - time, - -1, getpid (), - &id, &value, 1); + sysprof_capture_writer_set_counters (writer, + time, + -1, getpid (), + &id, &value, 1); } #else diff --git a/gdk/meson.build b/gdk/meson.build index 7380961ccf..21c38df33e 100644 --- a/gdk/meson.build +++ b/gdk/meson.build @@ -47,13 +47,6 @@ gdk_public_sources = files([ 'gdkprofiler.c' ]) -if not win32_enabled - gdk_public_sources += files([ - 'capture/sp-capture-writer.c', - 'capture/sp-clock.c' - ]) -endif - gdk_public_headers = files([ 'gdk-autocleanup.h', 'gdk.h', @@ -188,6 +181,12 @@ gdk_deps = [ vulkan_dep, ] +if profiler_enabled + if profiler_dep.found() + gdk_deps += [profiler_dep] + endif +endif + # add generated gdk sources gdk_sources += [ gdkconfig, diff --git a/meson.build b/meson.build index 97cc7fdf28..34cf3cfcc5 100644 --- a/meson.build +++ b/meson.build @@ -666,6 +666,16 @@ if cloudproviders_enabled endif endif +profiler_enabled = get_option('profiler') +if profiler_enabled + profiler_dep = dependency('sysprof-capture-3', static: true, required: true) + if profiler_dep.found() + cdata.set('HAVE_SYSPROF_CAPTURE', profiler_dep.found()) + else + error('Profiler support not found, but was explicitly requested.') + endif +endif + graphene_dep_type = graphene_dep.type_name() if graphene_dep_type == 'pkgconfig' graphene_has_sse2 = graphene_dep.get_pkgconfig_variable('graphene_has_sse2') == '1' @@ -811,6 +821,7 @@ summary = [ ' Vulkan support: @0@'.format(have_vulkan), ' Cloud support: @0@'.format(get_option('cloudproviders')), ' Colord support: @0@'.format(get_option('colord')), + ' Profiler: @0@'.format(get_option('profiler')), ' Introspection: @0@'.format(get_option('introspection')), ' Documentation: @0@'.format(get_option('documentation')), ' Man pages: @0@'.format(get_option('man-pages')), diff --git a/meson_options.txt b/meson_options.txt index a189ee2cba..20dc5d0338 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -21,6 +21,8 @@ option('xinerama', type: 'combo', choices : ['yes', 'no', 'auto'], value : 'auto description : 'Enable support for the Xinerama extension') option('cloudproviders', type: 'boolean', value: false, description : 'Enable the cloudproviders support') +option('profiler', type: 'boolean', value: false, + description : 'Enable profiler support') # Print backends option('print-backends', type : 'string', value : 'cups,file', |