1 : /*
2 : * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 : * Use of this source code is governed by a BSD-style license that can be
4 : * found in the LICENSE file.
5 : */
6 :
7 : #include <time.h>
8 : #include <errno.h>
9 :
10 : #include "native_client/src/shared/platform/nacl_clock.h"
11 :
12 : #include "native_client/src/include/nacl_macros.h"
13 : #include "native_client/src/shared/platform/nacl_host_desc.h"
14 : #include "native_client/src/shared/platform/nacl_log.h"
15 : #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
16 :
17 : /*
18 : * Linux is POSIX.1-2001 compliant, so the clock functions are trivial
19 : * mappings -- essentially we just translate NaCl ABI enums and
20 : * errnos.
21 : */
22 : static int g_NaClClock_is_initialized = 0;
23 :
24 349 : int NaClClockInit(void) { g_NaClClock_is_initialized = 1; return 1; }
25 57 : void NaClClockFini(void) {}
26 :
27 8 : int NaClClockGetRes(nacl_clockid_t clk_id,
28 : struct nacl_abi_timespec *res) {
29 8 : int rv = -NACL_ABI_EINVAL;
30 : struct timespec host_res;
31 : clockid_t host_clk_id;
32 :
33 8 : if (!g_NaClClock_is_initialized) {
34 0 : NaClLog(LOG_FATAL,
35 : "NaClClockGetRes invoked without successful NaClClockInit\n");
36 : }
37 8 : switch (clk_id) {
38 : case NACL_CLOCK_REALTIME:
39 2 : host_clk_id = CLOCK_REALTIME;
40 2 : rv = 0;
41 2 : break;
42 : case NACL_CLOCK_MONOTONIC:
43 2 : host_clk_id = CLOCK_MONOTONIC;
44 2 : rv = 0;
45 2 : break;
46 : case NACL_CLOCK_PROCESS_CPUTIME_ID:
47 2 : host_clk_id = CLOCK_PROCESS_CPUTIME_ID;
48 2 : rv = 0;
49 2 : break;
50 : case NACL_CLOCK_THREAD_CPUTIME_ID:
51 2 : host_clk_id = CLOCK_THREAD_CPUTIME_ID;
52 2 : rv = 0;
53 2 : break;
54 : }
55 8 : if (0 == rv) {
56 8 : if (0 != clock_getres(host_clk_id, &host_res)) {
57 0 : rv = -NaClXlateErrno(errno);
58 : }
59 : }
60 8 : if (0 == rv) {
61 8 : res->tv_sec = host_res.tv_sec;
62 8 : res->tv_nsec = host_res.tv_nsec;
63 : }
64 8 : return rv;
65 : }
66 :
67 404251 : int NaClClockGetTime(nacl_clockid_t clk_id,
68 : struct nacl_abi_timespec *tp) {
69 404251 : int rv = -NACL_ABI_EINVAL;
70 : struct timespec host_time;
71 :
72 404251 : if (!g_NaClClock_is_initialized) {
73 0 : NaClLog(LOG_FATAL,
74 : "NaClClockGetTime invoked without successful NaClClockInit\n");
75 : }
76 404251 : switch (clk_id) {
77 : case NACL_CLOCK_REALTIME:
78 9 : if (0 != clock_gettime(CLOCK_REALTIME, &host_time)) {
79 0 : rv = -NaClXlateErrno(errno);
80 : } else {
81 9 : rv = 0;
82 : }
83 9 : break;
84 : case NACL_CLOCK_MONOTONIC:
85 404216 : if (0 != clock_gettime(CLOCK_MONOTONIC, &host_time)) {
86 0 : rv = -NaClXlateErrno(errno);
87 : } else {
88 404216 : rv = 0;
89 : }
90 404216 : break;
91 : case NACL_CLOCK_PROCESS_CPUTIME_ID:
92 : /*
93 : * This will include the time spent in an TCB-private service thread
94 : * as well as the actual user threads. This not a major issue given
95 : * all the trade-offs of implementing the proper semantics, but it is
96 : * worth noting that the return value might be somewhat different from
97 : * what this would be in a real POSIX OS.
98 : */
99 13 : if (0 != clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &host_time)) {
100 0 : rv = -NaClXlateErrno(errno);
101 : } else {
102 13 : rv = 0;
103 : }
104 13 : break;
105 : case NACL_CLOCK_THREAD_CPUTIME_ID:
106 13 : if (0 != clock_gettime(CLOCK_THREAD_CPUTIME_ID, &host_time)) {
107 0 : rv = -NaClXlateErrno(errno);
108 : } else {
109 13 : rv = 0;
110 : }
111 13 : break;
112 : }
113 404251 : if (0 == rv) {
114 404251 : tp->tv_sec = host_time.tv_sec;
115 404251 : tp->tv_nsec = host_time.tv_nsec;
116 : }
117 404251 : return rv;
118 : }
|