Flutter Engine
The Flutter Engine
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
Definition: thread_state.h:37
static ThreadState * Current()
Definition: thread_state.h:27
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
uint8_t value
GAsyncResult * result
uint32_t uint32_t * format
va_start(args, format)
va_end(args)
Definition: dart_vm.cc:33
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
static zx_koid_t GetCurrentProcessId()
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
CanvasImage Image
Definition: dart_ui.cc:55
static double time(int loops, Benchmark *bench, Target *target)
Definition: nanobench.cpp:394
SeparatedVector2 offset
struct _FILETIME FILETIME
unsigned long DWORD
Definition: windows_types.h:22