| 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 |