Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Use deterministic Process.StartTime for OS X #39434 (#39572)
Browse files Browse the repository at this point in the history
* Use pbi_start for StartTime on OS X fixes #39434

* Add test to ensure StartTime remains stable

* Reduce delay in test based on feedback

- Use the correct Assert.Equal too.

* Ensure StartTime is in Local Time

* Remove unnecessary test and reenable other test for OS X

* Remove unused OS X interop methods

- SystemNative_GetAbsoluteTime
- SystemNative_GetTimebaseInfo

* Remove cmake entries for unused HAVE_MACH_TIMEBASE_INFO

* Address review comment regarding constants
  • Loading branch information
watfordgnf authored and stephentoub committed Aug 6, 2019
1 parent 902dff4 commit b368697
Show file tree
Hide file tree
Showing 8 changed files with 8 additions and 93 deletions.

This file was deleted.

1 change: 0 additions & 1 deletion src/Native/Unix/Common/pal_config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
#cmakedefine01 HAVE_CLOCK_MONOTONIC
#cmakedefine01 HAVE_CLOCK_REALTIME
#cmakedefine01 HAVE_MACH_ABSOLUTE_TIME
#cmakedefine01 HAVE_MACH_TIMEBASE_INFO
#cmakedefine01 HAVE_CURLM_ADDED_ALREADY
#cmakedefine01 HAVE_CURL_HTTP_VERSION_2TLS
#cmakedefine01 HAVE_CURLPIPE_MULTIPLEX
Expand Down
35 changes: 0 additions & 35 deletions src/Native/Unix/System.Native/pal_time.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,41 +93,6 @@ uint64_t SystemNative_GetTimestamp()
#endif
}

int32_t SystemNative_GetAbsoluteTime(uint64_t* timestamp)
{
assert(timestamp);

#if HAVE_MACH_ABSOLUTE_TIME
*timestamp = mach_absolute_time();
return 1;

#else
*timestamp = 0;
return 0;
#endif
}

int32_t SystemNative_GetTimebaseInfo(uint32_t* numer, uint32_t* denom)
{
#if HAVE_MACH_TIMEBASE_INFO
mach_timebase_info_data_t timebase;
kern_return_t ret = mach_timebase_info(&timebase);
assert(ret == KERN_SUCCESS);

if (ret == KERN_SUCCESS)
{
*numer = timebase.numer;
*denom = timebase.denom;
}
else
#endif
{
*numer = 1;
*denom = 1;
}
return 1;
}

#if defined(_ARM_) || defined(_ARM64_)
#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF
#else
Expand Down
4 changes: 0 additions & 4 deletions src/Native/Unix/System.Native/pal_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ DLLEXPORT uint64_t SystemNative_GetTimestampResolution(void);
*/
DLLEXPORT uint64_t SystemNative_GetTimestamp(void);

DLLEXPORT int32_t SystemNative_GetAbsoluteTime(uint64_t* timestamp);

DLLEXPORT int32_t SystemNative_GetTimebaseInfo(uint32_t* numer, uint32_t* denom);

/**
* The main purpose of this function is to compute the overall CPU utilization
* for the CLR thread pool to regulate the number of worker threads.
Expand Down
5 changes: 0 additions & 5 deletions src/Native/Unix/configure.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -444,11 +444,6 @@ check_symbol_exists(
mach/mach_time.h
HAVE_MACH_ABSOLUTE_TIME)

check_symbol_exists(
mach_timebase_info
mach/mach_time.h
HAVE_MACH_TIMEBASE_INFO)

check_function_exists(
futimes
HAVE_FUTIMES)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,6 @@
<Compile Include="$(CommonPath)\System\StringExtensions.cs">
<Link>Common\System\StringExtensions.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Native\Interop.GetAbsoluteTime.cs">
<Link>Common\Unix\System.Native\Interop.GetAbsoluteTime.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' == 'netcoreapp' AND '$(TargetsWindows)' == 'true'">
<Compile Include="$(CommonPath)\Interop\Windows\Shell32\Interop.ShellExecuteExW.cs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ namespace System.Diagnostics
public partial class Process
{
private const int NanosecondsTo100NanosecondsFactor = 100;

private const int MicrosecondsToSecondsFactor = 1_000_000;

/// <summary>Gets the amount of time the process has spent running code inside the operating system core.</summary>
public TimeSpan PrivilegedProcessorTime
Expand All @@ -27,37 +29,16 @@ internal DateTime StartTimeCore
{
get
{
// Get the RUsage data and convert the process start time.
// To calculcate the process start time in OSX we call proc_pid_rusage() and use ri_proc_start_abstime.
//
// ri_proc_start_abstime is absolute time which is the time since some reference point. The reference point
// usually is the system boot time but this is not necessary true in all versions of OSX. For example in Sierra
// Mac OS 10.12 the reference point is not really the boot time. To be always accurate in our calculations
// we don’t assume the reference point to be the boot time and instead we calculate it by calling GetTimebaseInfo
// which is a wrapper for native mach_absolute_time(). That method returns the current time referenced to the needed start point
// Then we can subtract the returned time from DateTime.UtcNow and we’ll get the exact reference point.
//
// The absolute time is measured by the bus cycle of the processor which is measured in nanoseconds multiplied
// by some factor “numer / denom”. In most cases the factor is (1 / 1) but we have to get the factor and use it just
// in case we run on a machine has different factor. To get the factor we call GetTimebaseInfo the wrapper for the
// mach_timebase_info() which give us the factor. Then we multiply the factor by the absolute time and the divide
// the result by 10^9 to convert it from nanoseconds to seconds.

EnsureState(State.HaveNonExitedId);
Interop.libproc.proc_taskallinfo? info = Interop.libproc.GetProcessInfoById(Id);

uint numer, denom;
Interop.Sys.GetTimebaseInfo(out numer, out denom);
Interop.libproc.rusage_info_v3 info = Interop.libproc.proc_pid_rusage(_processId);
ulong absoluteTime;
if (info == null)
throw new Win32Exception(SR.ProcessInformationUnavailable);

if (!Interop.Sys.GetAbsoluteTime(out absoluteTime))
{
throw new Win32Exception(SR.RUsageFailure);
}
DateTime startTime = DateTime.UnixEpoch + TimeSpan.FromSeconds(info.Value.pbsd.pbi_start_tvsec + info.Value.pbsd.pbi_start_tvusec / (double)MicrosecondsToSecondsFactor);

// usually seconds will be negative
double seconds = (((long)info.ri_proc_start_abstime - (long)absoluteTime) * (double)numer / denom) / NanoSecondToSecondFactor;
return DateTime.UtcNow.AddSeconds(seconds).ToLocalTime();
// The return value is expected to be in the local time zone.
return startTime.ToLocalTime();
}
}

Expand Down
1 change: 0 additions & 1 deletion src/System.Diagnostics.Process/tests/ProcessTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,6 @@ public void TestProcessStartTime()
}

[Fact]
[PlatformSpecific(~TestPlatforms.OSX)]
[ActiveIssue(31908, TargetFrameworkMonikers.Uap)]
public void ProcessStartTime_Deterministic_Across_Instances()
{
Expand Down

0 comments on commit b368697

Please sign in to comment.