📄 platform-win32.cc.svn-base
字号:
static bool initialized = false; static TimeStamp init_time; static DWORD init_ticks; static const int kHundredNanosecondsPerSecond = 10000; static const int kMaxClockElapsedTime = 60*60*24*kHundredNanosecondsPerSecond; // 1 day // If we are uninitialized, we need to resync the clock. bool needs_resync = !initialized; // Get the current time. TimeStamp time_now; GetSystemTimeAsFileTime(&time_now.ft_); DWORD ticks_now = timeGetTime(); // Check if we need to resync due to clock rollover. needs_resync |= ticks_now < init_ticks; // Check if we need to resync due to elapsed time. needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; // Resync the clock if necessary. if (needs_resync) { GetSystemTimeAsFileTime(&init_time.ft_); init_ticks = ticks_now = timeGetTime(); initialized = true; } // Finally, compute the actual time. Why is this so hard. DWORD elapsed = ticks_now - init_ticks; this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000);}// Return the local timezone offset in milliseconds east of UTC. This// takes into account whether daylight saving is in effect at the time.int64_t Time::LocalOffset() { // Initialize timezone information, if needed. TzSet(); // Convert timestamp to date/time components. These are now in UTC // format. NB: Please do not replace the following three calls with one // call to FileTimeToLocalFileTime(), because it does not handle // daylight saving correctly. SYSTEMTIME utc; FileTimeToSystemTime(&ft(), &utc); // Convert to local time, using timezone information. SYSTEMTIME local; SystemTimeToTzSpecificLocalTime(&tzinfo_, &utc, &local); // Convert local time back to a timestamp. This timestamp now // has a bias similar to the local timezone bias in effect // at the time of the original timestamp. Time localtime; SystemTimeToFileTime(&local, &localtime.ft()); // The difference between the new local timestamp and the original // timestamp and is the local timezone offset. return localtime.Diff(this);}// Return whether or not daylight savings time is in effect at this time.bool Time::InDST() { // Initialize timezone information, if needed. TzSet(); // Determine if DST is in effect at the specified time. bool in_dst = false; if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) { // Get the local timezone offset for the timestamp in milliseconds. int64_t offset = LocalOffset(); // Compute the offset for DST. The bias parameters in the timezone info // are specified in minutes. These must be converted to milliseconds. int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute; // If the local time offset equals the timezone bias plus the daylight // bias then DST is in effect. in_dst = offset == dstofs; } return in_dst;}// Return the dalight savings time offset for this time.int64_t Time::DaylightSavingsOffset() { return InDST() ? 60 * kMsPerMinute : 0;}// Returns a string identifying the current timezone for the// timestamp taking into account daylight saving.char* Time::LocalTimezone() { // Return the standard or DST time zone name based on whether daylight // saving is in effect at the given time. return InDST() ? dst_tz_name_ : std_tz_name_;}void OS::Setup() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it // to an unsigned. Going directly can cause an overflow and the seed to be // set to all ones. The seed will be identical for different instances that // call this setup code within the same millisecond. uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); srand(static_cast<unsigned int>(seed));}// Returns the accumulated user time for thread.int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { FILETIME dummy; uint64_t usertime; // Get the amount of time that the thread has executed in user mode. if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy, reinterpret_cast<FILETIME*>(&usertime))) return -1; // Adjust the resolution to micro-seconds. usertime /= 10; // Convert to seconds and microseconds *secs = static_cast<uint32_t>(usertime / 1000000); *usecs = static_cast<uint32_t>(usertime % 1000000); return 0;}// Returns current time as the number of milliseconds since// 00:00:00 UTC, January 1, 1970.double OS::TimeCurrentMillis() { Time t; t.SetToCurrentTime(); return t.ToJSTime();}// Returns the tickcounter based on timeGetTime.int64_t OS::Ticks() { return timeGetTime() * 1000; // Convert to microseconds.}// Returns a string identifying the current timezone taking into// account daylight saving.char* OS::LocalTimezone(double time) { return Time(time).LocalTimezone();}// Returns the local time offset in milliseconds east of UTC without// taking daylight savings time into account.double OS::LocalTimeOffset() { // Use current time, rounded to the millisecond. Time t(TimeCurrentMillis()); // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset());}// Returns the daylight savings offset in milliseconds for the given// time.double OS::DaylightSavingsOffset(double time) { int64_t offset = Time(time).DaylightSavingsOffset(); return static_cast<double>(offset);}// ----------------------------------------------------------------------------// Win32 console output.//// If a Win32 application is linked as a console application it has a normal// standard output and standard error. In this case normal printf works fine// for output. However, if the application is linked as a GUI application,// the process doesn't have a console, and therefore (debugging) output is lost.// This is the case if we are embedded in a windows program (like a browser).// In order to be able to get debug output in this case the the debugging// facility using OutputDebugString. This output goes to the active debugger// for the process (if any). Else the output can be monitored using DBMON.EXE.enum OutputMode { UNKNOWN, // Output method has not yet been determined. CONSOLE, // Output is written to stdout. ODS // Output is written to debug facility.};static OutputMode output_mode = UNKNOWN; // Current output mode.// Determine if the process has a console for output.static bool HasConsole() { // Only check the first time. Eventual race conditions are not a problem, // because all threads will eventually determine the same mode. if (output_mode == UNKNOWN) { // We cannot just check that the standard output is attached to a console // because this would fail if output is redirected to a file. Therefore we // say that a process does not have an output console if either the // standard output handle is invalid or its file type is unknown. if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE && GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN) output_mode = CONSOLE; else output_mode = ODS; } return output_mode == CONSOLE;}static void VPrintHelper(FILE* stream, const char* format, va_list args) { if (HasConsole()) { vfprintf(stream, format, args); } else { // It is important to use safe print here in order to avoid // overflowing the buffer. We might truncate the output, but this // does not crash. EmbeddedVector<char, 4096> buffer; OS::VSNPrintF(buffer, format, args); OutputDebugStringA(buffer.start()); }}FILE* OS::FOpen(const char* path, const char* mode) { FILE* result; if (fopen_s(&result, path, mode) == 0) { return result; } else { return NULL; }}// Print (debug) message to console.void OS::Print(const char* format, ...) { va_list args; va_start(args, format); VPrint(format, args); va_end(args);}void OS::VPrint(const char* format, va_list args) { VPrintHelper(stdout, format, args);}// Print error message to console.void OS::PrintError(const char* format, ...) { va_list args; va_start(args, format); VPrintError(format, args); va_end(args);}void OS::VPrintError(const char* format, va_list args) { VPrintHelper(stderr, format, args);}int OS::SNPrintF(Vector<char> str, const char* format, ...) { va_list args; va_start(args, format); int result = VSNPrintF(str, format, args); va_end(args); return result;}int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) { int n = _vsnprintf_s(str.start(), str.length(), _TRUNCATE, format, args); // Make sure to zero-terminate the string if the output was // truncated or if there was an error. if (n < 0 || n >= str.length()) { str[str.length() - 1] = '\0'; return -1; } else { return n; }}void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { int result = strncpy_s(dest.start(), dest.length(), src, n); USE(result); ASSERT(result == 0);}void OS::WcsCpy(Vector<wchar_t> dest, const wchar_t* src) { int result = wcscpy_s(dest.start(), dest.length(), src); USE(result); ASSERT(result == 0);}char *OS::StrDup(const char* str) { return _strdup(str);}// We keep the lowest and highest addresses mapped as a quick way of// determining that pointers are outside the heap (used mostly in assertions// and verification). The estimate is conservative, ie, not all addresses in// 'allocated' space are actually allocated to our heap. The range is// [lowest, highest), inclusive on the low and and exclusive on the high end.static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);static void* highest_ever_allocated = reinterpret_cast<void*>(0);static void UpdateAllocatedSpaceLimits(void* address, int size) { lowest_ever_allocated = Min(lowest_ever_allocated, address); highest_ever_allocated = Max(highest_ever_allocated, reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));}bool OS::IsOutsideAllocatedSpace(void* pointer) { if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated) return true; // Ask the Windows API if (IsBadWritePtr(pointer, 1)) return true; return false;}// Get the system's page size used by VirtualAlloc() or the next power// of two. The reason for always returning a power of two is that the// rounding up in OS::Allocate expects that.static size_t GetPageSize() { static size_t page_size = 0; if (page_size == 0) { SYSTEM_INFO info; GetSystemInfo(&info); page_size = RoundUpToPowerOf2(info.dwPageSize); } return page_size;}// The allocation alignment is the guaranteed alignment for// VirtualAlloc'ed blocks of memory.size_t OS::AllocateAlignment() { static size_t allocate_alignment = 0; if (allocate_alignment == 0) { SYSTEM_INFO info; GetSystemInfo(&info); allocate_alignment = info.dwAllocationGranularity; } return allocate_alignment;}void* OS::Allocate(const size_t requested, size_t* allocated, bool executable) { // VirtualAlloc rounds allocated size to page size automatically. size_t msize = RoundUp(requested, GetPageSize()); // Windows XP SP2 allows Data Excution Prevention (DEP). int prot = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; LPVOID mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot); if (mbase == NULL) { LOG(StringEvent("OS::Allocate", "VirtualAlloc failed")); return NULL; } ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment())); *allocated = msize; UpdateAllocatedSpaceLimits(mbase, msize); return mbase;}void OS::Free(void* buf, const size_t length) { // TODO(1240712): VirtualFree has a return value which is ignored here. VirtualFree(buf, 0, MEM_RELEASE); USE(length);}void OS::Sleep(int milliseconds) { ::Sleep(milliseconds);}void OS::Abort() { // Redirect to windows specific abort to ensure // collaboration with sandboxing.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -