xref: /third_party/node/deps/uvwasi/src/clocks.c (revision 1cb0ef41)
11cb0ef41Sopenharmony_ci#ifndef _WIN32
21cb0ef41Sopenharmony_ci# include <errno.h>
31cb0ef41Sopenharmony_ci# include <sys/time.h>
41cb0ef41Sopenharmony_ci# include <sys/resource.h>
51cb0ef41Sopenharmony_ci# include <time.h>
61cb0ef41Sopenharmony_ci#endif /* _WIN32 */
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include "uv.h"
91cb0ef41Sopenharmony_ci#include "clocks.h"
101cb0ef41Sopenharmony_ci#include "wasi_types.h"
111cb0ef41Sopenharmony_ci#include "uv_mapping.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#define UVWASI__WIN_TIME_AND_RETURN(handle, get_times, time)                  \
151cb0ef41Sopenharmony_ci  do {                                                                        \
161cb0ef41Sopenharmony_ci    FILETIME create;                                                          \
171cb0ef41Sopenharmony_ci    FILETIME exit;                                                            \
181cb0ef41Sopenharmony_ci    FILETIME system;                                                          \
191cb0ef41Sopenharmony_ci    FILETIME user;                                                            \
201cb0ef41Sopenharmony_ci    if (0 == get_times((handle), &create, &exit, &system, &user)) {           \
211cb0ef41Sopenharmony_ci      return uvwasi__translate_uv_error(                                      \
221cb0ef41Sopenharmony_ci        uv_translate_sys_error(GetLastError())                                \
231cb0ef41Sopenharmony_ci      );                                                                      \
241cb0ef41Sopenharmony_ci    }                                                                         \
251cb0ef41Sopenharmony_ci                                                                              \
261cb0ef41Sopenharmony_ci    /* FILETIME times are in units of 100 nanoseconds */                      \
271cb0ef41Sopenharmony_ci    (time) = (((uvwasi_timestamp_t)                                           \
281cb0ef41Sopenharmony_ci               system.dwHighDateTime << 32 | system.dwLowDateTime) * 100 +    \
291cb0ef41Sopenharmony_ci              ((uvwasi_timestamp_t)                                           \
301cb0ef41Sopenharmony_ci               user.dwHighDateTime << 32 | user.dwLowDateTime) * 100);        \
311cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
321cb0ef41Sopenharmony_ci  } while (0)
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci#define UVWASI__CLOCK_GETTIME_AND_RETURN(clk, time)                           \
361cb0ef41Sopenharmony_ci  do {                                                                        \
371cb0ef41Sopenharmony_ci    struct timespec ts;                                                       \
381cb0ef41Sopenharmony_ci    if (0 != clock_gettime((clk), &ts))                                       \
391cb0ef41Sopenharmony_ci      return uvwasi__translate_uv_error(uv_translate_sys_error(errno));       \
401cb0ef41Sopenharmony_ci    (time) = ((uvwasi_timestamp_t)(ts.tv_sec) * NANOS_PER_SEC) + ts.tv_nsec;  \
411cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
421cb0ef41Sopenharmony_ci  } while (0)
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci#define UVWASI__GETRUSAGE_AND_RETURN(who, time)                               \
461cb0ef41Sopenharmony_ci  do {                                                                        \
471cb0ef41Sopenharmony_ci    struct rusage ru;                                                         \
481cb0ef41Sopenharmony_ci    if (0 != getrusage((who), &ru))                                           \
491cb0ef41Sopenharmony_ci      return uvwasi__translate_uv_error(uv_translate_sys_error(errno));       \
501cb0ef41Sopenharmony_ci    (time) = ((uvwasi_timestamp_t)(ru.ru_utime.tv_sec) * NANOS_PER_SEC) +     \
511cb0ef41Sopenharmony_ci             (ru.ru_utime.tv_usec * 1000) +                                   \
521cb0ef41Sopenharmony_ci             ((uvwasi_timestamp_t)(ru.ru_stime.tv_sec) * NANOS_PER_SEC) +     \
531cb0ef41Sopenharmony_ci             (ru.ru_stime.tv_usec * 1000);                                    \
541cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
551cb0ef41Sopenharmony_ci  } while (0)
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci#define UVWASI__OSX_THREADTIME_AND_RETURN(time)                               \
591cb0ef41Sopenharmony_ci  do {                                                                        \
601cb0ef41Sopenharmony_ci    mach_port_t thread;                                                       \
611cb0ef41Sopenharmony_ci    thread_basic_info_data_t info;                                            \
621cb0ef41Sopenharmony_ci    mach_msg_type_number_t count;                                             \
631cb0ef41Sopenharmony_ci    count = THREAD_BASIC_INFO_COUNT;                                          \
641cb0ef41Sopenharmony_ci    thread = pthread_mach_thread_np(pthread_self());                          \
651cb0ef41Sopenharmony_ci    if (KERN_SUCCESS != thread_info(thread,                                   \
661cb0ef41Sopenharmony_ci                                    THREAD_BASIC_INFO,                        \
671cb0ef41Sopenharmony_ci                                    (thread_info_t) &info,                    \
681cb0ef41Sopenharmony_ci                                    &count)) {                                \
691cb0ef41Sopenharmony_ci      return UVWASI_ENOSYS;                                                   \
701cb0ef41Sopenharmony_ci    }                                                                         \
711cb0ef41Sopenharmony_ci    (time) = ((uvwasi_timestamp_t)(info.user_time.seconds) * NANOS_PER_SEC) + \
721cb0ef41Sopenharmony_ci             (info.user_time.microseconds * 1000) +                           \
731cb0ef41Sopenharmony_ci             ((uvwasi_timestamp_t)(info.system_time.seconds) * NANOS_PER_SEC) + \
741cb0ef41Sopenharmony_ci             (info.system_time.microseconds * 1000);                          \
751cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
761cb0ef41Sopenharmony_ci  } while (0)
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci#define UVWASI__WIN_GETRES_AND_RETURN(time)                                   \
801cb0ef41Sopenharmony_ci  do {                                                                        \
811cb0ef41Sopenharmony_ci    /* The GetProcessTimes() docs claim a resolution of 100 ns. */            \
821cb0ef41Sopenharmony_ci    (time) = 100;                                                             \
831cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
841cb0ef41Sopenharmony_ci  } while (0)
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci#define UVWASI__CLOCK_GETRES_AND_RETURN(clk, time)                            \
881cb0ef41Sopenharmony_ci  do {                                                                        \
891cb0ef41Sopenharmony_ci    struct timespec ts;                                                       \
901cb0ef41Sopenharmony_ci    /* Try calling clock_getres(). If it doesn't succeed, then default to     \
911cb0ef41Sopenharmony_ci       1000000. We implement all of the clocks, and some platforms (such as   \
921cb0ef41Sopenharmony_ci       SmartOS) don't support all of the clocks, even though they define      \
931cb0ef41Sopenharmony_ci       the constants for them. */                                             \
941cb0ef41Sopenharmony_ci    if (0 != clock_getres((clk), &ts))                                        \
951cb0ef41Sopenharmony_ci      (time) = 1000000;                                                       \
961cb0ef41Sopenharmony_ci    else                                                                      \
971cb0ef41Sopenharmony_ci      (time) = ((uvwasi_timestamp_t)(ts.tv_sec) * NANOS_PER_SEC) + ts.tv_nsec; \
981cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
991cb0ef41Sopenharmony_ci  } while (0)
1001cb0ef41Sopenharmony_ci
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci#define UVWASI__SLOW_GETRES_AND_RETURN(time)                                  \
1031cb0ef41Sopenharmony_ci  do {                                                                        \
1041cb0ef41Sopenharmony_ci    /* Assume a "worst case" of 1000000 ns resolution. */                     \
1051cb0ef41Sopenharmony_ci    (time) = 1000000;                                                         \
1061cb0ef41Sopenharmony_ci    return UVWASI_ESUCCESS;                                                   \
1071cb0ef41Sopenharmony_ci  } while (0)
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi__clock_gettime_realtime(uvwasi_timestamp_t* time) {
1111cb0ef41Sopenharmony_ci  uv_timeval64_t tv;
1121cb0ef41Sopenharmony_ci  int r;
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  r = uv_gettimeofday(&tv);
1151cb0ef41Sopenharmony_ci  if (r != 0)
1161cb0ef41Sopenharmony_ci    return uvwasi__translate_uv_error(r);
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  *time = (tv.tv_sec * NANOS_PER_SEC) + (tv.tv_usec * 1000);
1191cb0ef41Sopenharmony_ci  return UVWASI_ESUCCESS;
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi__clock_gettime_process_cputime(uvwasi_timestamp_t* time) {
1241cb0ef41Sopenharmony_ci#if defined(_WIN32)
1251cb0ef41Sopenharmony_ci  UVWASI__WIN_TIME_AND_RETURN(GetCurrentProcess(), GetProcessTimes, *time);
1261cb0ef41Sopenharmony_ci#elif defined(CLOCK_PROCESS_CPUTIME_ID) && \
1271cb0ef41Sopenharmony_ci      !defined(__APPLE__)               && \
1281cb0ef41Sopenharmony_ci      !defined(__sun)
1291cb0ef41Sopenharmony_ci  UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_PROCESS_CPUTIME_ID, *time);
1301cb0ef41Sopenharmony_ci#else
1311cb0ef41Sopenharmony_ci  UVWASI__GETRUSAGE_AND_RETURN(RUSAGE_SELF, *time);
1321cb0ef41Sopenharmony_ci#endif
1331cb0ef41Sopenharmony_ci}
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi__clock_gettime_thread_cputime(uvwasi_timestamp_t* time) {
1371cb0ef41Sopenharmony_ci#if defined(_WIN32)
1381cb0ef41Sopenharmony_ci  UVWASI__WIN_TIME_AND_RETURN(GetCurrentThread(), GetThreadTimes, *time);
1391cb0ef41Sopenharmony_ci#elif defined(__APPLE__)
1401cb0ef41Sopenharmony_ci  UVWASI__OSX_THREADTIME_AND_RETURN(*time);
1411cb0ef41Sopenharmony_ci#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun) && !defined(__PASE__)
1421cb0ef41Sopenharmony_ci  UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_THREAD_CPUTIME_ID, *time);
1431cb0ef41Sopenharmony_ci#else
1441cb0ef41Sopenharmony_ci# if defined(RUSAGE_LWP)
1451cb0ef41Sopenharmony_ci  UVWASI__GETRUSAGE_AND_RETURN(RUSAGE_LWP, *time);
1461cb0ef41Sopenharmony_ci# elif defined(RUSAGE_THREAD)
1471cb0ef41Sopenharmony_ci  UVWASI__GETRUSAGE_AND_RETURN(RUSAGE_THREAD, *time);
1481cb0ef41Sopenharmony_ci# else
1491cb0ef41Sopenharmony_ci  return UVWASI_ENOSYS;
1501cb0ef41Sopenharmony_ci# endif /* RUSAGE_LWP */
1511cb0ef41Sopenharmony_ci#endif
1521cb0ef41Sopenharmony_ci}
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi__clock_getres_process_cputime(uvwasi_timestamp_t* time) {
1561cb0ef41Sopenharmony_ci#if defined(_WIN32)
1571cb0ef41Sopenharmony_ci  UVWASI__WIN_GETRES_AND_RETURN(*time);
1581cb0ef41Sopenharmony_ci#elif defined(CLOCK_PROCESS_CPUTIME_ID) && \
1591cb0ef41Sopenharmony_ci      !defined(__APPLE__)               && \
1601cb0ef41Sopenharmony_ci      !defined(__sun)
1611cb0ef41Sopenharmony_ci  UVWASI__CLOCK_GETRES_AND_RETURN(CLOCK_PROCESS_CPUTIME_ID, *time);
1621cb0ef41Sopenharmony_ci#else
1631cb0ef41Sopenharmony_ci  UVWASI__SLOW_GETRES_AND_RETURN(*time);
1641cb0ef41Sopenharmony_ci#endif
1651cb0ef41Sopenharmony_ci}
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci
1681cb0ef41Sopenharmony_ciuvwasi_errno_t uvwasi__clock_getres_thread_cputime(uvwasi_timestamp_t* time) {
1691cb0ef41Sopenharmony_ci#if defined(_WIN32)
1701cb0ef41Sopenharmony_ci  UVWASI__WIN_GETRES_AND_RETURN(*time);
1711cb0ef41Sopenharmony_ci#elif defined(__APPLE__)
1721cb0ef41Sopenharmony_ci  UVWASI__SLOW_GETRES_AND_RETURN(*time);
1731cb0ef41Sopenharmony_ci#elif defined(CLOCK_THREAD_CPUTIME_ID) && !defined(__sun) && !defined(__PASE__)
1741cb0ef41Sopenharmony_ci  UVWASI__CLOCK_GETTIME_AND_RETURN(CLOCK_THREAD_CPUTIME_ID, *time);
1751cb0ef41Sopenharmony_ci#elif defined(RUSAGE_THREAD) || defined(RUSAGE_LWP)
1761cb0ef41Sopenharmony_ci  UVWASI__SLOW_GETRES_AND_RETURN(*time);
1771cb0ef41Sopenharmony_ci#else
1781cb0ef41Sopenharmony_ci  return UVWASI_ENOSYS;
1791cb0ef41Sopenharmony_ci#endif
1801cb0ef41Sopenharmony_ci}
181