1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 18:11:04 +09:00

Refactor get_time_stamp_ns (#34536)

* Refactor get_time_stamp_ns

* Add place holder function for pc to make pc build pass

* Add missing header file

* Move all time functions to mono-time.c

* Make sampling_thread_running a global variable

* Pass void* to init, clean_up and get_time function to accormodate different clock ID types for different os, and move back profiler specific function

* Add static keyword for local helper function and fix a typo

* Change to platform-specific typedef approach

* Add missing header file for macOS

* Add missing header file for linux

* Change header file name

* Change header file name one more time

* Fix failures on macOS

* Update src/mono/mono/utils/mono-time.h

Co-Authored-By: Ryan Lucia <ryan@luciaonline.net>

Co-authored-by: Ryan Lucia <ryan@luciaonline.net>
This commit is contained in:
Fan Yang 2020-04-24 11:35:58 -04:00 committed by GitHub
commit ede936d155
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 131 additions and 78 deletions

View file

@ -70,6 +70,7 @@
#include <mono/utils/mono-threads.h>
#include <mono/utils/os-event.h>
#include <mono/utils/mono-state.h>
#include <mono/utils/mono-time.h>
#include <mono/mini/debugger-state-machine.h>
#include "mini.h"
@ -517,48 +518,11 @@ static volatile gint32 sampling_thread_running;
#ifdef HOST_DARWIN
static clock_serv_t sampling_clock_service;
static clock_serv_t sampling_clock;
static void
clock_init (MonoProfilerSampleMode mode)
clock_init_for_profiler (MonoProfilerSampleMode mode)
{
kern_return_t ret;
do {
ret = host_get_clock_service (mach_host_self (), SYSTEM_CLOCK, &sampling_clock_service);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
g_error ("%s: host_get_clock_service () returned %d", __func__, ret);
}
static void
clock_cleanup (void)
{
kern_return_t ret;
do {
ret = mach_port_deallocate (mach_task_self (), sampling_clock_service);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
g_error ("%s: mach_port_deallocate () returned %d", __func__, ret);
}
static guint64
clock_get_time_ns (void)
{
kern_return_t ret;
mach_timespec_t mach_ts;
do {
ret = clock_get_time (sampling_clock_service, &mach_ts);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
g_error ("%s: clock_get_time () returned %d", __func__, ret);
return ((guint64) mach_ts.tv_sec * 1000000000) + (guint64) mach_ts.tv_nsec;
}
static void
@ -571,7 +535,7 @@ clock_sleep_ns_abs (guint64 ns_abs)
then.tv_nsec = ns_abs % 1000000000;
do {
ret = clock_sleep (sampling_clock_service, TIME_ABSOLUTE, then, &remain_unused);
ret = clock_sleep (sampling_clock, TIME_ABSOLUTE, then, &remain_unused);
if (ret != KERN_SUCCESS && ret != KERN_ABORTED)
g_error ("%s: clock_sleep () returned %d", __func__, ret);
@ -580,10 +544,10 @@ clock_sleep_ns_abs (guint64 ns_abs)
#else
static clockid_t sampling_posix_clock;
static clockid_t sampling_clock;
static void
clock_init (MonoProfilerSampleMode mode)
clock_init_for_profiler (MonoProfilerSampleMode mode)
{
switch (mode) {
case MONO_PROFILER_SAMPLE_MODE_PROCESS: {
@ -601,34 +565,18 @@ clock_init (MonoProfilerSampleMode mode)
* those systems, we fall back to CLOCK_MONOTONIC if we get EINVAL.
*/
if (clock_nanosleep (CLOCK_PROCESS_CPUTIME_ID, TIMER_ABSTIME, &ts, NULL) != EINVAL) {
sampling_posix_clock = CLOCK_PROCESS_CPUTIME_ID;
sampling_clock = CLOCK_PROCESS_CPUTIME_ID;
break;
}
#endif
// fallthrough
}
case MONO_PROFILER_SAMPLE_MODE_REAL: sampling_posix_clock = CLOCK_MONOTONIC; break;
case MONO_PROFILER_SAMPLE_MODE_REAL: sampling_clock = CLOCK_MONOTONIC; break;
default: g_assert_not_reached (); break;
}
}
static void
clock_cleanup (void)
{
}
static guint64
clock_get_time_ns (void)
{
struct timespec ts;
if (clock_gettime (sampling_posix_clock, &ts) == -1)
g_error ("%s: clock_gettime () returned -1, errno = %d", __func__, errno);
return ((guint64) ts.tv_sec * 1000000000) + (guint64) ts.tv_nsec;
}
static void
clock_sleep_ns_abs (guint64 ns_abs)
{
@ -640,7 +588,7 @@ clock_sleep_ns_abs (guint64 ns_abs)
then.tv_nsec = ns_abs % 1000000000;
do {
ret = clock_nanosleep (sampling_posix_clock, TIMER_ABSTIME, &then, NULL);
ret = clock_nanosleep (sampling_clock, TIMER_ABSTIME, &then, NULL);
if (ret != 0 && ret != EINTR)
g_error ("%s: clock_nanosleep () returned %d", __func__, ret);
@ -675,7 +623,7 @@ clock_sleep_ns_abs (guint64 ns_abs)
* nanoseconds).
*/
do {
diff = (gint64) ns_abs - (gint64) clock_get_time_ns ();
diff = (gint64) ns_abs - (gint64) mono_clock_get_time_ns (sampling_clock);
if (diff <= 0)
break;
@ -743,16 +691,17 @@ init:
goto init;
}
clock_init (mode);
mono_clock_init (&sampling_clock);
clock_init_for_profiler (mode);
for (guint64 sleep = clock_get_time_ns (); mono_atomic_load_i32 (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
for (guint64 sleep = mono_clock_get_time_ns (sampling_clock); mono_atomic_load_i32 (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
uint32_t freq;
MonoProfilerSampleMode new_mode;
mono_profiler_get_sample_mode (NULL, &new_mode, &freq);
if (new_mode != mode) {
clock_cleanup ();
mono_clock_cleanup (sampling_clock);
goto init;
}
@ -774,7 +723,7 @@ init:
} FOREACH_THREAD_SAFE_END
}
clock_cleanup ();
mono_clock_cleanup (sampling_clock);
done:
mono_atomic_store_i32 (&sampling_thread_exiting, 1);

View file

@ -70,6 +70,7 @@
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-proclib.h>
#include <mono/utils/mono-state.h>
#include <mono/utils/mono-time.h>
#include <mono/metadata/w32handle.h>
#include <mono/metadata/threadpool.h>
@ -1934,6 +1935,7 @@ static FILE *perf_dump_file;
static mono_mutex_t perf_dump_mutex;
static void *perf_dump_mmap_addr = MAP_FAILED;
static guint32 perf_dump_pid;
static clockid_t clock_id = CLOCK_MONOTONIC;
enum {
JIT_DUMP_MAGIC = 0x4A695444,
@ -1984,7 +1986,6 @@ typedef struct
} JitCodeLoadRecord;
static void add_file_header_info (FileHeader *header);
static guint64 get_time_stamp_ns (void);
static void add_basic_JitCodeLoadRecord_info (JitCodeLoadRecord *record);
void
@ -2025,18 +2026,10 @@ add_file_header_info (FileHeader *header)
header->elf_mach = ELF_MACHINE;
header->pad1 = 0;
header->pid = perf_dump_pid;
header->timestamp = get_time_stamp_ns ();
header->timestamp = mono_clock_get_time_ns (clock_id);
header->flags = 0;
}
static guint64
get_time_stamp_ns (void)
{
struct timespec ts;
int result = clock_gettime (CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}
void
mono_emit_jit_dump (MonoJitInfo *jinfo, gpointer code)
{
@ -2059,7 +2052,7 @@ mono_emit_jit_dump (MonoJitInfo *jinfo, gpointer code)
// TODO: write debugInfo and unwindInfo immediately before the JitCodeLoadRecord (while lock is held).
record.header.timestamp = get_time_stamp_ns ();
record.header.timestamp = mono_clock_get_time_ns (clock_id);
fwrite (&record, sizeof (record), 1, perf_dump_file);
fwrite (jinfo->d.method->name, nameLen + 1, 1, perf_dump_file);
@ -2073,7 +2066,7 @@ static void
add_basic_JitCodeLoadRecord_info (JitCodeLoadRecord *record)
{
record->header.id = JIT_CODE_LOAD;
record->header.timestamp = get_time_stamp_ns ();
record->header.timestamp = mono_clock_get_time_ns (clock_id);
record->pid = perf_dump_pid;
record->tid = syscall (SYS_gettid);
}

View file

@ -15,6 +15,12 @@
#include <sys/time.h>
#endif
#ifdef HOST_DARWIN
#include <mach/clock.h>
#include <mach/mach.h>
#endif
#include <mono/utils/mono-time.h>
#include <mono/utils/atomic.h>
@ -229,3 +235,94 @@ mono_100ns_datetime_from_timeval (struct timeval tv)
#endif
#if defined(HOST_DARWIN)
void
mono_clock_init (mono_clock_id_t *clk_id)
{
kern_return_t ret;
do {
ret = host_get_clock_service (mach_host_self (), SYSTEM_CLOCK, clk_id);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
g_error ("%s: host_get_clock_service () returned %d", __func__, ret);
}
void
mono_clock_cleanup (mono_clock_id_t clk_id)
{
kern_return_t ret;
do {
ret = mach_port_deallocate (mach_task_self (), clk_id);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
g_error ("%s: mach_port_deallocate () returned %d", __func__, ret);
}
guint64
mono_clock_get_time_ns (mono_clock_id_t clk_id)
{
kern_return_t ret;
mach_timespec_t mach_ts;
do {
ret = clock_get_time (clk_id, &mach_ts);
} while (ret == KERN_ABORTED);
if (ret != KERN_SUCCESS)
g_error ("%s: clock_get_time () returned %d", __func__, ret);
return ((guint64) mach_ts.tv_sec * 1000000000) + (guint64) mach_ts.tv_nsec;
}
#elif defined(__linux__)
void
mono_clock_init (mono_clock_id_t *clk_id)
{
}
void
mono_clock_cleanup (mono_clock_id_t clk_id)
{
}
guint64
mono_clock_get_time_ns (mono_clock_id_t clk_id)
{
struct timespec ts;
if (clock_gettime (clk_id, &ts) == -1)
g_error ("%s: clock_gettime () returned -1, errno = %d", __func__, errno);
return ((guint64) ts.tv_sec * 1000000000) + (guint64) ts.tv_nsec;
}
#else
void
mono_clock_init (mono_clock_id_t *clk_id)
{
// TODO: need to implement this function for PC
g_assert_not_reached ();
}
void
mono_clock_cleanup (mono_clock_id_t clk_id)
{
// TODO: need to implement this function for PC
g_assert_not_reached ();
}
guint64
mono_clock_get_time_ns (mono_clock_id_t clk_id)
{
// TODO: need to implement time stamp function for PC
g_assert_not_reached ();
}
#endif

View file

@ -29,6 +29,20 @@ gint64 mono_100ns_datetime (void);
gint64 mono_100ns_datetime_from_timeval (struct timeval tv);
#endif
#if defined(HOST_DARWIN)
#include <mach/clock.h>
typedef clock_serv_t mono_clock_id_t;
#elif defined(__linux__)
#include <sys/types.h>
typedef clockid_t mono_clock_id_t;
#else
typedef void *mono_clock_id_t;
#endif
void mono_clock_init (mono_clock_id_t *clk_id);
void mono_clock_cleanup (mono_clock_id_t clk_id);
guint64 mono_clock_get_time_ns (mono_clock_id_t clk_id);
/* Stopwatch class for internal runtime use */
typedef struct {
gint64 start, stop;