Skip to content

Commit

Permalink
Add usertime sampler
Browse files Browse the repository at this point in the history
  • Loading branch information
Your Name committed May 20, 2024
1 parent e42fa02 commit 9390984
Show file tree
Hide file tree
Showing 9 changed files with 761 additions and 0 deletions.
95 changes: 95 additions & 0 deletions libs/gum/prof/gumusertimesampler-darwin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2011-2022 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#include "gumusertimesampler.h"

#include <mach/mach.h>

struct _GumUserTimeSampler
{
GObject parent;
GumThreadId thread_id;
};

static void gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data);
static GumSample gum_user_time_sampler_sample (GumSampler * sampler);

G_DEFINE_TYPE_EXTENDED (GumUserTimeSampler,
gum_user_time_sampler,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (GUM_TYPE_SAMPLER,
gum_user_time_sampler_iface_init))

static void
gum_user_time_sampler_class_init (GumUserTimeSamplerClass * klass)
{
}

static void
gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data)
{
GumSamplerInterface * iface = g_iface;

iface->sample = gum_user_time_sampler_sample;
}

static void
gum_user_time_sampler_init (GumUserTimeSampler * self)
{
}

GumSampler *
gum_user_time_sampler_new (void)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = gum_process_get_current_thread_id ();

return GUM_SAMPLER (sampler);
}

GumSampler *
gum_user_time_sampler_new_with_thread_id (GumThreadId thread_id)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = thread_id;

return GUM_SAMPLER (sampler);
}

gboolean
gum_user_time_sampler_is_available (GumUserTimeSampler * self)
{
return TRUE;
}

static GumSample
gum_user_time_sampler_sample (GumSampler * sampler)
{
GumUserTimeSampler * user_time_sampler = (GumUserTimeSampler *) sampler;
mach_port_t port = (mach_port_t) user_time_sampler->thread_id;
thread_basic_info_data_t info;
mach_msg_type_number_t info_count = THREAD_BASIC_INFO_COUNT;
kern_return_t kr;

kr = thread_info (port, THREAD_BASIC_INFO, (thread_info_t) &info,
&info_count);

if (kr != KERN_SUCCESS)
{
g_printerr ("thread_info failed: %d\n", kr);
return 0;
}

return ((GumSample) info.user_time.seconds * G_USEC_PER_SEC) +
info.user_time.microseconds;
}
77 changes: 77 additions & 0 deletions libs/gum/prof/gumusertimesampler-freebsd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2022 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#include "gumusertimesampler.h"

struct _GumUserTimeSampler
{
GObject parent;
GumThreadId thread_id;
};

static void gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data);
static GumSample gum_user_time_sampler_sample (GumSampler * sampler);

G_DEFINE_TYPE_EXTENDED (GumUserTimeSampler,
gum_user_time_sampler,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (GUM_TYPE_SAMPLER,
gum_user_time_sampler_iface_init))

static void
gum_user_time_sampler_class_init (GumUserTimeSamplerClass * klass)
{
}

static void
gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data)
{
GumSamplerInterface * iface = g_iface;

iface->sample = gum_user_time_sampler_sample;
}

static void
gum_user_time_sampler_init (GumUserTimeSampler * self)
{
}

GumSampler *
gum_user_time_sampler_new (void)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = gum_process_get_current_thread_id ();

return GUM_SAMPLER (sampler);
}

GumSampler *
gum_user_time_sampler_new_with_thread_id (GumThreadId thread_id)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = thread_id;

return GUM_SAMPLER (sampler);
}

gboolean
gum_user_time_sampler_is_available (GumUserTimeSampler * self)
{
return FALSE;
}

static GumSample
gum_user_time_sampler_sample (GumSampler * sampler)
{
return 0;
}
124 changes: 124 additions & 0 deletions libs/gum/prof/gumusertimesampler-linux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright (C) 2015-2018 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#include "gumusertimesampler.h"

#include <unistd.h>

struct _GumUserTimeSampler
{
GObject parent;
GumThreadId thread_id;
};

static void gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data);
static GumSample gum_user_time_sampler_sample (GumSampler * sampler);

