diff options
author | Tarek Mahmoud Sayed <tarekms@microsoft.com> | 2018-12-08 12:40:13 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-08 12:40:13 -0800 |
commit | 98e49952213ff29ee78cb9c33dd33927a88905c6 (patch) | |
tree | 81eb17c8cdcbf6dfd750c2415398af5a0609aa81 /src/classlibnative | |
parent | 2d1a55eefd7bbebe5968b02229da5dfcf6505bf7 (diff) | |
download | coreclr-98e49952213ff29ee78cb9c33dd33927a88905c6.tar.gz coreclr-98e49952213ff29ee78cb9c33dd33927a88905c6.tar.bz2 coreclr-98e49952213ff29ee78cb9c33dd33927a88905c6.zip |
Leap Seconds Support (#21420)
* Leap Seconds Support
* Address Feedback
* More feedback addressing
Diffstat (limited to 'src/classlibnative')
-rw-r--r-- | src/classlibnative/bcltype/system.cpp | 132 | ||||
-rw-r--r-- | src/classlibnative/bcltype/system.h | 12 |
2 files changed, 117 insertions, 27 deletions
diff --git a/src/classlibnative/bcltype/system.cpp b/src/classlibnative/bcltype/system.cpp index d525f87a29..bd1db8f146 100644 --- a/src/classlibnative/bcltype/system.cpp +++ b/src/classlibnative/bcltype/system.cpp @@ -76,7 +76,7 @@ void WINAPI InitializeGetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime) { func = &::GetSystemTimeAsFileTime; } - + g_pfnGetSystemTimeAsFileTime = func; func(lpSystemTimeAsFileTime); } @@ -99,12 +99,90 @@ FCIMPL0(INT64, SystemNative::__GetSystemTimeAsFileTime) FCIMPLEND; +#ifndef FEATURE_PAL + +FCIMPL1(VOID, SystemNative::GetSystemTimeWithLeapSecondsHandling, FullSystemTime *time) +{ + FCALL_CONTRACT; + INT64 timestamp; + + g_pfnGetSystemTimeAsFileTime((FILETIME*)×tamp); + + if (::FileTimeToSystemTime((FILETIME*)×tamp, &(time->systemTime))) + { + // to keep the time precision + time->hundredNanoSecond = timestamp % 10000; // 10000 is the number of 100-nano seconds per Millisecond + } + else + { + ::GetSystemTime(&(time->systemTime)); + time->hundredNanoSecond = 0; + } + + if (time->systemTime.wSecond > 59) + { + // we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation. + // we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds + time->systemTime.wSecond = 59; + time->systemTime.wMilliseconds = 999; + time->hundredNanoSecond = 9999; + } +} +FCIMPLEND; + +FCIMPL2(FC_BOOL_RET, SystemNative::FileTimeToSystemTime, INT64 fileTime, FullSystemTime *time) +{ + FCALL_CONTRACT; + if (::FileTimeToSystemTime((FILETIME*)&fileTime, (LPSYSTEMTIME) time)) + { + // to keep the time precision + time->hundredNanoSecond = fileTime % 10000; // 10000 is the number of 100-nano seconds per Millisecond + if (time->systemTime.wSecond > 59) + { + // we have a leap second, force it to last second in the minute as DateTime doesn't account for leap seconds in its calculation. + // we use the maxvalue from the milliseconds and the 100-nano seconds to avoid reporting two out of order 59 seconds + time->systemTime.wSecond = 59; + time->systemTime.wMilliseconds = 999; + time->hundredNanoSecond = 9999; + } + FC_RETURN_BOOL(TRUE); + } + FC_RETURN_BOOL(FALSE); +} +FCIMPLEND; + +FCIMPL2(FC_BOOL_RET, SystemNative::ValidateSystemTime, SYSTEMTIME *time, CLR_BOOL localTime) +{ + FCALL_CONTRACT; + + if (localTime) + { + SYSTEMTIME st; + FC_RETURN_BOOL(::TzSpecificLocalTimeToSystemTime(NULL, time, &st)); + } + else + { + FILETIME timestamp; + FC_RETURN_BOOL(::SystemTimeToFileTime(time, ×tamp)); + } +} +FCIMPLEND; + +FCIMPL2(FC_BOOL_RET, SystemNative::SystemTimeToFileTime, SYSTEMTIME *time, INT64 *pFileTime) +{ + FCALL_CONTRACT; + + BOOL ret = ::SystemTimeToFileTime(time, (LPFILETIME) pFileTime); + FC_RETURN_BOOL(ret); +} +FCIMPLEND; +#endif // FEATURE_PAL FCIMPL0(UINT32, SystemNative::GetTickCount) { FCALL_CONTRACT; - + return ::GetTickCount(); } FCIMPLEND; @@ -132,7 +210,7 @@ VOID QCALLTYPE SystemNative::Exit(INT32 exitcode) FCIMPL1(VOID,SystemNative::SetExitCode,INT32 exitcode) { FCALL_CONTRACT; - + // The exit code for the process is communicated in one of two ways. If the // entrypoint returns an 'int' we take that. Otherwise we take a latched // process exit code. This can be modified by the app via setting @@ -144,7 +222,7 @@ FCIMPLEND FCIMPL0(INT32, SystemNative::GetExitCode) { FCALL_CONTRACT; - + // Return whatever has been latched so far. This is uninitialized to 0. return GetLatchedExitCode(); } @@ -161,7 +239,7 @@ void QCALLTYPE SystemNative::_GetCommandLine(QCall::StringHandleOnStack retStrin commandLine = WszGetCommandLine(); if (commandLine==NULL) COMPlusThrowOM(); - + retString.Set(commandLine); END_QCALL; @@ -187,10 +265,10 @@ FCIMPL0(Object*, SystemNative::GetCommandLineArgs) COMPlusThrowOM(); _ASSERTE(numArgs > 0); - + strArray = (PTRARRAYREF) AllocateObjectArray(numArgs, g_pStringClass); // Copy each argument into new Strings. - for(unsigned int i=0; i<numArgs; i++) + for(unsigned int i=0; i<numArgs; i++) { STRINGREF str = StringObject::NewString(argv[i]); STRINGREF * destData = ((STRINGREF*)(strArray->GetDataPtr())) + i; @@ -200,7 +278,7 @@ FCIMPL0(Object*, SystemNative::GetCommandLineArgs) HELPER_METHOD_FRAME_END(); - return OBJECTREFToObject(strArray); + return OBJECTREFToObject(strArray); } FCIMPLEND @@ -208,7 +286,7 @@ FCIMPLEND FCIMPL1(ReflectMethodObject*, SystemNative::GetMethodFromStackTrace, ArrayBase* pStackTraceUNSAFE) { FCALL_CONTRACT; - + I1ARRAYREF pArray(static_cast<I1Array *>(pStackTraceUNSAFE)); StackTraceArray stackArray(pArray); @@ -276,7 +354,7 @@ FCIMPL0(FC_BOOL_RET, SystemNative::HasShutdownStarted) { FCALL_CONTRACT; - // Return true if the EE has started to shutdown and is now going to + // Return true if the EE has started to shutdown and is now going to // aggressively finalize objects referred to by static variables OR // if someone is unloading the current AppDomain AND we have started // finalizing objects referred to by static variables. @@ -304,7 +382,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce SO_TOLERANT; }CONTRACTL_END; - struct + struct { STRINGREF refMesgString; EXCEPTIONREF refExceptionForWatsonBucketing; @@ -313,7 +391,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce ZeroMemory(&gc, sizeof(gc)); GCPROTECT_BEGIN(gc); - + gc.refMesgString = refMesgString; gc.refExceptionForWatsonBucketing = refExceptionForWatsonBucketing; gc.refErrorSourceString = refErrorSourceString; @@ -344,12 +422,12 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce WCHAR * errorSourceString = NULL; - if (gc.refErrorSourceString != NULL) + if (gc.refErrorSourceString != NULL) { DWORD cchErrorSource = gc.refErrorSourceString->GetStringLength(); errorSourceString = new (nothrow) WCHAR[cchErrorSource + 1]; - if (errorSourceString != NULL) + if (errorSourceString != NULL) { memcpyNoGCRefs(errorSourceString, gc.refErrorSourceString->GetBuffer(), cchErrorSource * sizeof(WCHAR)); errorSourceString[cchErrorSource] = W('\0'); @@ -372,7 +450,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce pszMessage = g_szFailFastBuffer; } } - + if (cchMessage > 0) memcpyNoGCRefs(pszMessage, gc.refMesgString->GetBuffer(), cchMessage * sizeof(WCHAR)); pszMessage[cchMessage] = W('\0'); @@ -396,7 +474,7 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce Thread *pThread = GetThread(); -#ifndef FEATURE_PAL +#ifndef FEATURE_PAL // If we have the exception object, then try to setup // the watson bucket if it has any details. // On CoreCLR, Watson may not be enabled. Thus, we should @@ -430,18 +508,18 @@ void SystemNative::GenericFailFast(STRINGREF refMesgString, EXCEPTIONREF refExce } // Note: Do not merge this FCALL method with any other FailFast overloads. -// Watson uses the managed FailFast method with one String for crash dump bucketization. +// Watson uses the managed FailFast method with one String for crash dump bucketization. FCIMPL1(VOID, SystemNative::FailFast, StringObject* refMessageUNSAFE) -{ +{ FCALL_CONTRACT; STRINGREF refMessage = (STRINGREF)refMessageUNSAFE; - + HELPER_METHOD_FRAME_BEGIN_1(refMessage); // The HelperMethodFrame knows how to get the return address. UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS(); - + // Call the actual worker to perform failfast GenericFailFast(refMessage, NULL, retaddr, COR_E_FAILFAST, NULL); @@ -450,16 +528,16 @@ FCIMPL1(VOID, SystemNative::FailFast, StringObject* refMessageUNSAFE) FCIMPLEND FCIMPL2(VOID, SystemNative::FailFastWithExitCode, StringObject* refMessageUNSAFE, UINT exitCode) -{ +{ FCALL_CONTRACT; STRINGREF refMessage = (STRINGREF)refMessageUNSAFE; - + HELPER_METHOD_FRAME_BEGIN_1(refMessage); // The HelperMethodFrame knows how to get the return address. UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS(); - + // Call the actual worker to perform failfast GenericFailFast(refMessage, NULL, retaddr, exitCode, NULL); @@ -468,7 +546,7 @@ FCIMPL2(VOID, SystemNative::FailFastWithExitCode, StringObject* refMessageUNSAFE FCIMPLEND FCIMPL2(VOID, SystemNative::FailFastWithException, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE) -{ +{ FCALL_CONTRACT; STRINGREF refMessage = (STRINGREF)refMessageUNSAFE; @@ -478,7 +556,7 @@ FCIMPL2(VOID, SystemNative::FailFastWithException, StringObject* refMessageUNSAF // The HelperMethodFrame knows how to get the return address. UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS(); - + // Call the actual worker to perform failfast GenericFailFast(refMessage, refException, retaddr, COR_E_FAILFAST, NULL); @@ -498,7 +576,7 @@ FCIMPL3(VOID, SystemNative::FailFastWithExceptionAndSource, StringObject* refMes // The HelperMethodFrame knows how to get the return address. UINT_PTR retaddr = HELPER_METHOD_FRAME_GET_RETURN_ADDRESS(); - + // Call the actual worker to perform failfast GenericFailFast(refMessage, refException, retaddr, COR_E_FAILFAST, errorSource); @@ -534,6 +612,6 @@ BOOL QCALLTYPE SystemNative::WinRTSupported() - + diff --git a/src/classlibnative/bcltype/system.h b/src/classlibnative/bcltype/system.h index 9480ee9417..803f1dfca8 100644 --- a/src/classlibnative/bcltype/system.h +++ b/src/classlibnative/bcltype/system.h @@ -15,6 +15,12 @@ #include "fcall.h" #include "qcall.h" +struct FullSystemTime +{ + SYSTEMTIME systemTime; + INT64 hundredNanoSecond; +}; + class SystemNative { friend class DebugStackTrace; @@ -38,6 +44,12 @@ private: public: // Functions on the System.Environment class +#ifndef FEATURE_PAL + static FCDECL1(VOID, GetSystemTimeWithLeapSecondsHandling, FullSystemTime *time); + static FCDECL2(FC_BOOL_RET, ValidateSystemTime, SYSTEMTIME *time, CLR_BOOL localTime); + static FCDECL2(FC_BOOL_RET, FileTimeToSystemTime, INT64 fileTime, FullSystemTime *time); + static FCDECL2(FC_BOOL_RET, SystemTimeToFileTime, SYSTEMTIME *time, INT64 *pFileTime); +#endif // FEATURE_PAL static FCDECL0(INT64, __GetSystemTimeAsFileTime); static FCDECL0(UINT32, GetTickCount); |