blob: 137a012c6ec1d9e4f02c7dbe042b514d1a5f5a28 [file] [log] [blame]
/*
* Copyright (c) 2014 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <errno.h>
#include <sys/time.h>
#include <time.h>
#include "native_client/src/untrusted/irt/irt.h"
#include "native_client/src/untrusted/irt/irt_dev.h"
#include "native_client/src/untrusted/irt/irt_extension.h"
#include "native_client/tests/irt_ext/basic_calls.h"
#include "native_client/tests/irt_ext/error_report.h"
static struct nacl_irt_basic g_irt_basic;
static struct basic_calls_environment *g_activated_env = NULL;
static const struct basic_calls_environment g_default_env = {
.exit_called = false,
};
static void my_exit(int status) {
if (status == TEST_EXIT_CODE)
status = 0;
g_irt_basic.exit(status);
}
static int my_gettod(struct timeval *tv) {
if (g_activated_env) {
tv->tv_sec = g_activated_env->current_time;
tv->tv_usec = 0;
g_activated_env->current_time++;
return 0;
}
return ENOSYS;
}
/* Returns number of ticks which will just be seconds in current time. */
static int my_clock(clock_t *ticks) {
if (g_activated_env) {
*ticks = g_activated_env->current_time;
g_activated_env->current_time++;
return 0;
}
return ENOSYS;
}
static int my_nanosleep(const struct timespec *req, struct timespec *rem) {
if (g_activated_env) {
g_activated_env->current_time += req->tv_sec;
rem->tv_sec = 0;
rem->tv_nsec = req->tv_nsec;
return 0;
}
return ENOSYS;
}
static int my_sched_yield(void) {
if (g_activated_env) {
g_activated_env->thread_yielded = true;
return 0;
}
return ENOSYS;
}
static int my_sysconf(int name, int *value) {
if (g_activated_env && name == SYSCONF_TEST_IRT_QUERY) {
*value = SYSCONF_TEST_VALUE;
return 0;
}
return ENOSYS;
}
static int my_getpid(int *pid) {
if (g_activated_env) {
*pid = g_activated_env->pid;
return 0;
}
return ENOSYS;
}
static int my_clock_getres(nacl_irt_clockid_t clock_id, struct timespec *res) {
if (g_activated_env && clock_id == ENV_CLOCK_ID) {
res->tv_sec = 1;
res->tv_nsec = 0;
return 0;
}
return ENOSYS;
}
static int my_clock_gettime(nacl_irt_clockid_t clock_id, struct timespec *tp) {
if (g_activated_env && clock_id == ENV_CLOCK_ID) {
tp->tv_sec = g_activated_env->current_time++;
tp->tv_nsec = 0;
return 0;
}
return ENOSYS;
}
void init_basic_calls_module(void) {
size_t bytes = nacl_interface_query(NACL_IRT_BASIC_v0_1,
&g_irt_basic, sizeof(g_irt_basic));
IRT_EXT_ASSERT_MSG(bytes == sizeof(g_irt_basic),
"Could not query interface: " NACL_IRT_BASIC_v0_1);
struct nacl_irt_basic basic_calls = {
my_exit,
my_gettod,
my_clock,
my_nanosleep,
my_sched_yield,
my_sysconf,
};
bytes = nacl_interface_ext_supply(NACL_IRT_BASIC_v0_1, &basic_calls,
sizeof(basic_calls));
IRT_EXT_ASSERT_MSG(bytes == sizeof(basic_calls),
"Could not supply interface: " NACL_IRT_BASIC_v0_1);
struct nacl_irt_dev_getpid getpid_calls = {
my_getpid,
};
bytes = nacl_interface_ext_supply(NACL_IRT_DEV_GETPID_v0_1, &getpid_calls,
sizeof(getpid_calls));
IRT_EXT_ASSERT_MSG(bytes == sizeof(getpid_calls),
"Could not supply interface: " NACL_IRT_DEV_GETPID_v0_1);
struct nacl_irt_clock clock_calls = {
my_clock_getres,
my_clock_gettime,
};
bytes = nacl_interface_ext_supply(NACL_IRT_CLOCK_v0_1, &clock_calls,
sizeof(clock_calls));
IRT_EXT_ASSERT_MSG(bytes == sizeof(clock_calls),
"Could not supply interface: " NACL_IRT_CLOCK_v0_1);
}
void init_basic_calls_environment(struct basic_calls_environment *env) {
*env = g_default_env;
}
void activate_basic_calls_env(struct basic_calls_environment *env) {
g_activated_env = env;
}
void deactivate_basic_calls_env(void) {
g_activated_env = NULL;
}