G_DEFINE_TYPE_EXTENDED (GumUserTimeSampler,
gum_user_time_sampler,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (GUM_TYPE_SAMPLER,
gum_user_time_sampler_iface_init))

static void
gum_user_time_sampler_class_init (GumUserTimeSamplerClass * klass)
{
}

static void
gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data)
{
GumSamplerInterface * iface = g_iface;

iface->sample = gum_user_time_sampler_sample;
}

static void
gum_user_time_sampler_init (GumUserTimeSampler * self)
{
}

GumSampler *
gum_user_time_sampler_new (void)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = gum_process_get_current_thread_id ();

return GUM_SAMPLER (sampler);
}

GumSampler *
gum_user_time_sampler_new_with_thread_id (GumThreadId thread_id)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = thread_id;

return GUM_SAMPLER (sampler);
}

gboolean
gum_user_time_sampler_is_available (GumUserTimeSampler * self)
{
return TRUE;
}

static GumSample
gum_user_time_sampler_sample (GumSampler * sampler)
{
GumUserTimeSampler * user_time_sampler = (GumUserTimeSampler *) sampler;
int thread_id = (int) user_time_sampler->thread_id;
gchar * stat_path = NULL;
gchar * stat_contents = NULL;
gsize stat_len;
GError * error = NULL;
gchar ** fields = NULL;
gchar ** iterator;
guint num_fields = 0;
guint64 clock_ticks;
long ticks_per_sec;
GumSample utime = 0;

stat_path = g_strdup_printf ("/proc/%d/task/%d/stat", getpid (), thread_id);

if (!g_file_get_contents (stat_path, &stat_contents, &stat_len, &error))
{
g_printerr ("Error reading file: %s\n", error->message);
goto beach;
}

fields = g_strsplit (stat_contents, " ", -1);

for (iterator = fields; *iterator != NULL; iterator++)
{
num_fields++;
}

if (num_fields < 14)
{
g_printerr ("Not enough fields: %u in '%s'\n", num_fields, stat_contents);
goto beach;
}

clock_ticks = g_ascii_strtoull (fields[13], NULL, 10);

ticks_per_sec = sysconf (_SC_CLK_TCK);

utime = (clock_ticks * 1000000) / ticks_per_sec;

beach:
g_strfreev (fields);
g_free (stat_contents);
g_free (stat_path);

return utime;
}
78 changes: 78 additions & 0 deletions libs/gum/prof/gumusertimesampler-qnx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2015-2018 Ole André Vadla Ravnås <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/

#include "gumusertimesampler.h"

struct _GumUserTimeSampler
{
GObject parent;
GumThreadId thread_id;
};

static void gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data);
static GumSample gum_user_time_sampler_sample (GumSampler * sampler);

G_DEFINE_TYPE_EXTENDED (GumUserTimeSampler,
gum_user_time_sampler,
G_TYPE_OBJECT,
0,
G_IMPLEMENT_INTERFACE (GUM_TYPE_SAMPLER,
gum_user_time_sampler_iface_init))

static void
gum_user_time_sampler_class_init (GumUserTimeSamplerClass * klass)
{
}

static void
gum_user_time_sampler_iface_init (gpointer g_iface,
gpointer iface_data)
{
GumSamplerInterface * iface = g_iface;

iface->sample = gum_user_time_sampler_sample;
}

static void
gum_user_time_sampler_init (GumUserTimeSampler * self)
{
}

GumSampler *
gum_user_time_sampler_new (void)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = gum_process_get_current_thread_id ();

return GUM_SAMPLER (sampler);
}

GumSampler *
gum_user_time_sampler_new_with_thread_id (GumThreadId thread_id)
{
GumUserTimeSampler * sampler;

sampler = g_object_new (GUM_TYPE_USER_TIME_SAMPLER, NULL);
sampler->thread_id = thread_id;

return GUM_SAMPLER (sampler);
}

gboolean
gum_user_time_sampler_is_available (GumUserTimeSampler * self)
{
return FALSE;
}

static GumSample
gum_user_time_sampler_sample (GumSampler * sampler)
{
/* TODO: implement */
return 0;
}
Loading

0 comments on commit 9390984

Please sign in to comment.