OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(HOST_OS_WINDOWS) | 6 #if defined(HOST_OS_WINDOWS) |
7 | 7 |
8 #include "vm/os.h" | 8 #include "vm/os.h" |
9 | 9 |
10 #include <malloc.h> // NOLINT | 10 #include <malloc.h> // NOLINT |
11 #include <process.h> // NOLINT | 11 #include <process.h> // NOLINT |
12 #include <psapi.h> // NOLINT | 12 #include <psapi.h> // NOLINT |
13 #include <time.h> // NOLINT | 13 #include <time.h> // NOLINT |
14 | 14 |
| 15 #include "platform/assert.h" |
15 #include "platform/utils.h" | 16 #include "platform/utils.h" |
16 #include "platform/assert.h" | |
17 #include "vm/os_thread.h" | 17 #include "vm/os_thread.h" |
18 #include "vm/zone.h" | 18 #include "vm/zone.h" |
19 | 19 |
20 namespace dart { | 20 namespace dart { |
21 | 21 |
22 // Defined in vm/os_thread_win.cc | 22 // Defined in vm/os_thread_win.cc |
23 extern bool private_flag_windows_run_tls_destructors; | 23 extern bool private_flag_windows_run_tls_destructors; |
24 | 24 |
25 const char* OS::Name() { | 25 const char* OS::Name() { |
26 return "windows"; | 26 return "windows"; |
27 } | 27 } |
28 | 28 |
29 | |
30 intptr_t OS::ProcessId() { | 29 intptr_t OS::ProcessId() { |
31 return static_cast<intptr_t>(GetCurrentProcessId()); | 30 return static_cast<intptr_t>(GetCurrentProcessId()); |
32 } | 31 } |
33 | 32 |
34 | |
35 // As a side-effect sets the globals _timezone, _daylight and _tzname. | 33 // As a side-effect sets the globals _timezone, _daylight and _tzname. |
36 static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { | 34 static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) { |
37 time_t seconds = static_cast<time_t>(seconds_since_epoch); | 35 time_t seconds = static_cast<time_t>(seconds_since_epoch); |
38 if (seconds != seconds_since_epoch) { | 36 if (seconds != seconds_since_epoch) { |
39 return false; | 37 return false; |
40 } | 38 } |
41 // localtime_s implicitly sets _timezone, _daylight and _tzname. | 39 // localtime_s implicitly sets _timezone, _daylight and _tzname. |
42 errno_t error_code = localtime_s(tm_result, &seconds); | 40 errno_t error_code = localtime_s(tm_result, &seconds); |
43 return error_code == 0; | 41 return error_code == 0; |
44 } | 42 } |
45 | 43 |
46 | |
47 static int GetDaylightSavingBiasInSeconds() { | 44 static int GetDaylightSavingBiasInSeconds() { |
48 TIME_ZONE_INFORMATION zone_information; | 45 TIME_ZONE_INFORMATION zone_information; |
49 memset(&zone_information, 0, sizeof(zone_information)); | 46 memset(&zone_information, 0, sizeof(zone_information)); |
50 if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) { | 47 if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) { |
51 // By default the daylight saving offset is an hour. | 48 // By default the daylight saving offset is an hour. |
52 return -60 * 60; | 49 return -60 * 60; |
53 } else { | 50 } else { |
54 return static_cast<int>(zone_information.DaylightBias * 60); | 51 return static_cast<int>(zone_information.DaylightBias * 60); |
55 } | 52 } |
56 } | 53 } |
57 | 54 |
58 | |
59 const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { | 55 const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { |
60 TIME_ZONE_INFORMATION zone_information; | 56 TIME_ZONE_INFORMATION zone_information; |
61 memset(&zone_information, 0, sizeof(zone_information)); | 57 memset(&zone_information, 0, sizeof(zone_information)); |
62 | 58 |
63 // Initialize and grab the time zone data. | 59 // Initialize and grab the time zone data. |
64 _tzset(); | 60 _tzset(); |
65 DWORD status = GetTimeZoneInformation(&zone_information); | 61 DWORD status = GetTimeZoneInformation(&zone_information); |
66 if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) { | 62 if (GetTimeZoneInformation(&zone_information) == TIME_ZONE_ID_INVALID) { |
67 // If we can't get the time zone data, the Windows docs indicate that we | 63 // If we can't get the time zone data, the Windows docs indicate that we |
68 // are probably out of memory. Return an empty string. | 64 // are probably out of memory. Return an empty string. |
(...skipping 13 matching lines...) Expand all Loading... |
82 wchar_t* wchar_name = daylight_savings ? zone_information.DaylightName | 78 wchar_t* wchar_name = daylight_savings ? zone_information.DaylightName |
83 : zone_information.StandardName; | 79 : zone_information.StandardName; |
84 intptr_t utf8_len = | 80 intptr_t utf8_len = |
85 WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, NULL, 0, NULL, NULL); | 81 WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, NULL, 0, NULL, NULL); |
86 char* name = Thread::Current()->zone()->Alloc<char>(utf8_len + 1); | 82 char* name = Thread::Current()->zone()->Alloc<char>(utf8_len + 1); |
87 WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, name, utf8_len, NULL, NULL); | 83 WideCharToMultiByte(CP_UTF8, 0, wchar_name, -1, name, utf8_len, NULL, NULL); |
88 name[utf8_len] = '\0'; | 84 name[utf8_len] = '\0'; |
89 return name; | 85 return name; |
90 } | 86 } |
91 | 87 |
92 | |
93 int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) { | 88 int OS::GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch) { |
94 tm decomposed; | 89 tm decomposed; |
95 // LocalTime will set _timezone. | 90 // LocalTime will set _timezone. |
96 bool succeeded = LocalTime(seconds_since_epoch, &decomposed); | 91 bool succeeded = LocalTime(seconds_since_epoch, &decomposed); |
97 if (succeeded) { | 92 if (succeeded) { |
98 int inDaylightSavingsTime = decomposed.tm_isdst; | 93 int inDaylightSavingsTime = decomposed.tm_isdst; |
99 ASSERT(inDaylightSavingsTime == 0 || inDaylightSavingsTime == 1); | 94 ASSERT(inDaylightSavingsTime == 0 || inDaylightSavingsTime == 1); |
100 // Dart and Windows disagree on the sign of the bias. | 95 // Dart and Windows disagree on the sign of the bias. |
101 int offset = static_cast<int>(-_timezone); | 96 int offset = static_cast<int>(-_timezone); |
102 if (inDaylightSavingsTime == 1) { | 97 if (inDaylightSavingsTime == 1) { |
103 static int daylight_bias = GetDaylightSavingBiasInSeconds(); | 98 static int daylight_bias = GetDaylightSavingBiasInSeconds(); |
104 // Subtract because windows and Dart disagree on the sign. | 99 // Subtract because windows and Dart disagree on the sign. |
105 offset = offset - daylight_bias; | 100 offset = offset - daylight_bias; |
106 } | 101 } |
107 return offset; | 102 return offset; |
108 } else { | 103 } else { |
109 // Return zero like V8 does. | 104 // Return zero like V8 does. |
110 return 0; | 105 return 0; |
111 } | 106 } |
112 } | 107 } |
113 | 108 |
114 | |
115 int OS::GetLocalTimeZoneAdjustmentInSeconds() { | 109 int OS::GetLocalTimeZoneAdjustmentInSeconds() { |
116 // TODO(floitsch): avoid excessive calls to _tzset? | 110 // TODO(floitsch): avoid excessive calls to _tzset? |
117 _tzset(); | 111 _tzset(); |
118 // Dart and Windows disagree on the sign of the bias. | 112 // Dart and Windows disagree on the sign of the bias. |
119 return static_cast<int>(-_timezone); | 113 return static_cast<int>(-_timezone); |
120 } | 114 } |
121 | 115 |
122 | |
123 int64_t OS::GetCurrentTimeMillis() { | 116 int64_t OS::GetCurrentTimeMillis() { |
124 return GetCurrentTimeMicros() / 1000; | 117 return GetCurrentTimeMicros() / 1000; |
125 } | 118 } |
126 | 119 |
127 | |
128 int64_t OS::GetCurrentTimeMicros() { | 120 int64_t OS::GetCurrentTimeMicros() { |
129 static const int64_t kTimeEpoc = 116444736000000000LL; | 121 static const int64_t kTimeEpoc = 116444736000000000LL; |
130 static const int64_t kTimeScaler = 10; // 100 ns to us. | 122 static const int64_t kTimeScaler = 10; // 100 ns to us. |
131 | 123 |
132 // Although win32 uses 64-bit integers for representing timestamps, | 124 // Although win32 uses 64-bit integers for representing timestamps, |
133 // these are packed into a FILETIME structure. The FILETIME | 125 // these are packed into a FILETIME structure. The FILETIME |
134 // structure is just a struct representing a 64-bit integer. The | 126 // structure is just a struct representing a 64-bit integer. The |
135 // TimeStamp union allows access to both a FILETIME and an integer | 127 // TimeStamp union allows access to both a FILETIME and an integer |
136 // representation of the timestamp. The Windows timestamp is in | 128 // representation of the timestamp. The Windows timestamp is in |
137 // 100-nanosecond intervals since January 1, 1601. | 129 // 100-nanosecond intervals since January 1, 1601. |
138 union TimeStamp { | 130 union TimeStamp { |
139 FILETIME ft_; | 131 FILETIME ft_; |
140 int64_t t_; | 132 int64_t t_; |
141 }; | 133 }; |
142 TimeStamp time; | 134 TimeStamp time; |
143 GetSystemTimeAsFileTime(&time.ft_); | 135 GetSystemTimeAsFileTime(&time.ft_); |
144 return (time.t_ - kTimeEpoc) / kTimeScaler; | 136 return (time.t_ - kTimeEpoc) / kTimeScaler; |
145 } | 137 } |
146 | 138 |
147 | |
148 static int64_t qpc_ticks_per_second = 0; | 139 static int64_t qpc_ticks_per_second = 0; |
149 | 140 |
150 | |
151 int64_t OS::GetCurrentMonotonicTicks() { | 141 int64_t OS::GetCurrentMonotonicTicks() { |
152 if (qpc_ticks_per_second == 0) { | 142 if (qpc_ticks_per_second == 0) { |
153 // QueryPerformanceCounter not supported, fallback. | 143 // QueryPerformanceCounter not supported, fallback. |
154 return GetCurrentTimeMicros(); | 144 return GetCurrentTimeMicros(); |
155 } | 145 } |
156 // Grab performance counter value. | 146 // Grab performance counter value. |
157 LARGE_INTEGER now; | 147 LARGE_INTEGER now; |
158 QueryPerformanceCounter(&now); | 148 QueryPerformanceCounter(&now); |
159 return static_cast<int64_t>(now.QuadPart); | 149 return static_cast<int64_t>(now.QuadPart); |
160 } | 150 } |
161 | 151 |
162 | |
163 int64_t OS::GetCurrentMonotonicFrequency() { | 152 int64_t OS::GetCurrentMonotonicFrequency() { |
164 if (qpc_ticks_per_second == 0) { | 153 if (qpc_ticks_per_second == 0) { |
165 // QueryPerformanceCounter not supported, fallback. | 154 // QueryPerformanceCounter not supported, fallback. |
166 return kMicrosecondsPerSecond; | 155 return kMicrosecondsPerSecond; |
167 } | 156 } |
168 return qpc_ticks_per_second; | 157 return qpc_ticks_per_second; |
169 } | 158 } |
170 | 159 |
171 | |
172 int64_t OS::GetCurrentMonotonicMicros() { | 160 int64_t OS::GetCurrentMonotonicMicros() { |
173 int64_t ticks = GetCurrentMonotonicTicks(); | 161 int64_t ticks = GetCurrentMonotonicTicks(); |
174 int64_t frequency = GetCurrentMonotonicFrequency(); | 162 int64_t frequency = GetCurrentMonotonicFrequency(); |
175 | 163 |
176 // Convert to microseconds. | 164 // Convert to microseconds. |
177 int64_t seconds = ticks / frequency; | 165 int64_t seconds = ticks / frequency; |
178 int64_t leftover_ticks = ticks - (seconds * frequency); | 166 int64_t leftover_ticks = ticks - (seconds * frequency); |
179 int64_t result = seconds * kMicrosecondsPerSecond; | 167 int64_t result = seconds * kMicrosecondsPerSecond; |
180 result += ((leftover_ticks * kMicrosecondsPerSecond) / frequency); | 168 result += ((leftover_ticks * kMicrosecondsPerSecond) / frequency); |
181 return result; | 169 return result; |
182 } | 170 } |
183 | 171 |
184 | |
185 int64_t OS::GetCurrentThreadCPUMicros() { | 172 int64_t OS::GetCurrentThreadCPUMicros() { |
186 // TODO(johnmccutchan): Implement. See base/time_win.cc for details. | 173 // TODO(johnmccutchan): Implement. See base/time_win.cc for details. |
187 return -1; | 174 return -1; |
188 } | 175 } |
189 | 176 |
190 | |
191 intptr_t OS::ActivationFrameAlignment() { | 177 intptr_t OS::ActivationFrameAlignment() { |
192 #if defined(TARGET_ARCH_ARM64) | 178 #if defined(TARGET_ARCH_ARM64) |
193 return 16; | 179 return 16; |
194 #elif defined(TARGET_ARCH_ARM) | 180 #elif defined(TARGET_ARCH_ARM) |
195 return 8; | 181 return 8; |
196 #elif defined(_WIN64) | 182 #elif defined(_WIN64) |
197 // Windows 64-bit ABI requires the stack to be 16-byte aligned. | 183 // Windows 64-bit ABI requires the stack to be 16-byte aligned. |
198 return 16; | 184 return 16; |
199 #else | 185 #else |
200 // No requirements on Win32. | 186 // No requirements on Win32. |
201 return 1; | 187 return 1; |
202 #endif | 188 #endif |
203 } | 189 } |
204 | 190 |
205 | |
206 intptr_t OS::PreferredCodeAlignment() { | 191 intptr_t OS::PreferredCodeAlignment() { |
207 ASSERT(32 <= OS::kMaxPreferredCodeAlignment); | 192 ASSERT(32 <= OS::kMaxPreferredCodeAlignment); |
208 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ | 193 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \ |
209 defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC) | 194 defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_DBC) |
210 return 32; | 195 return 32; |
211 #elif defined(TARGET_ARCH_ARM) | 196 #elif defined(TARGET_ARCH_ARM) |
212 return 16; | 197 return 16; |
213 #else | 198 #else |
214 #error Unsupported architecture. | 199 #error Unsupported architecture. |
215 #endif | 200 #endif |
216 } | 201 } |
217 | 202 |
218 | |
219 int OS::NumberOfAvailableProcessors() { | 203 int OS::NumberOfAvailableProcessors() { |
220 SYSTEM_INFO info; | 204 SYSTEM_INFO info; |
221 GetSystemInfo(&info); | 205 GetSystemInfo(&info); |
222 return info.dwNumberOfProcessors; | 206 return info.dwNumberOfProcessors; |
223 } | 207 } |
224 | 208 |
225 | |
226 uintptr_t OS::MaxRSS() { | 209 uintptr_t OS::MaxRSS() { |
227 PROCESS_MEMORY_COUNTERS pmc; | 210 PROCESS_MEMORY_COUNTERS pmc; |
228 GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); | 211 GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); |
229 return pmc.PeakWorkingSetSize; | 212 return pmc.PeakWorkingSetSize; |
230 } | 213 } |
231 | 214 |
232 | |
233 void OS::Sleep(int64_t millis) { | 215 void OS::Sleep(int64_t millis) { |
234 ::Sleep(millis); | 216 ::Sleep(millis); |
235 } | 217 } |
236 | 218 |
237 | |
238 void OS::SleepMicros(int64_t micros) { | 219 void OS::SleepMicros(int64_t micros) { |
239 // Windows only supports millisecond sleeps. | 220 // Windows only supports millisecond sleeps. |
240 if (micros < kMicrosecondsPerMillisecond) { | 221 if (micros < kMicrosecondsPerMillisecond) { |
241 // Calling ::Sleep with 0 has no determined behaviour, round up. | 222 // Calling ::Sleep with 0 has no determined behaviour, round up. |
242 micros = kMicrosecondsPerMillisecond; | 223 micros = kMicrosecondsPerMillisecond; |
243 } | 224 } |
244 OS::Sleep(micros / kMicrosecondsPerMillisecond); | 225 OS::Sleep(micros / kMicrosecondsPerMillisecond); |
245 } | 226 } |
246 | 227 |
247 | |
248 void OS::DebugBreak() { | 228 void OS::DebugBreak() { |
249 #if defined(_MSC_VER) | 229 #if defined(_MSC_VER) |
250 // Microsoft Visual C/C++ or drop-in replacement. | 230 // Microsoft Visual C/C++ or drop-in replacement. |
251 __debugbreak(); | 231 __debugbreak(); |
252 #elif defined(__GCC__) | 232 #elif defined(__GCC__) |
253 __builtin_trap(); | 233 __builtin_trap(); |
254 #else | 234 #else |
255 // Microsoft style assembly. | 235 // Microsoft style assembly. |
256 __asm { | 236 __asm { |
257 int 3 | 237 int 3 |
258 } | 238 } |
259 #endif | 239 #endif |
260 } | 240 } |
261 | 241 |
262 | |
263 DART_NOINLINE uintptr_t OS::GetProgramCounter() { | 242 DART_NOINLINE uintptr_t OS::GetProgramCounter() { |
264 return reinterpret_cast<uintptr_t>(_ReturnAddress()); | 243 return reinterpret_cast<uintptr_t>(_ReturnAddress()); |
265 } | 244 } |
266 | 245 |
267 | |
268 char* OS::StrNDup(const char* s, intptr_t n) { | 246 char* OS::StrNDup(const char* s, intptr_t n) { |
269 intptr_t len = strlen(s); | 247 intptr_t len = strlen(s); |
270 if ((n < 0) || (len < 0)) { | 248 if ((n < 0) || (len < 0)) { |
271 return NULL; | 249 return NULL; |
272 } | 250 } |
273 if (n < len) { | 251 if (n < len) { |
274 len = n; | 252 len = n; |
275 } | 253 } |
276 char* result = reinterpret_cast<char*>(malloc(len + 1)); | 254 char* result = reinterpret_cast<char*>(malloc(len + 1)); |
277 if (result == NULL) { | 255 if (result == NULL) { |
278 return NULL; | 256 return NULL; |
279 } | 257 } |
280 result[len] = '\0'; | 258 result[len] = '\0'; |
281 return reinterpret_cast<char*>(memmove(result, s, len)); | 259 return reinterpret_cast<char*>(memmove(result, s, len)); |
282 } | 260 } |
283 | 261 |
284 | |
285 intptr_t OS::StrNLen(const char* s, intptr_t n) { | 262 intptr_t OS::StrNLen(const char* s, intptr_t n) { |
286 return strnlen(s, n); | 263 return strnlen(s, n); |
287 } | 264 } |
288 | 265 |
289 | |
290 void OS::Print(const char* format, ...) { | 266 void OS::Print(const char* format, ...) { |
291 va_list args; | 267 va_list args; |
292 va_start(args, format); | 268 va_start(args, format); |
293 VFPrint(stdout, format, args); | 269 VFPrint(stdout, format, args); |
294 va_end(args); | 270 va_end(args); |
295 } | 271 } |
296 | 272 |
297 | |
298 void OS::VFPrint(FILE* stream, const char* format, va_list args) { | 273 void OS::VFPrint(FILE* stream, const char* format, va_list args) { |
299 vfprintf(stream, format, args); | 274 vfprintf(stream, format, args); |
300 fflush(stream); | 275 fflush(stream); |
301 } | 276 } |
302 | 277 |
303 | |
304 int OS::SNPrint(char* str, size_t size, const char* format, ...) { | 278 int OS::SNPrint(char* str, size_t size, const char* format, ...) { |
305 va_list args; | 279 va_list args; |
306 va_start(args, format); | 280 va_start(args, format); |
307 int retval = VSNPrint(str, size, format, args); | 281 int retval = VSNPrint(str, size, format, args); |
308 va_end(args); | 282 va_end(args); |
309 return retval; | 283 return retval; |
310 } | 284 } |
311 | 285 |
312 | |
313 int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) { | 286 int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) { |
314 if (str == NULL || size == 0) { | 287 if (str == NULL || size == 0) { |
315 int retval = _vscprintf(format, args); | 288 int retval = _vscprintf(format, args); |
316 if (retval < 0) { | 289 if (retval < 0) { |
317 FATAL1("Fatal error in OS::VSNPrint with format '%s'", format); | 290 FATAL1("Fatal error in OS::VSNPrint with format '%s'", format); |
318 } | 291 } |
319 return retval; | 292 return retval; |
320 } | 293 } |
321 va_list args_copy; | 294 va_list args_copy; |
322 va_copy(args_copy, args); | 295 va_copy(args_copy, args); |
(...skipping 14 matching lines...) Expand all Loading... |
337 // Make sure to zero-terminate the string if the output was | 310 // Make sure to zero-terminate the string if the output was |
338 // truncated or if there was an error. | 311 // truncated or if there was an error. |
339 // The static cast is safe here as we have already determined that 'written' | 312 // The static cast is safe here as we have already determined that 'written' |
340 // is >= 0. | 313 // is >= 0. |
341 if (static_cast<size_t>(written) >= size) { | 314 if (static_cast<size_t>(written) >= size) { |
342 str[size - 1] = '\0'; | 315 str[size - 1] = '\0'; |
343 } | 316 } |
344 return written; | 317 return written; |
345 } | 318 } |
346 | 319 |
347 | |
348 char* OS::SCreate(Zone* zone, const char* format, ...) { | 320 char* OS::SCreate(Zone* zone, const char* format, ...) { |
349 va_list args; | 321 va_list args; |
350 va_start(args, format); | 322 va_start(args, format); |
351 char* buffer = VSCreate(zone, format, args); | 323 char* buffer = VSCreate(zone, format, args); |
352 va_end(args); | 324 va_end(args); |
353 return buffer; | 325 return buffer; |
354 } | 326 } |
355 | 327 |
356 | |
357 char* OS::VSCreate(Zone* zone, const char* format, va_list args) { | 328 char* OS::VSCreate(Zone* zone, const char* format, va_list args) { |
358 // Measure. | 329 // Measure. |
359 va_list measure_args; | 330 va_list measure_args; |
360 va_copy(measure_args, args); | 331 va_copy(measure_args, args); |
361 intptr_t len = VSNPrint(NULL, 0, format, measure_args); | 332 intptr_t len = VSNPrint(NULL, 0, format, measure_args); |
362 va_end(measure_args); | 333 va_end(measure_args); |
363 | 334 |
364 char* buffer; | 335 char* buffer; |
365 if (zone) { | 336 if (zone) { |
366 buffer = zone->Alloc<char>(len + 1); | 337 buffer = zone->Alloc<char>(len + 1); |
367 } else { | 338 } else { |
368 buffer = reinterpret_cast<char*>(malloc(len + 1)); | 339 buffer = reinterpret_cast<char*>(malloc(len + 1)); |
369 } | 340 } |
370 ASSERT(buffer != NULL); | 341 ASSERT(buffer != NULL); |
371 | 342 |
372 // Print. | 343 // Print. |
373 va_list print_args; | 344 va_list print_args; |
374 va_copy(print_args, args); | 345 va_copy(print_args, args); |
375 VSNPrint(buffer, len + 1, format, print_args); | 346 VSNPrint(buffer, len + 1, format, print_args); |
376 va_end(print_args); | 347 va_end(print_args); |
377 return buffer; | 348 return buffer; |
378 } | 349 } |
379 | 350 |
380 | |
381 bool OS::StringToInt64(const char* str, int64_t* value) { | 351 bool OS::StringToInt64(const char* str, int64_t* value) { |
382 ASSERT(str != NULL && strlen(str) > 0 && value != NULL); | 352 ASSERT(str != NULL && strlen(str) > 0 && value != NULL); |
383 int32_t base = 10; | 353 int32_t base = 10; |
384 char* endptr; | 354 char* endptr; |
385 int i = 0; | 355 int i = 0; |
386 if (str[0] == '-') { | 356 if (str[0] == '-') { |
387 i = 1; | 357 i = 1; |
388 } | 358 } |
389 if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') && | 359 if ((str[i] == '0') && (str[i + 1] == 'x' || str[i + 1] == 'X') && |
390 (str[i + 2] != '\0')) { | 360 (str[i + 2] != '\0')) { |
391 base = 16; | 361 base = 16; |
392 } | 362 } |
393 errno = 0; | 363 errno = 0; |
394 *value = _strtoi64(str, &endptr, base); | 364 *value = _strtoi64(str, &endptr, base); |
395 return ((errno == 0) && (endptr != str) && (*endptr == 0)); | 365 return ((errno == 0) && (endptr != str) && (*endptr == 0)); |
396 } | 366 } |
397 | 367 |
398 | |
399 void OS::RegisterCodeObservers() {} | 368 void OS::RegisterCodeObservers() {} |
400 | 369 |
401 | |
402 void OS::PrintErr(const char* format, ...) { | 370 void OS::PrintErr(const char* format, ...) { |
403 va_list args; | 371 va_list args; |
404 va_start(args, format); | 372 va_start(args, format); |
405 VFPrint(stderr, format, args); | 373 VFPrint(stderr, format, args); |
406 va_end(args); | 374 va_end(args); |
407 } | 375 } |
408 | 376 |
409 | |
410 void OS::InitOnce() { | 377 void OS::InitOnce() { |
411 // TODO(5411554): For now we check that initonce is called only once, | 378 // TODO(5411554): For now we check that initonce is called only once, |
412 // Once there is more formal mechanism to call InitOnce we can move | 379 // Once there is more formal mechanism to call InitOnce we can move |
413 // this check there. | 380 // this check there. |
414 static bool init_once_called = false; | 381 static bool init_once_called = false; |
415 ASSERT(init_once_called == false); | 382 ASSERT(init_once_called == false); |
416 init_once_called = true; | 383 init_once_called = true; |
417 // Do not pop up a message box when abort is called. | 384 // Do not pop up a message box when abort is called. |
418 _set_abort_behavior(0, _WRITE_ABORT_MSG); | 385 _set_abort_behavior(0, _WRITE_ABORT_MSG); |
419 ThreadLocalData::InitOnce(); | 386 ThreadLocalData::InitOnce(); |
420 MonitorWaitData::monitor_wait_data_key_ = OSThread::CreateThreadLocal(); | 387 MonitorWaitData::monitor_wait_data_key_ = OSThread::CreateThreadLocal(); |
421 MonitorData::GetMonitorWaitDataForThread(); | 388 MonitorData::GetMonitorWaitDataForThread(); |
422 LARGE_INTEGER ticks_per_sec; | 389 LARGE_INTEGER ticks_per_sec; |
423 if (!QueryPerformanceFrequency(&ticks_per_sec)) { | 390 if (!QueryPerformanceFrequency(&ticks_per_sec)) { |
424 qpc_ticks_per_second = 0; | 391 qpc_ticks_per_second = 0; |
425 } else { | 392 } else { |
426 qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart); | 393 qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart); |
427 } | 394 } |
428 } | 395 } |
429 | 396 |
430 | |
431 void OS::Shutdown() { | 397 void OS::Shutdown() { |
432 // TODO(zra): Enable once VM can shutdown cleanly. | 398 // TODO(zra): Enable once VM can shutdown cleanly. |
433 // ThreadLocalData::Shutdown(); | 399 // ThreadLocalData::Shutdown(); |
434 } | 400 } |
435 | 401 |
436 | |
437 void OS::Abort() { | 402 void OS::Abort() { |
438 // TODO(zra): Remove once VM shuts down cleanly. | 403 // TODO(zra): Remove once VM shuts down cleanly. |
439 private_flag_windows_run_tls_destructors = false; | 404 private_flag_windows_run_tls_destructors = false; |
440 abort(); | 405 abort(); |
441 } | 406 } |
442 | 407 |
443 | |
444 void OS::Exit(int code) { | 408 void OS::Exit(int code) { |
445 // TODO(zra): Remove once VM shuts down cleanly. | 409 // TODO(zra): Remove once VM shuts down cleanly. |
446 private_flag_windows_run_tls_destructors = false; | 410 private_flag_windows_run_tls_destructors = false; |
447 // On Windows we use ExitProcess so that threads can't clobber the exit_code. | 411 // On Windows we use ExitProcess so that threads can't clobber the exit_code. |
448 // See: https://code.google.com/p/nativeclient/issues/detail?id=2870 | 412 // See: https://code.google.com/p/nativeclient/issues/detail?id=2870 |
449 ::ExitProcess(code); | 413 ::ExitProcess(code); |
450 } | 414 } |
451 | 415 |
452 } // namespace dart | 416 } // namespace dart |
453 | 417 |
454 #endif // defined(HOST_OS_WINDOWS) | 418 #endif // defined(HOST_OS_WINDOWS) |
OLD | NEW |