Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
os_win.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h"
6#if defined(DART_HOST_OS_WINDOWS)
7
8#include "vm/os.h"
9
10#include <malloc.h> // NOLINT
11#include <process.h> // NOLINT
12#include <psapi.h> // NOLINT
13#include <time.h> // NOLINT
14
15#include "platform/assert.h"
16#include "platform/utils.h"
17#include "vm/image_snapshot.h"
18#include "vm/os_thread.h"
19#include "vm/zone.h"
20
21namespace dart {
22
23// Defined in vm/os_thread_win.cc
24extern bool private_flag_windows_run_tls_destructors;
25
26intptr_t OS::ProcessId() {
27 return static_cast<intptr_t>(GetCurrentProcessId());
28}
29
30// 100-nanoseconds intervals from from 1601-01-01 to 1970-01-01.
31const int64_t kTimeEpoc = 116444736000000000LL;
32
33static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) {
34 time_t seconds = static_cast<time_t>(seconds_since_epoch);
35 SYSTEMTIME systemTime;
36 union {
37 FILETIME fileTime;
38 ULARGE_INTEGER ulargeInt;
39 };
40 const int64_t kTimeScaler = 10 * 1000 * 1000; // 100 ns to s.
41 const int64_t hundreds_us = seconds_since_epoch * kTimeScaler;
42 ulargeInt.QuadPart = kTimeEpoc + hundreds_us;
43
44 if (!FileTimeToSystemTime(&fileTime, &systemTime)) {
45 return false;
46 }
47
48 TIME_ZONE_INFORMATION timeZoneInformation;
49 if (!GetTimeZoneInformationForYear(systemTime.wYear, nullptr,
50 &timeZoneInformation)) {
51 return false;
52 }
53
54 SYSTEMTIME localTime;
55 if (!SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &systemTime,
56 &localTime)) {
57 return false;
58 }
59 // To determine whether the date is in DST or not, if tz has daylight
60 // bias set, we run convert system time to tz-specific time twice: first
61 // with the original bias, then with bias reset 0 and compare the result
62 // time. If they match, we are oustide of DST, if they don't - we are inside.
63 ASSERT(tm_result != nullptr);
64 if (timeZoneInformation.DaylightBias == 0) {
65 tm_result->tm_isdst = 0;
66 } else {
67 const auto hourWithDaylightBias = localTime.wHour;
68 timeZoneInformation.DaylightBias = 0;
69 if (!SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &systemTime,
70 &localTime)) {
71 return false;
72 }
73 const auto hourWithoutDaylightBias = localTime.wHour;
74 tm_result->tm_isdst = hourWithDaylightBias != hourWithoutDaylightBias;
75 }
76
77 // Populate the rest of the fields even though they are not really used
78 // in this module.
79 tm_result->tm_year = localTime.wYear;
80 tm_result->tm_mon = localTime.wMonth;
81 tm_result->tm_hour = localTime.wHour;
82 tm_result->tm_wday = localTime.wDayOfWeek;
83 tm_result->tm_mday = localTime.wDay;
84 tm_result->tm_min = localTime.wMinute;
85 tm_result->tm_sec = localTime.wSecond;
86 tm_result->tm_yday = 0; // Seemingly no easily-available source for this.
87 return true;
88}
89
90static int GetDaylightSavingBiasInSeconds() {
91 TIME_ZONE_INFORMATION zone_information;
92 memset(&zone_information, 0, sizeof(zone_information));
93 if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) {
94 // By default the daylight saving offset is an hour.
95 return -60 * 60;
96 } else {
97 return static_cast<int>(zone_information.DaylightBias * 60);
98 }
99}
100
101const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) {
102 TIME_ZONE_INFORMATION zone_information;
103 memset(&zone_information, 0, sizeof(zone_information));
104
105 // Initialize and grab the time zone data.
106 _tzset();
107 DWORD status = GetTimeZoneInformation(&zone_information);
108 if (status == TIME_ZONE_ID_INVALID) {
109 // If we can't get the time zone data, the Windows docs indicate that we
110 // are probably out of memory. Return an empty string.
111 return "";
112 }
113
114 // Figure out whether we're in standard or daylight.
115 tm local_time;
116 if (!LocalTime(seconds_since_epoch, &local_time)) {
117 return "";
118 }
119 const bool daylight_savings = (local_time.tm_isdst == 1);
120
121 // Convert the wchar string to a null-terminated utf8 string.
122 wchar_t* wchar_name = daylight_savings ? zone_information.DaylightName
123 : zone_information.StandardName;
124 intptr_t utf8_len = WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, nullptr,
125 0, nullptr, nullptr);
126 char* name = ThreadState::Current()->zone()->Alloc<char>(utf8_len + 1);
127 WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, name, utf8_len, nullptr,
128 nullptr);
129 name[utf8_len] = '\0';
130 return name;
131}
132
133int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) {
134 tm decomposed;
135 bool succeeded = LocalTime(seconds_since_epoch, &decomposed);
136 if (succeeded) {
137 int inDaylightSavingsTime = decomposed.tm_isdst;
138 ASSERT(inDaylightSavingsTime == 0 || inDaylightSavingsTime == 1);
139 tzset();
140 // Dart and Windows disagree on the sign of the bias.
141 int offset = static_cast<int>(-_timezone);
142 if (inDaylightSavingsTime == 1) {
143 static int daylight_bias = GetDaylightSavingBiasInSeconds();
144 // Subtract because windows and Dart disagree on the sign.
145 offset = offset - daylight_bias;
146 }
147 return offset;
148 } else {
149 // Return zero like V8 does.
150 return 0;
151 }
152}
153
154int64_t OS::GetCurrentTimeMillis() {
155 return GetCurrentTimeMicros() / 1000;
156}
157
158int64_t OS::GetCurrentTimeMicros() {
159 const int64_t kTimeScaler = 10; // 100 ns to us.
160
161 // Although win32 uses 64-bit integers for representing timestamps,
162 // these are packed into a FILETIME structure. The FILETIME
163 // structure is just a struct representing a 64-bit integer. The
164 // TimeStamp union allows access to both a FILETIME and an integer
165 // representation of the timestamp. The Windows timestamp is in
166 // 100-nanosecond intervals since January 1, 1601.
167 union TimeStamp {
168 FILETIME ft_;
169 int64_t t_;
170 };
171 TimeStamp time;
172 GetSystemTimeAsFileTime(&time.ft_);
173 return (time.t_ - kTimeEpoc) / kTimeScaler;
174}
175
176static int64_t qpc_ticks_per_second = 0;
177
179 if (qpc_ticks_per_second == 0) {
180 // QueryPerformanceCounter not supported, fallback.
181 return GetCurrentTimeMicros();
182 }
183 // Grab performance counter value.
184 LARGE_INTEGER now;
185 QueryPerformanceCounter(&now);
186 return static_cast<int64_t>(now.QuadPart);
187}
188
190 if (qpc_ticks_per_second == 0) {
191 // QueryPerformanceCounter not supported, fallback.
193 }
194 return qpc_ticks_per_second;
195}
196
198 int64_t ticks = GetCurrentMonotonicTicks();
199 int64_t frequency = GetCurrentMonotonicFrequency();
200
201 // Convert to microseconds.
202 int64_t seconds = ticks / frequency;
203 int64_t leftover_ticks = ticks - (seconds * frequency);
204 int64_t result = seconds * kMicrosecondsPerSecond;
205 result += ((leftover_ticks * kMicrosecondsPerSecond) / frequency);
206 return result;
207}
208
210 // TODO(johnmccutchan): Implement. See base/time_win.cc for details.
211 return -1;
212}
213
215#if defined(SUPPORT_TIMELINE)
217#else
218 return -1;
219#endif
220}
221
223#if defined(TARGET_ARCH_ARM64)
224 return 16;
225#elif defined(TARGET_ARCH_ARM)
226 return 8;
227#elif defined(_WIN64)
228 // Windows 64-bit ABI requires the stack to be 16-byte aligned.
229 return 16;
230#else
231 // No requirements on Win32.
232 return 1;
233#endif
234}
235
237 SYSTEM_INFO info;
238 GetSystemInfo(&info);
239 return info.dwNumberOfProcessors;
240}
241
242void OS::Sleep(int64_t millis) {
243 ::Sleep(millis);
244}
245
246void OS::SleepMicros(int64_t micros) {
247 // Windows only supports millisecond sleeps.
248 if (micros < kMicrosecondsPerMillisecond) {
249 // Calling ::Sleep with 0 has no determined behaviour, round up.
251 }
253}
254
255void OS::DebugBreak() {
256#if defined(_MSC_VER)
257 // Microsoft Visual C/C++ or drop-in replacement.
258 __debugbreak();
259#elif defined(__GCC__)
260 __builtin_trap();
261#else
262 // Microsoft style assembly.
263 __asm {
264 int 3
265 }
266#endif
267}
268
269DART_NOINLINE uintptr_t OS::GetProgramCounter() {
270 return reinterpret_cast<uintptr_t>(_ReturnAddress());
271}
272
273void OS::Print(const char* format, ...) {
274 va_list args;
276 VFPrint(stdout, format, args);
277 va_end(args);
278}
279
280void OS::VFPrint(FILE* stream, const char* format, va_list args) {
281 vfprintf(stream, format, args);
282 fflush(stream);
283}
284
285char* OS::SCreate(Zone* zone, const char* format, ...) {
286 va_list args;
288 char* buffer = VSCreate(zone, format, args);
289 va_end(args);
290 return buffer;
291}
292
293char* OS::VSCreate(Zone* zone, const char* format, va_list args) {
294 // Measure.
295 va_list measure_args;
296 va_copy(measure_args, args);
297 intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
298 va_end(measure_args);
299
300 char* buffer;
301 if (zone) {
302 buffer = zone->Alloc<char>(len + 1);
303 } else {
304 buffer = reinterpret_cast<char*>(malloc(len + 1));
305 }
306 ASSERT(buffer != nullptr);
307
308 // Print.
309 va_list print_args;
310 va_copy(print_args, args);
311 Utils::VSNPrint(buffer, len + 1, format, print_args);
312 va_end(print_args);
313 return buffer;
314}
315
316bool OS::StringToInt64(const char* str, int64_t* value) {
317 ASSERT(str != nullptr && strlen(str) > 0 && value != nullptr);
318 int32_t base = 10;
319 char* endptr;
320 int i = 0;
321 if (str[0] == '-') {
322 i = 1;
323 } else if (str[0] == '+') {
324 i = 1;
325 }
326 if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') &&
327 (str[i + 2] != '\0')) {
328 base = 16;
329 }
330 errno = 0;
331 if (base == 16) {
332 // Unsigned 64-bit hexadecimal integer literals are allowed but
333 // immediately interpreted as signed 64-bit integers.
334 *value = static_cast<int64_t>(_strtoui64(str, &endptr, base));
335 } else {
336 *value = _strtoi64(str, &endptr, base);
337 }
338 return ((errno == 0) && (endptr != str) && (*endptr == 0));
339}
340
342
343void OS::PrintErr(const char* format, ...) {
344 va_list args;
346 VFPrint(stderr, format, args);
347 va_end(args);
348}
349
350void OS::Init() {
351 static bool init_once_called = false;
352 if (init_once_called) {
353 return;
354 }
355 init_once_called = true;
356 // Do not pop up a message box when abort is called.
357 _set_abort_behavior(0, _WRITE_ABORT_MSG);
358 ThreadLocalData::Init();
359 LARGE_INTEGER ticks_per_sec;
360 if (!QueryPerformanceFrequency(&ticks_per_sec)) {
361 qpc_ticks_per_second = 0;
362 } else {
363 qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart);
364 }
365}
366
367void OS::Cleanup() {
368 // TODO(zra): Enable once VM can shutdown cleanly.
369 // ThreadLocalData::Cleanup();
370}
371
372void OS::PrepareToAbort() {
373 // TODO(zra): Remove once VM shuts down cleanly.
374 private_flag_windows_run_tls_destructors = false;
375}
376
377void OS::Abort() {
379 abort();
380}
381
382void OS::Exit(int code) {
383 // TODO(zra): Remove once VM shuts down cleanly.
384 private_flag_windows_run_tls_destructors = false;
385 // On Windows we use ExitProcess so that threads can't clobber the exit_code.
386 // See: https://code.google.com/p/nativeclient/issues/detail?id=2870
387 ::ExitProcess(code);
388}
389
390OS::BuildId OS::GetAppBuildId(const uint8_t* snapshot_instructions) {
391 // Since we only use direct-to-ELF snapshots on Windows, the build ID
392 // information must be available from the instructions image.
393 const Image instructions_image(snapshot_instructions);
394 auto* const image_build_id = instructions_image.build_id();
395 ASSERT(image_build_id != nullptr);
396 return {instructions_image.build_id_length(), image_build_id};
397}
398
399} // namespace dart
400
401#endif // defined(DART_HOST_OS_WINDOWS)
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
static DART_NORETURN void Exit(int code)
static int NumberOfAvailableProcessors()
static const char * GetTimeZoneName(int64_t seconds_since_epoch)
static void SleepMicros(int64_t micros)
static int64_t GetCurrentTimeMillis()
static void RegisterCodeObservers()
static int64_t GetCurrentMonotonicMicros()
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static void Sleep(int64_t millis)
static void Print(const char *format,...) PRINTF_ATTRIBUTE(1
static bool StringToInt64(const char *str, int64_t *value)
static BuildId GetAppBuildId(const uint8_t *snapshot_instructions)
static void Init()
static int64_t GetCurrentTimeMicros()
static intptr_t ActivationFrameAlignment()
static void static void static void VFPrint(FILE *stream, const char *format, va_list args)
static void Cleanup()
static void DebugBreak()
static DART_NORETURN void Abort()
static char static char * VSCreate(Zone *zone, const char *format, va_list args)
static int64_t GetCurrentThreadCPUMicros()
static uintptr_t GetProgramCounter()
static intptr_t ProcessId()
static void PrepareToAbort()
static int64_t GetCurrentMonotonicFrequency()
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
static int64_t GetCurrentMonotonicTicks()
static int64_t GetCurrentMonotonicMicrosForTimeline()
static int GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch)
Zone * zone() const
static ThreadState * Current()
static int static int VSNPrint(char *str, size_t size, const char *format, va_list args)
ElementType * Alloc(intptr_t length)
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint8_t value
GAsyncResult * result
uint32_t uint32_t * format
va_start(args, format)
va_end(args)
constexpr intptr_t kMicrosecondsPerMillisecond
Definition globals.h:561
const char *const name
constexpr intptr_t kMicrosecondsPerSecond
Definition globals.h:562
void * malloc(size_t size)
Definition allocation.cc:19
CanvasImage Image
Definition dart_ui.cc:55
Point offset
struct _FILETIME FILETIME
unsigned long DWORD