1
2 // Copyright (C) 2023 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 #include <Windows.h>
16 #include <sys/time.h>
17 #include <time.h>
18
19 #include <cassert>
20 #include <chrono>
21 #include <ctime>
22 #include <iostream>
23 #include <thread>
24
25 #include "compat_compiler.h"
26
27 ANDROID_BEGIN_HEADER
28
29 typedef int clockid_t;
30
clock_gettime(clockid_t clk_id,struct timespec * tp)31 int clock_gettime(clockid_t clk_id, struct timespec* tp) {
32 assert(clk_id == CLOCK_MONOTONIC);
33 auto now = std::chrono::steady_clock::now();
34 auto duration = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
35
36 tp->tv_sec = static_cast<time_t>(duration.count());
37 tp->tv_nsec = static_cast<long>(
38 std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch() - duration)
39 .count());
40
41 return 0; // Success
42 }
43
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)44 int nanosleep(const struct timespec* rqtp, struct timespec* rmtp) {
45 // Validate input
46 if (rqtp == NULL || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1'000'000'000) {
47 SetLastError(ERROR_INVALID_PARAMETER);
48 return -1;
49 }
50
51 // Create a persistent thread local timer object
52 struct ThreadLocalTimerState {
53 ThreadLocalTimerState() {
54 timerHandle = CreateWaitableTimerEx(
55 nullptr /* no security attributes */, nullptr /* no timer name */,
56 CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
57
58 if (!timerHandle) {
59 // Use an older version of waitable timer as backup.
60 timerHandle = CreateWaitableTimer(nullptr, FALSE, nullptr);
61 }
62 }
63
64 ~ThreadLocalTimerState() {
65 if (timerHandle) {
66 CloseHandle(timerHandle);
67 }
68 }
69
70 HANDLE timerHandle = 0;
71 };
72
73 static thread_local ThreadLocalTimerState tl_timerInfo;
74
75 // Convert timespec to FILETIME
76 ULARGE_INTEGER fileTime;
77 fileTime.QuadPart = static_cast<ULONGLONG>(rqtp->tv_sec) * 10'000'000 + rqtp->tv_nsec / 100;
78
79 if (!tl_timerInfo.timerHandle) {
80 // Oh oh, for some reason we do not have a handle..
81 return -1;
82 }
83
84 LARGE_INTEGER dueTime;
85 // Note: Negative values indicate relative time.
86 // (https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setwaitabletimer)
87 dueTime.QuadPart = -static_cast<LONGLONG>(fileTime.QuadPart);
88
89 if (!SetWaitableTimer(tl_timerInfo.timerHandle, &dueTime, 0, NULL, NULL, FALSE)) {
90 return -1;
91 }
92
93 if (WaitForSingleObject(tl_timerInfo.timerHandle, INFINITE) != WAIT_OBJECT_0) {
94 return -1; // Sleep interrupted or error
95 }
96
97 // Calculate remaining time if needed
98 if (rmtp != NULL) {
99 // Get current time
100 FILETIME currentTime;
101 GetSystemTimeAsFileTime(¤tTime);
102
103 // Calculate remaining time
104 ULARGE_INTEGER currentFileTime;
105 currentFileTime.LowPart = currentTime.dwLowDateTime;
106 currentFileTime.HighPart = currentTime.dwHighDateTime;
107
108 ULONGLONG remainingTime = fileTime.QuadPart + currentFileTime.QuadPart;
109 rmtp->tv_sec = static_cast<time_t>(remainingTime / 10'000'000);
110 rmtp->tv_nsec = static_cast<long>((remainingTime % 10'000'000) * 100);
111 }
112
113 return 0;
114 }
115
gettimeofday(struct timeval * tp,void *)116 int gettimeofday(struct timeval* tp, void* /* tzp */) {
117 if (tp == nullptr) {
118 return -1;
119 }
120
121 // Get the current time using std::chrono::system_clock
122 auto now = std::chrono::system_clock::now();
123 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(now.time_since_epoch());
124
125 // Extract seconds and microseconds
126 tp->tv_sec = static_cast<long>(duration.count() / 1'000'000);
127 tp->tv_usec = static_cast<long>(duration.count() % 1'000'000);
128
129 // Return success
130 return 0;
131 }
132
usleep(int64_t usec)133 void usleep(int64_t usec) {
134 struct timespec req;
135 req.tv_sec = static_cast<time_t>(usec / 1'000'000);
136 req.tv_nsec = static_cast<long>((usec % 1'000'000) * 1000);
137
138 nanosleep(&req, nullptr);
139 }
140
sleep(unsigned int seconds)141 unsigned int sleep(unsigned int seconds) {
142 Sleep(seconds * 1000);
143 return 0;
144 }
145
146 ANDROID_END_HEADER