hoshi-lang dev
Yet another programming language
Loading...
Searching...
No Matches
time.cpp
Go to the documentation of this file.
1#include <ctime>
2#include <runtime/time/time.h>
3
4#include <stdio.h>
5
6#if defined (_WIN32)
7
8long get_tm_gmtoff(struct tm *t) {
9 struct tm temp = *t;
10
11 time_t utc_timestamp = _mkgmtime(&temp);
12
13 temp = *t;
14 temp.tm_isdst = -1;
15
16 time_t local_timestamp = mktime(&temp);
17
18 return (long)(utc_timestamp - local_timestamp);
19}
20
21static struct tm *localtime_r(const time_t *timer, struct tm *buf) {
22 if (timer == NULL || buf == NULL) {
23 return NULL;
24 }
25
26 errno_t err = localtime_s(buf, timer);
27
28 if (err != 0) {
29 return NULL;
30 }
31
32 return buf;
33}
34
35static struct tm* gmtime_r(const time_t* timer, struct tm* buf) {
36 if (timer == NULL || buf == NULL) {
37 return NULL;
38 }
39
40 errno_t err = gmtime_s(buf, timer);
41
42 if (err != 0) {
43 return NULL;
44 }
45
46 return buf;
47}
48
49#if !defined (__CYGWIN__) && !defined (__MINGW32__)
50
51#include <windows.h>
52
53#define DELTA_EPOCH_IN_MICROSECS 116444736000000000LL
54
55int clock_gettime(int clk_id, struct timespec *tp) {
56 if (tp == NULL)
57 return -1;
58
59 if (clk_id == CLOCK_REALTIME) {
60 FILETIME ft;
61 GetSystemTimePreciseAsFileTime(&ft);
62
63 uint64_t t = ((uint64_t)ft.dwHighDateTime << 32) | ft.dwLowDateTime;
64
65 t -= DELTA_EPOCH_IN_MICROSECS;
66
67 tp->tv_sec = (time_t)(t / 10000000); // 100ns to seconds
68 tp->tv_nsec = (long)((t % 10000000) * 100); // Remaining 100ns to ns
69
70 return 0;
71 } else if (clk_id == CLOCK_MONOTONIC) {
72 static LARGE_INTEGER freq = {0};
73 LARGE_INTEGER count;
74
75 // Get frequency once (it doesn't change after boot)
76 if (freq.QuadPart == 0) {
77 if (!QueryPerformanceFrequency(&freq))
78 return -1;
79 }
80
81 if (!QueryPerformanceCounter(&count))
82 return -1;
83
84 // Convert QPC units to seconds and nanoseconds
85 tp->tv_sec = (time_t)(count.QuadPart / freq.QuadPart);
86
87 // Calculate remainder carefully to avoid overflow before division
88 // logic: (count % freq) * 1e9 / freq
89 tp->tv_nsec = (long)(((count.QuadPart % freq.QuadPart) * 1000000000) / freq.QuadPart);
90
91 return 0;
92 }
93
94 return -1; // Unknown clock ID
95}
96
97int nanosleep(const struct timespec *req, struct timespec *rem) {
98 if (req == NULL || req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000) {
99 return -1;
100 }
101
102 // Windows WaitableTimers use 100-nanosecond intervals.
103 // Negative value indicates relative time.
104 LARGE_INTEGER li;
105
106 // Convert seconds + nanoseconds to 100ns ticks
107 int64_t interval = req->tv_sec * 10000000LL + req->tv_nsec / 100;
108 li.QuadPart = -interval;
109
110// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION requires Win 10 build 1803 or later.
111// If running on older Windows, fallback to 0 (standard resolution).
112#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
113#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
114#endif
115
116 HANDLE timer = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
117
118 if (!timer) {
119 // Fallback for Win7/8 if Ex fails or flag unsupported
120 timer = CreateWaitableTimer(NULL, TRUE, NULL);
121 if (!timer)
122 return -1;
123 }
124
125 if (!SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE)) {
126 CloseHandle(timer);
127 return -1;
128 }
129
130 // Wait for the timer
131 WaitForSingleObject(timer, INFINITE);
132 CloseHandle(timer);
133
134 // Note: Windows handles interruptions (APCs) differently than POSIX signals.
135 // In a strict port, you would check if WaitForSingleObject returns WAIT_IO_COMPLETION
136 // and calculate 'rem'. For most uses, this is unnecessary complexity.
137 if (rem) {
138 rem->tv_sec = 0;
139 rem->tv_nsec = 0;
140 }
141
142 return 0;
143}
144#endif // !defined (__CYGWIN__) && !defined (__MINGW32__)
145
146#else
147
148long get_tm_gmtoff(struct tm *t) {
149 return t->tm_gmtoff;
150}
151
152#endif // _WIN32
153
159
160YoiIntAndIntObject *YoiIntAndIntObject::create(int64_t seconds, int64_t nanoseconds) {
162 obj->gc_refcount = 1;
163 obj->type_id = 0;
164 obj->seconds = seconds;
165 obj->nanoseconds = nanoseconds;
166 return obj;
167}
168
170 struct timespec ts{};
171 clock_gettime(CLOCK_REALTIME, &ts);
172 int64_t seconds = ts.tv_sec;
173 int64_t nanoseconds = ts.tv_nsec;
174 return YoiIntAndIntObject::create(seconds, nanoseconds);
175}
176
177void runtime_time_sleep(int64_t seconds, int64_t nanoseconds) {
178 struct timespec ts{};
179 ts.tv_sec = seconds;
180 ts.tv_nsec = nanoseconds;
181 nanosleep(&ts, nullptr);
182}
183
184char *runtime_time_strftime(const char *format, int64_t timestamp) {
185 time_t t = timestamp;
186 struct tm tm{};
187 gmtime_r(&t, &tm);
188 char *result = (char *)malloc(MAX_TIME_STR_LEN);
189 strftime(result, MAX_TIME_STR_LEN, format, &tm);
190 return result;
191}
192
194 time_t now = time(nullptr);
195 tm local_time{};
196 localtime_r(&now, &local_time);
197 return get_tm_gmtoff(&local_time);
198}
199
201 struct timespec ts{};
202 clock_gettime(CLOCK_MONOTONIC, &ts);
203 int64_t seconds = ts.tv_sec;
204 int64_t nanoseconds = ts.tv_nsec;
205 return YoiIntAndIntObject::create(seconds, nanoseconds);
206}
207
208void runtime_time_finalize(void *memory) {
209 free(memory);
210}
void * runtime_object_alloc(unsigned long size)
Definition memory.cpp:96
void runtime_finalize_object(YoiObject *object)
Definition memory.cpp:90
unsigned long long gc_refcount
Definition time.h:24
unsigned long long seconds
Definition time.h:26
unsigned long long nanoseconds
Definition time.h:27
static void gc_refcount_decrease(YoiIntAndIntObject *obj)
Definition time.cpp:154
static YoiIntAndIntObject * create(int64_t seconds, int64_t nanoseconds)
Definition time.cpp:160
int64_t runtime_time_localtimezone_offset()
Get the local timezone offset in seconds.
Definition time.cpp:193
long get_tm_gmtoff(struct tm *t)
Definition time.cpp:148
YoiIntAndIntObject * runtime_time_monotonic_now()
Get the current monotonic time as a YoiIntAndIntObject.
Definition time.cpp:200
void runtime_time_sleep(int64_t seconds, int64_t nanoseconds)
Sleep for a given number of seconds.
Definition time.cpp:177
YoiIntAndIntObject * runtime_time_now()
Return the current time as a YoiIntAndIntObject.
Definition time.cpp:169
void runtime_time_finalize(void *memory)
Finalize the memory created by the time module.
Definition time.cpp:208
char * runtime_time_strftime(const char *format, int64_t timestamp)
Convert a timestamp to a string according to a given format.
Definition time.cpp:184
#define MAX_TIME_STR_LEN
Definition time.h:20