summaryrefslogtreecommitdiff
path: root/src/classlibnative
diff options
context:
space:
mode:
authorTarek Mahmoud Sayed <tarekms@microsoft.com>2018-12-08 12:40:13 -0800
committerGitHub <noreply@github.com>2018-12-08 12:40:13 -0800
commit98e49952213ff29ee78cb9c33dd33927a88905c6 (patch)
tree81eb17c8cdcbf6dfd750c2415398af5a0609aa81 /src/classlibnative
parent2d1a55eefd7bbebe5968b02229da5dfcf6505bf7 (diff)
downloadcoreclr-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.cpp132
-rw-r--r--src/classlibnative/bcltype/system.h12
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*)&timestamp);
+
+ if (::FileTimeToSystemTime((FILETIME*)&timestamp, &(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, &timestamp));
+ }
+}
+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);