1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 /*============================================================
6 **
7 **
8 **
9 ** Purpose: Provides some basic access to some environment
10 ** functionality.
11 **
12 **
13 ============================================================*/
14 
15 using System.Diagnostics;
16 using System.Runtime.CompilerServices;
17 using System.Threading;
18 
19 using Internal.Runtime.Augments;
20 
21 namespace System
22 {
23     public enum EnvironmentVariableTarget
24     {
25         Process = 0,
26         User = 1,
27         Machine = 2,
28     }
29 
30     internal static partial class Environment
31     {
32         /*==================================TickCount===================================
33         **Action: Gets the number of ticks since the system was started.
34         **Returns: The number of ticks since the system was started.
35         **Arguments: None
36         **Exceptions: None
37         ==============================================================================*/
38         public static int TickCount
39         {
40             get
41             {
42                 return (int)TickCount64;
43             }
44         }
45 
46         //// Note: The CLR's Watson bucketization code looks at the caller of the FCALL method
47         //// to assign blame for crashes.  Don't mess with this, such as by making it call
48         //// another managed helper method, unless you consult with some CLR Watson experts.
49 
50 
FailFast(String message)51         public static void FailFast(String message)
52         {
53             RuntimeExceptionHelpers.FailFast(message);
54         }
55 
FailFast(String message, Exception exception)56         public static void FailFast(String message, Exception exception)
57         {
58             RuntimeExceptionHelpers.FailFast(message, exception);
59         }
60 
61         // Still needed by shared\System\Diagnostics\Debug.Unix.cs
GetEnvironmentVariable(string variable)62         public static string GetEnvironmentVariable(string variable) => EnvironmentAugments.GetEnvironmentVariable(variable);
63 
64         public static int CurrentManagedThreadId
65         {
66             get
67             {
68                 return ManagedThreadId.Current;
69             }
70         }
71 
72         // The upper bits of t_executionIdCache are the executionId. The lower bits of
73         // the t_executionIdCache are counting down to get it periodically refreshed.
74         // TODO: Consider flushing the executionIdCache on Wait operations or similar
75         // actions that are likely to result in changing the executing core
76         [ThreadStatic]
77         private static int t_executionIdCache;
78 
79         private const int ExecutionIdCacheShift = 16;
80         private const int ExecutionIdCacheCountDownMask = (1 << ExecutionIdCacheShift) - 1;
81         private const int ExecutionIdRefreshRate = 5000;
82 
RefreshExecutionId()83         private static int RefreshExecutionId()
84         {
85             int executionId = ComputeExecutionId();
86 
87             Debug.Assert(ExecutionIdRefreshRate <= ExecutionIdCacheCountDownMask);
88 
89             // Mask with Int32.MaxValue to ensure the execution Id is not negative
90             t_executionIdCache = ((executionId << ExecutionIdCacheShift) & Int32.MaxValue) + ExecutionIdRefreshRate;
91 
92             return executionId;
93         }
94 
95         // Cached processor number used as a hint for which per-core stack to access. It is periodically
96         // refreshed to trail the actual thread core affinity.
97         internal static int CurrentExecutionId
98         {
99             [MethodImpl(MethodImplOptions.AggressiveInlining)]
100             get
101             {
102                 int executionIdCache = t_executionIdCache--;
103                 if ((executionIdCache & ExecutionIdCacheCountDownMask) == 0)
104                     return RefreshExecutionId();
105                 return (executionIdCache >> ExecutionIdCacheShift);
106             }
107         }
108 
109         public static bool HasShutdownStarted
110         {
111             get
112             {
113                 // .NET Core does not have shutdown finalization
114                 return false;
115             }
116         }
117 
118         /*===================================NewLine====================================
119         **Action: A property which returns the appropriate newline string for the given
120         **        platform.
121         **Returns: \r\n on Win32.
122         **Arguments: None.
123         **Exceptions: None.
124         ==============================================================================*/
125         public static String NewLine
126         {
127             get
128             {
129 #if !PLATFORM_UNIX
130                 return "\r\n";
131 #else
132                 return "\n";
133 #endif // !PLATFORM_UNIX
134             }
135         }
136 
137         public static String StackTrace
138         {
139             // Disable inlining to have predictable stack frame that EnvironmentAugments can skip
140             [MethodImpl(MethodImplOptions.NoInlining)]
141             get
142             {
143                 return EnvironmentAugments.StackTrace;
144             }
145         }
146 
147         public static int ProcessorCount
148         {
149             get
150             {
151                 return Runtime.RuntimeImports.RhGetProcessCpuCount();
152             }
153         }
154     }
155 }
156