1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Platform-specific code for Win32. 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Secure API functions are not available using MinGW with msvcrt.dll 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// on Windows XP. Make sure MINGW_HAS_SECURE_API is not defined to 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// disable definition of secure API functions in standard headers that 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// would conflict with our own implementation. 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __MINGW32__ 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <_mingw.h> 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef MINGW_HAS_SECURE_API 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef MINGW_HAS_SECURE_API 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // MINGW_HAS_SECURE_API 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // __MINGW32__ 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <limits> 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/win32-headers.h" 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h" 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/lazy-instance.h" 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/macros.h" 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h" 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/time.h" 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/utils/random-number-generator.h" 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Extra functions for MinGW. Most of these are the _s functions which are in 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the Microsoft Visual Studio C++ CRT. 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef __MINGW32__ 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef __MINGW64_VERSION_MAJOR 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define _TRUNCATE 0 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define STRUNCATE 80 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline void MemoryBarrier() { 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int barrier = 0; 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __asm__ __volatile__("xchgl %%eax,%0 ":"=r" (barrier)); 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // __MINGW64_VERSION_MAJOR 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint localtime_s(tm* out_tm, const time_t* time) { 49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch tm* posix_local_time_struct = localtime_r(time, out_tm); 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (posix_local_time_struct == NULL) return 1; 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint fopen_s(FILE** pFile, const char* filename, const char* mode) { 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *pFile = fopen(filename, mode); 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return *pFile != NULL ? 0 : 1; 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint _vsnprintf_s(char* buffer, size_t sizeOfBuffer, size_t count, 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* format, va_list argptr) { 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count == _TRUNCATE); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return _vsnprintf(buffer, sizeOfBuffer, format, argptr); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint strncpy_s(char* dest, size_t dest_size, const char* source, size_t count) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(source != NULL); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(dest != NULL); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_GT(dest_size, 0); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (count == _TRUNCATE) { 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (dest_size > 0 && *source != 0) { 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *(dest++) = *(source++); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch --dest_size; 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dest_size == 0) { 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *(dest - 1) = 0; 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return STRUNCATE; 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (dest_size > 0 && count > 0 && *source != 0) { 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *(dest++) = *(source++); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch --dest_size; 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch --count; 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK_GT(dest_size, 0); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *dest = 0; 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // __MINGW32__ 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base { 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool g_hard_abort = false; 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass TimezoneCache { 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TimezoneCache() : initialized_(false) { } 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void Clear() { 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch initialized_ = false; 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initialize timezone information. The timezone information is obtained from 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // windows. If we cannot get the timezone information we fall back to CET. 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void InitializeIfNeeded() { 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Just return if timezone information has already been initialized. 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (initialized_) return; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initialize POSIX time zone data. 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch _tzset(); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Obtain timezone information from operating system. 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memset(&tzinfo_, 0, sizeof(tzinfo_)); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) { 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we cannot get timezone information we fall back to CET. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.Bias = -60; 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.StandardDate.wMonth = 10; 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.StandardDate.wDay = 5; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.StandardDate.wHour = 3; 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.StandardBias = 0; 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.DaylightDate.wMonth = 3; 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.DaylightDate.wDay = 5; 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.DaylightDate.wHour = 2; 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tzinfo_.DaylightBias = -60; 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make standard and DST timezone names. 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1, 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std_tz_name_, kTzNameSize, NULL, NULL); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std_tz_name_[kTzNameSize - 1] = '\0'; 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1, 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dst_tz_name_, kTzNameSize, NULL, NULL); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dst_tz_name_[kTzNameSize - 1] = '\0'; 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If OS returned empty string or resource id (like "@tzres.dll,-211") 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // simply guess the name from the UTC bias of the timezone. 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // To properly resolve the resource identifier requires a library load, 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // which is not possible in a sandbox. 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') { 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OS::SNPrintF(std_tz_name_, kTzNameSize - 1, 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%s Standard Time", 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GuessTimezoneNameFromBias(tzinfo_.Bias)); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') { 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OS::SNPrintF(dst_tz_name_, kTzNameSize - 1, 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch "%s Daylight Time", 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GuessTimezoneNameFromBias(tzinfo_.Bias)); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Timezone information initialized. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch initialized_ = true; 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Guess the name of the timezone from the bias. 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The guess is very biased towards the northern hemisphere. 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* GuessTimezoneNameFromBias(int bias) { 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kHour = 60; 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (-bias) { 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case -9*kHour: return "Alaska"; 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case -8*kHour: return "Pacific"; 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case -7*kHour: return "Mountain"; 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case -6*kHour: return "Central"; 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case -5*kHour: return "Eastern"; 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case -4*kHour: return "Atlantic"; 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case 0*kHour: return "GMT"; 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +1*kHour: return "Central Europe"; 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +2*kHour: return "Eastern Europe"; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +3*kHour: return "Russia"; 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +5*kHour + 30: return "India"; 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +8*kHour: return "China"; 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +9*kHour: return "Japan"; 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case +12*kHour: return "New Zealand"; 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: return "Local"; 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kTzNameSize = 128; 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool initialized_; 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char std_tz_name_[kTzNameSize]; 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char dst_tz_name_[kTzNameSize]; 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TIME_ZONE_INFORMATION tzinfo_; 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch friend class Win32Time; 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ---------------------------------------------------------------------------- 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The Time class represents time on win32. A timestamp is represented as 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// timestamps are represented as a doubles in milliseconds since 00:00:00 UTC, 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// January 1, 1970. 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Win32Time { 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constructors. 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Win32Time(); 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit Win32Time(double jstime); 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Win32Time(int year, int mon, int day, int hour, int min, int sec); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert timestamp to JavaScript representation. 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double ToJSTime(); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set timestamp to current time. 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void SetToCurrentTime(); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the local timezone offset in milliseconds east of UTC. This is 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the number of milliseconds you must add to UTC to get local time, i.e. 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // routine also takes into account whether daylight saving is effect 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // at the time. 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t LocalOffset(TimezoneCache* cache); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns the daylight savings time offset for the time in milliseconds. 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t DaylightSavingsOffset(TimezoneCache* cache); 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Returns a string identifying the current timezone for the 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // timestamp taking into account daylight saving. 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* LocalTimezone(TimezoneCache* cache); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constants for time conversion. 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int64_t kTimeEpoc = 116444736000000000LL; 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int64_t kTimeScaler = 10000; 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int64_t kMsPerMinute = 60000; 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Constants for timezone information. 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const bool kShortTzNames = false; 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return whether or not daylight savings time is in effect at this time. 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool InDST(TimezoneCache* cache); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessor for FILETIME representation. 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILETIME& ft() { return time_.ft_; } 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessor for integer representation. 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t& t() { return time_.t_; } 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Although win32 uses 64-bit integers for representing timestamps, 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // these are packed into a FILETIME structure. The FILETIME structure 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is just a struct representing a 64-bit integer. The TimeStamp union 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // allows access to both a FILETIME and an integer representation of 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the timestamp. 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch union TimeStamp { 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILETIME ft_; 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t t_; 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch }; 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TimeStamp time_; 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Initialize timestamp to start of epoc. 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochWin32Time::Win32Time() { 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t() = 0; 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Initialize timestamp from a JavaScript timestamp. 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochWin32Time::Win32Time(double jstime) { 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc; 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Initialize timestamp from date/time components. 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochWin32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) { 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SYSTEMTIME st; 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wYear = year; 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wMonth = mon; 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wDay = day; 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wHour = hour; 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wMinute = min; 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wSecond = sec; 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch st.wMilliseconds = 0; 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SystemTimeToFileTime(&st, &ft()); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Convert timestamp to JavaScript timestamp. 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble Win32Time::ToJSTime() { 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<double>((t() - kTimeEpoc) / kTimeScaler); 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Set timestamp to current time. 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Win32Time::SetToCurrentTime() { 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The default GetSystemTimeAsFileTime has a ~15.5ms resolution. 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Because we're fast, we like fast timers which have at least a 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 1ms resolution. 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // timeGetTime() provides 1ms granularity when combined with 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // timeBeginPeriod(). If the host application for v8 wants fast 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // timers, it can use timeBeginPeriod to increase the resolution. 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Using timeGetTime() has a drawback because it is a 32bit value 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and hence rolls-over every ~49days. 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // To use the clock, we use GetSystemTimeAsFileTime as our base; 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and then use timeGetTime to extrapolate current time from the 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // start time. To deal with rollovers, we resync the clock 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // any time when more than kMaxClockElapsedTime has passed or 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // whenever timeGetTime creates a rollover. 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool initialized = false; 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static TimeStamp init_time; 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static DWORD init_ticks; 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int64_t kHundredNanosecondsPerSecond = 10000000; 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int64_t kMaxClockElapsedTime = 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 60*kHundredNanosecondsPerSecond; // 1 minute 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we are uninitialized, we need to resync the clock. 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool needs_resync = !initialized; 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the current time. 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TimeStamp time_now; 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetSystemTimeAsFileTime(&time_now.ft_); 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD ticks_now = timeGetTime(); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if we need to resync due to clock rollover. 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needs_resync |= ticks_now < init_ticks; 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if we need to resync due to elapsed time. 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if we need to resync due to backwards time change. 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch needs_resync |= time_now.t_ < init_time.t_; 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Resync the clock if necessary. 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (needs_resync) { 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetSystemTimeAsFileTime(&init_time.ft_); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch init_ticks = ticks_now = timeGetTime(); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch initialized = true; 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Finally, compute the actual time. Why is this so hard. 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD elapsed = ticks_now - init_ticks; 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Return the local timezone offset in milliseconds east of UTC. This 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// takes into account whether daylight saving is in effect at the time. 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Only times in the 32-bit Unix range may be passed to this function. 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Also, adding the time-zone offset to the input must not overflow. 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The function EquivalentTime() in date.js guarantees this. 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint64_t Win32Time::LocalOffset(TimezoneCache* cache) { 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache->InitializeIfNeeded(); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Win32Time rounded_to_second(*this); 357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier rounded_to_second.t() = 358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier rounded_to_second.t() / 1000 / kTimeScaler * 1000 * kTimeScaler; 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert to local time using POSIX localtime function. 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime() 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // very slow. Other browsers use localtime(). 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // POSIX seconds past 1/1/1970 0:00:00. 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000; 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) { 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int. 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch time_t posix_time = static_cast<time_t>(unchecked_posix_time); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert to local time, as struct with fields for day, hour, year, etc. 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch tm posix_local_time_struct; 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (localtime_s(&posix_local_time_struct, &posix_time)) return 0; 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (posix_local_time_struct.tm_isdst > 0) { 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * -kMsPerMinute; 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (posix_local_time_struct.tm_isdst == 0) { 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (cache->tzinfo_.Bias + cache->tzinfo_.StandardBias) * -kMsPerMinute; 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return cache->tzinfo_.Bias * -kMsPerMinute; 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Return whether or not daylight savings time is in effect at this time. 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Win32Time::InDST(TimezoneCache* cache) { 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache->InitializeIfNeeded(); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Determine if DST is in effect at the specified time. 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool in_dst = false; 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cache->tzinfo_.StandardDate.wMonth != 0 || 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache->tzinfo_.DaylightDate.wMonth != 0) { 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the local timezone offset for the timestamp in milliseconds. 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t offset = LocalOffset(cache); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the offset for DST. The bias parameters in the timezone info 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // are specified in minutes. These must be converted to milliseconds. 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t dstofs = 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch -(cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * kMsPerMinute; 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the local time offset equals the timezone bias plus the daylight 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bias then DST is in effect. 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch in_dst = offset == dstofs; 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return in_dst; 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Return the daylight savings time offset for this time. 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint64_t Win32Time::DaylightSavingsOffset(TimezoneCache* cache) { 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return InDST(cache) ? 60 * kMsPerMinute : 0; 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns a string identifying the current timezone for the 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// timestamp taking into account daylight saving. 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochchar* Win32Time::LocalTimezone(TimezoneCache* cache) { 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return the standard or DST time zone name based on whether daylight 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // saving is in effect at the given time. 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return InDST(cache) ? cache->dst_tz_name_ : cache->std_tz_name_; 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns the accumulated user time for thread. 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILETIME dummy; 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint64_t usertime; 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the amount of time that the thread has executed in user mode. 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy, 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<FILETIME*>(&usertime))) return -1; 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Adjust the resolution to micro-seconds. 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch usertime /= 10; 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Convert to seconds and microseconds 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *secs = static_cast<uint32_t>(usertime / 1000000); 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *usecs = static_cast<uint32_t>(usertime % 1000000); 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns current time as the number of milliseconds since 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 00:00:00 UTC, January 1, 1970. 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble OS::TimeCurrentMillis() { 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Time::Now().ToJsTime(); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTimezoneCache* OS::CreateTimezoneCache() { 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new TimezoneCache(); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::DisposeTimezoneCache(TimezoneCache* cache) { 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete cache; 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::ClearTimezoneCache(TimezoneCache* cache) { 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cache->Clear(); 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns a string identifying the current timezone taking into 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// account daylight saving. 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* OS::LocalTimezone(double time, TimezoneCache* cache) { 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Win32Time(time).LocalTimezone(cache); 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns the local time offset in milliseconds east of UTC without 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// taking daylight savings time into account. 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble OS::LocalTimeOffset(TimezoneCache* cache) { 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use current time, rounded to the millisecond. 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Win32Time t(TimeCurrentMillis()); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<double>(t.LocalOffset(cache) - 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t.DaylightSavingsOffset(cache)); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Returns the daylight savings offset in milliseconds for the given 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// time. 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochdouble OS::DaylightSavingsOffset(double time, TimezoneCache* cache) { 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int64_t offset = Win32Time(time).DaylightSavingsOffset(cache); 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<double>(offset); 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::GetLastError() { 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ::GetLastError(); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::GetCurrentProcessId() { 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<int>(::GetCurrentProcessId()); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::GetCurrentThreadId() { 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<int>(::GetCurrentThreadId()); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ---------------------------------------------------------------------------- 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Win32 console output. 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If a Win32 application is linked as a console application it has a normal 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// standard output and standard error. In this case normal printf works fine 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// for output. However, if the application is linked as a GUI application, 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the process doesn't have a console, and therefore (debugging) output is lost. 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// This is the case if we are embedded in a windows program (like a browser). 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// In order to be able to get debug output in this case the the debugging 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// facility using OutputDebugString. This output goes to the active debugger 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// for the process (if any). Else the output can be monitored using DBMON.EXE. 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum OutputMode { 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNKNOWN, // Output method has not yet been determined. 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CONSOLE, // Output is written to stdout. 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ODS // Output is written to debug facility. 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic OutputMode output_mode = UNKNOWN; // Current output mode. 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Determine if the process has a console for output. 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool HasConsole() { 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only check the first time. Eventual race conditions are not a problem, 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // because all threads will eventually determine the same mode. 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (output_mode == UNKNOWN) { 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We cannot just check that the standard output is attached to a console 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // because this would fail if output is redirected to a file. Therefore we 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // say that a process does not have an output console if either the 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // standard output handle is invalid or its file type is unknown. 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE && 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN) 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch output_mode = CONSOLE; 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch else 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch output_mode = ODS; 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return output_mode == CONSOLE; 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void VPrintHelper(FILE* stream, const char* format, va_list args) { 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if ((stream == stdout || stream == stderr) && !HasConsole()) { 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It is important to use safe print here in order to avoid 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // overflowing the buffer. We might truncate the output, but this 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // does not crash. 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char buffer[4096]; 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OS::VSNPrintF(buffer, sizeof(buffer), format, args); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OutputDebugStringA(buffer); 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch vfprintf(stream, format, args); 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochFILE* OS::FOpen(const char* path, const char* mode) { 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE* result; 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (fopen_s(&result, path, mode) == 0) { 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return NULL; 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool OS::Remove(const char* path) { 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return (DeleteFileA(path) != 0); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochchar OS::DirectorySeparator() { return '\\'; } 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochbool OS::isDirectorySeparator(const char ch) { 579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return ch == '/' || ch == '\\'; 580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochFILE* OS::OpenTemporaryFile() { 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tmpfile_s tries to use the root dir, don't use it. 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char tempPathBuffer[MAX_PATH]; 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD path_result = 0; 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch path_result = GetTempPathA(MAX_PATH, tempPathBuffer); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (path_result > MAX_PATH || path_result == 0) return NULL; 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UINT name_result = 0; 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char tempNameBuffer[MAX_PATH]; 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_result = GetTempFileNameA(tempPathBuffer, "", 0, tempNameBuffer); 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (name_result == 0) return NULL; 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE* result = FOpen(tempNameBuffer, "w+"); // Same mode as tmpfile uses. 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (result != NULL) { 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Remove(tempNameBuffer); // Delete on close. 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Open log file in binary mode to avoid /n -> /r/n conversion. 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* const OS::LogFileOpenMode = "wb"; 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Print (debug) message to console. 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::Print(const char* format, ...) { 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_list args; 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_start(args, format); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VPrint(format, args); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_end(args); 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::VPrint(const char* format, va_list args) { 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VPrintHelper(stdout, format, args); 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::FPrint(FILE* out, const char* format, ...) { 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_list args; 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_start(args, format); 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VFPrint(out, format, args); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_end(args); 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::VFPrint(FILE* out, const char* format, va_list args) { 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VPrintHelper(out, format, args); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Print error message to console. 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::PrintError(const char* format, ...) { 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_list args; 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_start(args, format); 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VPrintError(format, args); 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_end(args); 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::VPrintError(const char* format, va_list args) { 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VPrintHelper(stderr, format, args); 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::SNPrintF(char* str, int length, const char* format, ...) { 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_list args; 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_start(args, format); 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = VSNPrintF(str, length, format, args); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch va_end(args); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::VSNPrintF(char* str, int length, const char* format, va_list args) { 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int n = _vsnprintf_s(str, length, _TRUNCATE, format, args); 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure to zero-terminate the string if the output was 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // truncated or if there was an error. 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (n < 0 || n >= length) { 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (length > 0) 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch str[length - 1] = '\0'; 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return -1; 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return n; 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochchar* OS::StrChr(char* str, int c) { 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return const_cast<char*>(strchr(str, c)); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::StrNCpy(char* dest, int length, const char* src, size_t n) { 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use _TRUNCATE or strncpy_s crashes (by design) if buffer is too small. 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t buffer_size = static_cast<size_t>(length); 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (n + 1 > buffer_size) // count for trailing '\0' 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch n = _TRUNCATE; 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int result = strncpy_s(dest, length, src, n); 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result == 0 || (n == _TRUNCATE && result == STRUNCATE)); 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef _TRUNCATE 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef STRUNCATE 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Get the system's page size used by VirtualAlloc() or the next power 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// of two. The reason for always returning a power of two is that the 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// rounding up in OS::Allocate expects that. 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic size_t GetPageSize() { 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static size_t page_size = 0; 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (page_size == 0) { 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SYSTEM_INFO info; 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetSystemInfo(&info); 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch page_size = base::bits::RoundUpToPowerOfTwo32(info.dwPageSize); 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return page_size; 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The allocation alignment is the guaranteed alignment for 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// VirtualAlloc'ed blocks of memory. 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochsize_t OS::AllocateAlignment() { 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static size_t allocate_alignment = 0; 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (allocate_alignment == 0) { 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SYSTEM_INFO info; 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetSystemInfo(&info); 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocate_alignment = info.dwAllocationGranularity; 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return allocate_alignment; 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic LazyInstance<RandomNumberGenerator>::type 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch platform_random_number_generator = LAZY_INSTANCE_INITIALIZER; 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::Initialize(int64_t random_seed, bool hard_abort, 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* const gc_fake_mmap) { 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (random_seed) { 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch platform_random_number_generator.Pointer()->SetSeed(random_seed); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch g_hard_abort = hard_abort; 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* OS::GetRandomMmapAddr() { 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The address range used to randomize RWX allocations in OS::Allocate 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try not to map pages into the default range that windows loads DLLs 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Use a multiple of 64k to prevent committing unused memory. 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Note: This does not guarantee RWX regions will be within the 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // range kAllocationRandomAddressMin to kAllocationRandomAddressMax 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef V8_HOST_ARCH_64_BIT 736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static const uintptr_t kAllocationRandomAddressMin = 0x0000000080000000; 737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static const uintptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000; 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static const uintptr_t kAllocationRandomAddressMin = 0x04000000; 740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static const uintptr_t kAllocationRandomAddressMax = 0x3FFF0000; 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch uintptr_t address; 743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch platform_random_number_generator.Pointer()->NextBytes(&address, 744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch sizeof(address)); 745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch address <<= kPageSizeBits; 746014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch address += kAllocationRandomAddressMin; 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address &= kAllocationRandomAddressMax; 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return reinterpret_cast<void *>(address); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void* RandomizedVirtualAlloc(size_t size, int action, int protection) { 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPVOID base = NULL; 754014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static BOOL use_aslr = -1; 755014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef V8_HOST_ARCH_32_BIT 756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Don't bother randomizing on 32-bit hosts, because they lack the room and 757014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // don't have viable ASLR anyway. 758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (use_aslr == -1 && !IsWow64Process(GetCurrentProcess(), &use_aslr)) 759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch use_aslr = FALSE; 760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#else 761014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch use_aslr = TRUE; 762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (use_aslr && 765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS)) { 766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // For executable pages try and randomize the allocation address 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) { 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base = VirtualAlloc(OS::GetRandomMmapAddr(), size, action, protection); 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // After three attempts give up and let the OS find an address to use. 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (base == NULL) base = VirtualAlloc(NULL, size, action, protection); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return base; 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* OS::Allocate(const size_t requested, 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t* allocated, 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_executable) { 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // VirtualAlloc rounds allocated size to page size automatically. 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t msize = RoundUp(requested, static_cast<int>(GetPageSize())); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Windows XP SP2 allows Data Excution Prevention (DEP). 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPVOID mbase = RandomizedVirtualAlloc(msize, 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MEM_COMMIT | MEM_RESERVE, 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prot); 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mbase == NULL) return NULL; 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((reinterpret_cast<uintptr_t>(mbase) % OS::AllocateAlignment()) == 0); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *allocated = msize; 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return mbase; 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 80062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid* OS::AllocateGuarded(const size_t requested) { 80162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch return VirtualAlloc(nullptr, requested, MEM_RESERVE, PAGE_NOACCESS); 80262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::Free(void* address, const size_t size) { 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(1240712): VirtualFree has a return value which is ignored here. 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VirtualFree(address, 0, MEM_RELEASE); 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(size); 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochintptr_t OS::CommitPageSize() { 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 4096; 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::ProtectCode(void* address, const size_t size) { 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD old_protect; 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect); 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::Guard(void* address, const size_t size) { 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD oldprotect; 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect); 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 82762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid OS::Unprotect(void* address, const size_t size) { 82862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch LPVOID result = VirtualAlloc(address, size, MEM_COMMIT, PAGE_READWRITE); 82962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch DCHECK_IMPLIES(result != nullptr, GetLastError() == 0); 83062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch} 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 832014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid OS::Sleep(TimeDelta interval) { 833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ::Sleep(static_cast<DWORD>(interval.InMilliseconds())); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::Abort() { 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (g_hard_abort) { 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V8_IMMEDIATE_CRASH(); 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make the MSVCRT do a silent abort. 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch raise(SIGABRT); 843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Make sure function doesn't return. 845014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch abort(); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::DebugBreak() { 850958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#if V8_CC_MSVC 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // To avoid Visual Studio runtime support the following code can be used 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // instead 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // __asm { int 3 } 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __debugbreak(); 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ::DebugBreak(); 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass Win32MemoryMappedFile final : public OS::MemoryMappedFile { 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory, 864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t size) 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : file_(file), 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch file_mapping_(file_mapping), 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch memory_(memory), 868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_(size) {} 869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ~Win32MemoryMappedFile() final; 870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* memory() const final { return memory_; } 871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t size() const final { return size_; } 872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HANDLE const file_; 875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HANDLE const file_mapping_; 876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void* const memory_; 877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t const size_; 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Open a physical file 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (file == INVALID_HANDLE_VALUE) return NULL; 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DWORD size = GetFileSize(file, NULL); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create a file mapping for the physical file 891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HANDLE file_mapping = 892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CreateFileMapping(file, NULL, PAGE_READWRITE, 0, size, NULL); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (file_mapping == NULL) return NULL; 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Map a view of the file into memory 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new Win32MemoryMappedFile(file, file_mapping, memory, size); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// static 902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, 903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t size, void* initial) { 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Open a physical file 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch OPEN_ALWAYS, 0, NULL); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (file == NULL) return NULL; 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create a file mapping for the physical file 910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch HANDLE file_mapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch static_cast<DWORD>(size), NULL); 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (file_mapping == NULL) return NULL; 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Map a view of the file into memory 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (memory) memmove(memory, initial, size); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return new Win32MemoryMappedFile(file, file_mapping, memory, size); 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochWin32MemoryMappedFile::~Win32MemoryMappedFile() { 921014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (memory_) UnmapViewOfFile(memory_); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CloseHandle(file_mapping_); 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CloseHandle(file_); 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The following code loads functions defined in DbhHelp.h and TlHelp32.h 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// dynamically. This is to avoid being depending on dbghelp.dll and 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// kernel32.dll at some point so loading functions defines in TlHelp32.h 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// dynamically might not be necessary any more - for some versions of Windows?). 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Function pointers to functions dynamically loaded from dbghelp.dll. 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DBGHELP_FUNCTION_LIST(V) \ 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymInitialize) \ 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymGetOptions) \ 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymSetOptions) \ 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymGetSearchPath) \ 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymLoadModule64) \ 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(StackWalk64) \ 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymGetSymFromAddr64) \ 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymGetLineFromAddr64) \ 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymFunctionTableAccess64) \ 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(SymGetModuleBase64) 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Function pointers to functions dynamically loaded from dbghelp.dll. 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define TLHELP32_FUNCTION_LIST(V) \ 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(CreateToolhelp32Snapshot) \ 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(Module32FirstW) \ 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch V(Module32NextW) 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Define the decoration to use for the type and variable name used for 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// dynamically loaded DLL function.. 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DLL_FUNC_TYPE(name) _##name##_ 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DLL_FUNC_VAR(name) _##name 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Define the type for each dynamically loaded DLL function. The function 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// from the Windows include files are redefined here to have the function 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// definitions to be as close to the ones in the original .h files as possible. 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef IN 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define IN 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef VOID 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define VOID void 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DbgHelp isn't supported on MinGW yet 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef __MINGW32__ 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DbgHelp.h functions. 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess, 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN PSTR UserSearchPath, 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN BOOL fInvadeProcess); 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID); 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions); 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))( 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN HANDLE hProcess, 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OUT PSTR SearchPath, 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN DWORD SearchPathLength); 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))( 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN HANDLE hProcess, 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN HANDLE hFile, 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN PSTR ImageName, 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN PSTR ModuleName, 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN DWORD64 BaseOfDll, 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN DWORD SizeOfDll); 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))( 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD MachineType, 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE hProcess, 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE hThread, 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPSTACKFRAME64 StackFrame, 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PVOID ContextRecord, 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))( 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN HANDLE hProcess, 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN DWORD64 qwAddr, 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OUT PDWORD64 pdwDisplacement, 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OUT PIMAGEHLP_SYMBOL64 Symbol); 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))( 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN HANDLE hProcess, 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IN DWORD64 qwAddr, 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OUT PDWORD pdwDisplacement, 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OUT PIMAGEHLP_LINE64 Line64); 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DbgHelp.h typedefs. Implementation found in dbghelp.dll. 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))( 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE hProcess, 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD64 AddrBase); // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))( 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE hProcess, 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD64 AddrBase); // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// TlHelp32.h functions. 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))( 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD dwFlags, 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD th32ProcessID); 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot, 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPMODULEENTRY32W lpme); 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot, 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LPMODULEENTRY32W lpme); 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef IN 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef VOID 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Declare a variable for each dynamically loaded DLL function. 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL; 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochDBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION) 1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION) 1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DEF_DLL_FUNCTION 1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Load the functions. This function has a lot of "ugly" macros in order to 1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// keep down code duplication. 1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic bool LoadDbgHelpAndTlHelp32() { 1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool dbghelp_loaded = false; 1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (dbghelp_loaded) return true; 1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HMODULE module; 1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load functions from the dbghelp.dll module. 1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch module = LoadLibrary(TEXT("dbghelp.dll")); 1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (module == NULL) { 1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define LOAD_DLL_FUNC(name) \ 1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DLL_FUNC_VAR(name) = \ 1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochDBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC) 1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef LOAD_DLL_FUNC 1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load functions from the kernel32.dll module (the TlHelp32.h function used 1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to be in tlhelp32.dll but are now moved to kernel32.dll). 1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch module = LoadLibrary(TEXT("kernel32.dll")); 1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (module == NULL) { 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define LOAD_DLL_FUNC(name) \ 1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DLL_FUNC_VAR(name) = \ 1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC) 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef LOAD_DLL_FUNC 1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that all functions where loaded. 1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result = 1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) && 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochDBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED) 1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED) 1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DLL_FUNC_LOADED 1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch true; 1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch dbghelp_loaded = result; 1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // NOTE: The modules are never unloaded and will stay around until the 1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // application is closed. 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DBGHELP_FUNCTION_LIST 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef TLHELP32_FUNCTION_LIST 1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DLL_FUNC_VAR 1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef DLL_FUNC_TYPE 1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Load the symbols for generating stack traces. 1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic std::vector<OS::SharedLibraryAddress> LoadSymbols( 1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE process_handle) { 1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static std::vector<OS::SharedLibraryAddress> result; 1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static bool symbols_loaded = false; 1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (symbols_loaded) return result; 1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BOOL ok; 1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initialize the symbol engine. 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ok = _SymInitialize(process_handle, // hProcess 1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NULL, // UserSearchPath 1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch false); // fInvadeProcess 1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ok) return result; 1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD options = _SymGetOptions(); 1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options |= SYMOPT_LOAD_LINES; 1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options |= SYMOPT_FAIL_CRITICAL_ERRORS; 1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch options = _SymSetOptions(options); 1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char buf[OS::kStackWalkMaxNameLen] = {0}; 1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen); 1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!ok) { 1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int err = GetLastError(); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OS::Print("%d\n", err); 1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE snapshot = _CreateToolhelp32Snapshot( 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TH32CS_SNAPMODULE, // dwFlags 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GetCurrentProcessId()); // th32ProcessId 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (snapshot == INVALID_HANDLE_VALUE) return result; 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MODULEENTRY32W module_entry; 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch module_entry.dwSize = sizeof(module_entry); // Set the size of the structure. 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BOOL cont = _Module32FirstW(snapshot, &module_entry); 1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch while (cont) { 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD64 base; 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // NOTE the SymLoadModule64 function has the peculiarity of accepting a 1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // both unicode and ASCII strings even though the parameter is PSTR. 1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch base = _SymLoadModule64( 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch process_handle, // hProcess 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0, // hFile 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<PSTR>(module_entry.szExePath), // ImageName 1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<PSTR>(module_entry.szModule), // ModuleName 1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reinterpret_cast<DWORD64>(module_entry.modBaseAddr), // BaseOfDll 1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch module_entry.modBaseSize); // SizeOfDll 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (base == 0) { 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int err = GetLastError(); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (err != ERROR_MOD_NOT_FOUND && 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch err != ERROR_INVALID_HANDLE) { 1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result.clear(); 1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int lib_name_length = WideCharToMultiByte( 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CP_UTF8, 0, module_entry.szExePath, -1, NULL, 0, NULL, NULL); 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::string lib_name(lib_name_length, 0); 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WideCharToMultiByte(CP_UTF8, 0, module_entry.szExePath, -1, &lib_name[0], 1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch lib_name_length, NULL, NULL); 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result.push_back(OS::SharedLibraryAddress( 1156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch lib_name, reinterpret_cast<uintptr_t>(module_entry.modBaseAddr), 1157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<uintptr_t>(module_entry.modBaseAddr + 1158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch module_entry.modBaseSize))); 1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cont = _Module32NextW(snapshot, &module_entry); 1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CloseHandle(snapshot); 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch symbols_loaded = true; 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return result; 1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { 1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // SharedLibraryEvents are logged when loading symbol information. 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only the shared libraries loaded at the time of the call to 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // GetSharedLibraryAddresses are logged. DLLs loaded after 1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // initialization are not accounted for. 1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!LoadDbgHelpAndTlHelp32()) return std::vector<OS::SharedLibraryAddress>(); 1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE process_handle = GetCurrentProcess(); 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return LoadSymbols(process_handle); 1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::SignalCodeMovingGC() { 1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else // __MINGW32__ 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { 1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return std::vector<OS::SharedLibraryAddress>(); 1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid OS::SignalCodeMovingGC() { } 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // __MINGW32__ 1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint OS::ActivationFrameAlignment() { 1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef _WIN64 1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 16; // Windows 64-bit ABI requires the stack to be 16-byte aligned. 1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#elif defined(__MINGW32__) 1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // With gcc 4.4 the tree vectorization optimizer can generate code 1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // that requires 16 byte alignment such as movdqa on x86. 1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 16; 1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#else 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 8; // Floating-point math runs faster with 8-byte alignment. 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory(size_t size) 1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : address_(ReserveRegion(size)), size_(size) { } 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : address_(NULL), size_(0) { 1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK((alignment % OS::AllocateAlignment()) == 0); 1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_t request_size = RoundUp(size + alignment, 1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch void* address = ReserveRegion(request_size); 1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (address == NULL) return; 1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch uint8_t* base = RoundUp(static_cast<uint8_t*>(address), alignment); 1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Try reducing the size by freeing and then reallocating a specific area. 1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result = ReleaseRegion(address, request_size); 1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result); 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS); 1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (address != NULL) { 1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch request_size = size; 1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(base == static_cast<uint8_t*>(address)); 1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Resizing failed, just go with a bigger area. 1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address = ReserveRegion(request_size); 1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (address == NULL) return; 1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address_ = address; 1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_ = request_size; 1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochVirtualMemory::~VirtualMemory() { 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsReserved()) { 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool result = ReleaseRegion(address(), size()); 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result); 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::IsReserved() { 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return address_ != NULL; 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid VirtualMemory::Reset() { 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address_ = NULL; 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch size_ = 0; 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return CommitRegion(address, size, is_executable); 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsReserved()); 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return UncommitRegion(address, size); 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::Guard(void* address) { 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NULL == VirtualAlloc(address, 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OS::CommitPageSize(), 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MEM_COMMIT, 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PAGE_NOACCESS)) { 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS); 1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) { 1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) { 1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return VirtualFree(base, size, MEM_DECOMMIT) != 0; 1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1299f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochbool VirtualMemory::ReleasePartialRegion(void* base, size_t size, 1300f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch void* free_start, size_t free_size) { 1301f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch return VirtualFree(free_start, free_size, MEM_DECOMMIT) != 0; 1302f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch} 1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return VirtualFree(base, 0, MEM_RELEASE) != 0; 1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool VirtualMemory::HasLazyCommits() { 1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(alph): implement for the platform. 1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return false; 1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ---------------------------------------------------------------------------- 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Win32 thread support. 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Definition of invalid thread handle and id. 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const HANDLE kNoThread = INVALID_HANDLE_VALUE; 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Entry point for threads. The supplied argument is a pointer to the thread 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// object. The entry function dispatches to the run method in the thread 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// object. It is important that this function has __stdcall calling 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// convention. 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic unsigned int __stdcall ThreadEntry(void* arg) { 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Thread* thread = reinterpret_cast<Thread*>(arg); 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch thread->NotifyStartedAndRun(); 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return 0; 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Thread::PlatformData { 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit PlatformData(HANDLE thread) : thread_(thread) {} 1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HANDLE thread_; 1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unsigned thread_id_; 1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Initialize a Win32 thread object. The thread has an invalid thread 1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// handle until it is started. 1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochThread::Thread(const Options& options) 1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : stack_size_(options.stack_size()), 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch start_semaphore_(NULL) { 1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data_ = new PlatformData(kNoThread); 1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch set_name(options.name()); 1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Thread::set_name(const char* name) { 1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OS::StrNCpy(name_, sizeof(name_), name, strlen(name)); 1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name_[sizeof(name_) - 1] = '\0'; 1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Close our own handle for the thread. 1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochThread::~Thread() { 1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (data_->thread_ != kNoThread) CloseHandle(data_->thread_); 1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete data_; 1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Create a new thread. It is important to use _beginthreadex() instead of 1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the Win32 function CreateThread(), because the CreateThread() does not 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// initialize thread specific structures in the C runtime library. 1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Thread::Start() { 1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data_->thread_ = reinterpret_cast<HANDLE>( 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch _beginthreadex(NULL, 1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<unsigned>(stack_size_), 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ThreadEntry, 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch this, 1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 0, 1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &data_->thread_id_)); 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Wait for thread to terminate. 1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Thread::Join() { 1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (data_->thread_id_ != GetCurrentThreadId()) { 1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WaitForSingleObject(data_->thread_, INFINITE); 1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochThread::LocalStorageKey Thread::CreateThreadLocalKey() { 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DWORD result = TlsAlloc(); 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result != TLS_OUT_OF_INDEXES); 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return static_cast<LocalStorageKey>(result); 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BOOL result = TlsFree(static_cast<DWORD>(key)); 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result); 1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid* Thread::GetThreadLocal(LocalStorageKey key) { 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return TlsGetValue(static_cast<DWORD>(key)); 1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BOOL result = TlsSetValue(static_cast<DWORD>(key), value); 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(result); 1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result); 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace base 1412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 1413