1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <errno.h>
6#include <sched.h>
7#include <stdlib.h>
8#include <sys/time.h>
9#include <time.h>
10#include <unistd.h>
11
12#include "components/nacl/loader/nonsfi/abi_conversion.h"
13#include "components/nacl/loader/nonsfi/irt_interfaces.h"
14#include "components/nacl/loader/nonsfi/irt_util.h"
15#include "native_client/src/trusted/service_runtime/include/sys/time.h"
16#include "native_client/src/trusted/service_runtime/include/sys/unistd.h"
17
18namespace nacl {
19namespace nonsfi {
20namespace {
21
22void IrtExit(int status) {
23  _exit(status);
24}
25
26int IrtGetToD(struct nacl_abi_timeval* tv) {
27  struct timeval host_tv;
28  if (gettimeofday(&host_tv, NULL))
29    return errno;
30  tv->nacl_abi_tv_sec = host_tv.tv_sec;
31  tv->nacl_abi_tv_usec = host_tv.tv_usec;
32  return 0;
33}
34
35int IrtClock(nacl_abi_clock_t* ticks) {
36  // There is no definition of errno when clock is failed.
37  // So we assume it always succeeds.
38  *ticks = clock();
39  return 0;
40}
41
42int IrtNanoSleep(const struct nacl_abi_timespec* req,
43                 struct nacl_abi_timespec* rem) {
44  struct timespec host_req;
45  NaClAbiTimeSpecToTimeSpec(*req, &host_req);
46  struct timespec host_rem;
47  if (nanosleep(&host_req, &host_rem))
48    return errno;
49
50  if (rem)
51    TimeSpecToNaClAbiTimeSpec(host_rem, rem);
52  return 0;
53}
54
55int IrtSchedYield() {
56  return CheckError(sched_yield());
57}
58
59int IrtSysconf(int name, int* value) {
60  int result;
61  switch (name) {
62    case NACL_ABI__SC_NPROCESSORS_ONLN:
63      errno = 0;
64      result = sysconf(_SC_NPROCESSORS_ONLN);
65      break;
66    case NACL_ABI__SC_PAGESIZE:
67      errno = 0;
68      result = sysconf(_SC_PAGESIZE);
69      break;
70    default:
71      return EINVAL;
72  }
73
74  if (result == -1 && errno == EINVAL)
75    return EINVAL;
76
77  *value = result;
78  return 0;
79}
80
81}  // namespace
82
83// For gettod, clock and nanosleep, their argument types should be nacl_abi_X,
84// rather than host type, such as timeval or clock_t etc. However, the
85// definition of nacl_irt_basic uses host types, so here we need to cast them.
86const nacl_irt_basic kIrtBasic = {
87  IrtExit,
88  reinterpret_cast<int(*)(struct timeval*)>(IrtGetToD),
89  reinterpret_cast<int(*)(clock_t*)>(IrtClock),
90  reinterpret_cast<int(*)(const struct timespec*, struct timespec*)>(
91      IrtNanoSleep),
92  IrtSchedYield,
93  IrtSysconf,
94};
95
96}  // namespace nonsfi
97}  // namespace nacl
98