#include "spvm_native.h"
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#ifndef _WIN32
#include <sys/times.h>
#endif
static const char* FILE_NAME = "Sys/Time.c";
int32_t SPVM__Sys__Time__gettimeofday(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
void* obj_tv = stack[0].oval;
struct timeval* st_tv = NULL;
if (obj_tv) {
st_tv = env->get_pointer(env, stack, obj_tv);
}
void* obj_tz = stack[1].oval;
struct timezone* st_tz = NULL;
if (obj_tz) {
st_tz = env->get_pointer(env, stack, obj_tz);
}
int32_t status = gettimeofday(st_tv, st_tz);
if (status == -1) {
env->die(env, stack, "[System Error]gettimeofday failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = status;
return 0;
}
int32_t SPVM__Sys__Time__clock(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int64_t cpu_time = clock();
if (cpu_time == -1) {
env->die(env, stack, "[System Error]clock failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].lval = cpu_time;
return 0;
}
int32_t SPVM__Sys__Time__clock_gettime(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t clk_id = stack[0].ival;
void* obj_tp = stack[1].oval;
struct timespec* st_tp = NULL;
if (obj_tp) {
st_tp = env->get_pointer(env, stack, obj_tp);
}
else {
return env->die(env, stack, "The $tp must be defined", __func__, FILE_NAME, __LINE__);
}
int32_t status = clock_gettime(clk_id, st_tp);
if (status == -1) {
env->die(env, stack, "[System Error]clock_gettime failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = status;
return 0;
}
int32_t SPVM__Sys__Time__clock_getres(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
int32_t clk_id = stack[0].ival;
void* obj_res = stack[1].oval;
struct timespec* st_res = NULL;
if (obj_res) {
st_res = env->get_pointer(env, stack, obj_res);
}
else {
return env->die(env, stack, "The $res must be defined", __func__, FILE_NAME, __LINE__);
}
int32_t status = clock_getres(clk_id, st_res);
if (status == -1) {
env->die(env, stack, "[System Error]clock_getres failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = status;
return 0;
}
int32_t SPVM__Sys__Time__setitimer(SPVM_ENV* env, SPVM_VALUE* stack) {
#ifdef _WIN32
env->die(env, stack, "getitimer is not supported on this system(_WIN32)", __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_NOT_SUPPORTED;
#else
(void)env;
(void)stack;
int32_t which = stack[0].ival;
void* obj_new_value = stack[1].oval;
struct itimerval* st_new_value = NULL;
if (obj_new_value) {
st_new_value = env->get_pointer(env, stack, obj_new_value);
}
else {
return env->die(env, stack, "The $new_value must be defined", __func__, FILE_NAME, __LINE__);
}
void* obj_old_value = stack[1].oval;
struct itimerval* st_old_value = NULL;
if (obj_old_value) {
st_old_value = env->get_pointer(env, stack, obj_old_value);
}
int32_t status = setitimer(which, st_new_value, st_old_value);
if (status == -1) {
env->die(env, stack, "[System Error]setitimer failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = status;
return 0;
#endif
}
int32_t SPVM__Sys__Time__getitimer(SPVM_ENV* env, SPVM_VALUE* stack) {
#ifdef _WIN32
env->die(env, stack, "getitimer is not supported on this system(_WIN32)", __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_NOT_SUPPORTED;
#else
(void)env;
(void)stack;
int32_t which = stack[0].ival;
void* obj_curr_value = stack[1].oval;
struct itimerval* st_curr_value = NULL;
if (obj_curr_value) {
st_curr_value = env->get_pointer(env, stack, obj_curr_value);
}
else {
return env->die(env, stack, "The $curr_value must be defined", __func__, FILE_NAME, __LINE__);
}
int32_t status = getitimer(which, st_curr_value);
if (status == -1) {
env->die(env, stack, "[System Error]getitimer failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = status;
return 0;
#endif
}
int32_t SPVM__Sys__Time__times(SPVM_ENV* env, SPVM_VALUE* stack) {
#ifdef _WIN32
env->die(env, stack, "times is not supported on this system(_WIN32)", __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_NOT_SUPPORTED;
#else
void* obj_tms = stack[0].oval;
if (!obj_tms) {
return env->die(env, stack, "The $tms must be defined", __func__, FILE_NAME, __LINE__);
}
struct tms* st_tms = env->get_pointer(env, stack, obj_tms);
errno = 0;
int64_t clock_tick = times(st_tms);
if (errno != 0) {
env->die(env, stack, "[System Error]times failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].lval = clock_tick;
return 0;
#endif
}
int32_t SPVM__Sys__Time__clock_nanosleep(SPVM_ENV* env, SPVM_VALUE* stack) {
#ifdef __APPLE__
env->die(env, stack, "clock_nanosleep is not supported on this system(__APPLE__)", __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_NOT_SUPPORTED;
#elif __FreeBSD__ && !(__FreeBSD__ >= 13)
env->die(env, stack, "clock_nanosleep is not supported on this system(__FreeBSD__ && !(__FreeBSD__ >= 13))", __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_NOT_SUPPORTED;
#elif __OpenBSD__
env->die(env, stack, "clock_nanosleep is not supported on this system(__OpenBSD__)", __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_NOT_SUPPORTED;
#else
(void)env;
(void)stack;
int32_t clockid = stack[0].ival;
int32_t flags = stack[1].ival;
void* obj_request = stack[2].oval;
struct timespec* st_request = NULL;
if (obj_request) {
st_request = env->get_pointer(env, stack, obj_request);
}
else {
return env->die(env, stack, "The $request must be defined", __func__, FILE_NAME, __LINE__);
}
void* obj_remain = stack[3].oval;
struct timespec* st_remain = NULL;
if (obj_remain) {
st_remain = env->get_pointer(env, stack, obj_remain);
}
int32_t ret_errno = clock_nanosleep(clockid, flags, st_request, st_remain);
if (ret_errno != 0) {
env->die(env, stack, "[System Error]clock_nanosleep failed:%s.", env->strerror(env, stack, ret_errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = ret_errno;
return 0;
#endif
}
int32_t SPVM__Sys__Time__nanosleep(SPVM_ENV* env, SPVM_VALUE* stack) {
(void)env;
(void)stack;
void* obj_rqtp = stack[0].oval;
struct timespec* st_rqtp = NULL;
if (obj_rqtp) {
st_rqtp = env->get_pointer(env, stack, obj_rqtp);
}
else {
return env->die(env, stack, "The $rqtp must be defined", __func__, FILE_NAME, __LINE__);
}
void* obj_rmtp = stack[1].oval;
struct timespec* st_rmtp = NULL;
if (obj_rmtp) {
st_rmtp = env->get_pointer(env, stack, obj_rmtp);
}
int32_t status = nanosleep(st_rqtp, st_rmtp);
if (status == -1) {
env->die(env, stack, "[System Error]nanosleep failed:%s.", env->strerror(env, stack, errno, 0), __func__, FILE_NAME, __LINE__);
return SPVM_NATIVE_C_CLASS_ID_ERROR_SYSTEM;
}
stack[0].ival = status;
return 0;
}