1
0
Fork 0
mirror of https://github.com/endofunky/sidetiq.git synced 2022-11-09 13:53:30 -05:00
endofunky--sidetiq/ext/sidetiq_ext/sidetiq_ext.c
2013-02-01 18:27:27 +00:00

97 lines
3.1 KiB
C

#include <ruby.h>
#include <assert.h>
#include "sidetiq_ext.h"
#ifdef __APPLE__
#include <sys/time.h>
#include <sys/resource.h>
#include <mach/mach.h>
#include <mach/clock.h>
#include <mach/mach_time.h>
#include <errno.h>
#include <unistd.h>
#include <sched.h>
#else
#include <time.h>
#endif
VALUE msidetiq;
VALUE esidetiq_error;
VALUE csidetiq_clock;
#ifdef __APPLE__
static mach_timebase_info_data_t clock_gettime_inf;
typedef enum {
CLOCK_REALTIME,
CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID
} clockid_t;
int clock_gettime(clockid_t clk_id, struct timespec *tp)
{
kern_return_t ret;
clock_serv_t clk;
clock_id_t clk_serv_id;
mach_timespec_t tm;
uint64_t start, end, delta, nano;
int retval = -1;
switch (clk_id) {
case CLOCK_REALTIME:
case CLOCK_MONOTONIC:
clk_serv_id = clk_id == CLOCK_REALTIME ? CALENDAR_CLOCK : SYSTEM_CLOCK;
if (KERN_SUCCESS == (ret = host_get_clock_service(mach_host_self(), clk_serv_id, &clk))) {
if (KERN_SUCCESS == (ret = clock_get_time(clk, &tm))) {
tp->tv_sec = tm.tv_sec;
tp->tv_nsec = tm.tv_nsec;
retval = 0;
}
}
if (KERN_SUCCESS != ret) {
errno = EINVAL;
retval = -1;
}
break;
case CLOCK_PROCESS_CPUTIME_ID:
case CLOCK_THREAD_CPUTIME_ID:
start = mach_absolute_time();
if (clk_id == CLOCK_PROCESS_CPUTIME_ID) {
getpid();
} else {
sched_yield();
}
end = mach_absolute_time();
delta = end - start;
if (0 == clock_gettime_inf.denom) {
mach_timebase_info(&clock_gettime_inf);
}
nano = delta * clock_gettime_inf.numer / clock_gettime_inf.denom;
tp->tv_sec = nano * 1e-9;
tp->tv_nsec = nano - (tp->tv_sec * 1e9);
retval = 0;
break;
default:
errno = EINVAL;
retval = -1;
}
return retval;
}
#endif
static VALUE sidetiq_gettime(VALUE self)
{
struct timespec time;
assert(clock_gettime(CLOCK_REALTIME, &time) == 0);
return rb_time_nano_new(time.tv_sec, time.tv_nsec);
}
void Init_sidetiq_ext()
{
msidetiq = rb_define_module("Sidetiq");
esidetiq_error = rb_define_class_under(msidetiq, "Error", rb_eStandardError);
csidetiq_clock = rb_define_class_under(msidetiq, "Clock", rb_cObject);
rb_define_private_method(csidetiq_clock, "clock_gettime", sidetiq_gettime, 0);
}