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 // Interface between GC and the OS specific functionality 5 // 6 7 #ifndef __GCENV_OS_H__ 8 #define __GCENV_OS_H__ 9 10 // Critical section used by the GC 11 class CLRCriticalSection 12 { 13 CRITICAL_SECTION m_cs; 14 15 public: 16 // Initialize the critical section 17 void Initialize(); 18 19 // Destroy the critical section 20 void Destroy(); 21 22 // Enter the critical section. Blocks until the section can be entered. 23 void Enter(); 24 25 // Leave the critical section 26 void Leave(); 27 }; 28 29 // Flags for the GCToOSInterface::VirtualReserve method 30 struct VirtualReserveFlags 31 { 32 enum 33 { 34 None = 0, 35 WriteWatch = 1, 36 }; 37 }; 38 39 // Affinity of a GC thread 40 struct GCThreadAffinity 41 { 42 static const int None = -1; 43 44 // Processor group index, None if no group is specified 45 int Group; 46 // Processor index, None if no affinity is specified 47 int Processor; 48 }; 49 50 // GC thread function prototype 51 typedef void (*GCThreadFunction)(void* param); 52 53 // Interface that the GC uses to invoke OS specific functionality 54 class GCToOSInterface 55 { 56 public: 57 58 // 59 // Initialization and shutdown of the interface 60 // 61 62 // Initialize the interface implementation 63 // Return: 64 // true if it has succeeded, false if it has failed 65 static bool Initialize(); 66 67 // Shutdown the interface implementation 68 static void Shutdown(); 69 70 // 71 // Virtual memory management 72 // 73 74 // Reserve virtual memory range. 75 // Parameters: 76 // size - size of the virtual memory range 77 // alignment - requested memory alignment 78 // flags - flags to control special settings like write watching 79 // Return: 80 // Starting virtual address of the reserved range 81 static void* VirtualReserve(size_t size, size_t alignment, uint32_t flags); 82 83 // Release virtual memory range previously reserved using VirtualReserve 84 // Parameters: 85 // address - starting virtual address 86 // size - size of the virtual memory range 87 // Return: 88 // true if it has succeeded, false if it has failed 89 static bool VirtualRelease(void *address, size_t size); 90 91 // Commit virtual memory range. It must be part of a range reserved using VirtualReserve. 92 // Parameters: 93 // address - starting virtual address 94 // size - size of the virtual memory range 95 // Return: 96 // true if it has succeeded, false if it has failed 97 static bool VirtualCommit(void *address, size_t size); 98 99 // Decomit virtual memory range. 100 // Parameters: 101 // address - starting virtual address 102 // size - size of the virtual memory range 103 // Return: 104 // true if it has succeeded, false if it has failed 105 static bool VirtualDecommit(void *address, size_t size); 106 107 // Reset virtual memory range. Indicates that data in the memory range specified by address and size is no 108 // longer of interest, but it should not be decommitted. 109 // Parameters: 110 // address - starting virtual address 111 // size - size of the virtual memory range 112 // unlock - true if the memory range should also be unlocked 113 // Return: 114 // true if it has succeeded, false if it has failed 115 static bool VirtualReset(void *address, size_t size, bool unlock); 116 117 // 118 // Write watching 119 // 120 121 // Check if the OS supports write watching 122 static bool SupportsWriteWatch(); 123 124 // Reset the write tracking state for the specified virtual memory range. 125 // Parameters: 126 // address - starting virtual address 127 // size - size of the virtual memory range 128 static void ResetWriteWatch(void *address, size_t size); 129 130 // Retrieve addresses of the pages that are written to in a region of virtual memory 131 // Parameters: 132 // resetState - true indicates to reset the write tracking state 133 // address - starting virtual address 134 // size - size of the virtual memory range 135 // pageAddresses - buffer that receives an array of page addresses in the memory region 136 // pageAddressesCount - on input, size of the lpAddresses array, in array elements 137 // on output, the number of page addresses that are returned in the array. 138 // Return: 139 // true if it has succeeded, false if it has failed 140 static bool GetWriteWatch(bool resetState, void* address, size_t size, void** pageAddresses, uintptr_t* pageAddressesCount); 141 142 // 143 // Thread and process 144 // 145 146 // Create a new thread 147 // Parameters: 148 // function - the function to be executed by the thread 149 // param - parameters of the thread 150 // affinity - processor affinity of the thread 151 // Return: 152 // true if it has succeeded, false if it has failed 153 static bool CreateThread(GCThreadFunction function, void* param, GCThreadAffinity* affinity); 154 155 // Causes the calling thread to sleep for the specified number of milliseconds 156 // Parameters: 157 // sleepMSec - time to sleep before switching to another thread 158 static void Sleep(uint32_t sleepMSec); 159 160 // Causes the calling thread to yield execution to another thread that is ready to run on the current processor. 161 // Parameters: 162 // switchCount - number of times the YieldThread was called in a loop 163 static void YieldThread(uint32_t switchCount); 164 165 // Get the number of the current processor 166 static uint32_t GetCurrentProcessorNumber(); 167 168 // Check if the OS supports getting current processor number 169 static bool CanGetCurrentProcessorNumber(); 170 171 // Set ideal processor for the current thread 172 // Parameters: 173 // processorIndex - index of the processor in the group 174 // affinity - ideal processor affinity for the thread 175 // Return: 176 // true if it has succeeded, false if it has failed 177 static bool SetCurrentThreadIdealAffinity(GCThreadAffinity* affinity); 178 179 // Get numeric id of the current thread if possible on the 180 // current platform. It is indended for logging purposes only. 181 // Return: 182 // Numeric id of the current thread or 0 if the 183 static uint64_t GetCurrentThreadIdForLogging(); 184 185 // Get id of the current process 186 // Return: 187 // Id of the current process 188 static uint32_t GetCurrentProcessId(); 189 190 // 191 // Processor topology 192 // 193 194 // Get number of logical processors 195 static uint32_t GetLogicalCpuCount(); 196 197 // Get size of the largest cache on the processor die 198 // Parameters: 199 // trueSize - true to return true cache size, false to return scaled up size based on 200 // the processor architecture 201 // Return: 202 // Size of the cache 203 static size_t GetLargestOnDieCacheSize(bool trueSize = true); 204 205 // Get number of processors assigned to the current process 206 // Return: 207 // The number of processors 208 static uint32_t GetCurrentProcessCpuCount(); 209 210 // Get affinity mask of the current process 211 // Parameters: 212 // processMask - affinity mask for the specified process 213 // systemMask - affinity mask for the system 214 // Return: 215 // true if it has succeeded, false if it has failed 216 // Remarks: 217 // A process affinity mask is a bit vector in which each bit represents the processors that 218 // a process is allowed to run on. A system affinity mask is a bit vector in which each bit 219 // represents the processors that are configured into a system. 220 // A process affinity mask is a subset of the system affinity mask. A process is only allowed 221 // to run on the processors configured into a system. Therefore, the process affinity mask cannot 222 // specify a 1 bit for a processor when the system affinity mask specifies a 0 bit for that processor. 223 static bool GetCurrentProcessAffinityMask(uintptr_t *processMask, uintptr_t *systemMask); 224 225 // 226 // Global memory info 227 // 228 229 // Return the size of the user-mode portion of the virtual address space of this process. 230 // Return: 231 // non zero if it has succeeded, 0 if it has failed 232 static size_t GetVirtualMemoryLimit(); 233 234 // Get the physical memory that this process can use. 235 // Return: 236 // non zero if it has succeeded, 0 if it has failed 237 // Remarks: 238 // If a process runs with a restricted memory limit, it returns the limit. If there's no limit 239 // specified, it returns amount of actual physical memory. 240 static uint64_t GetPhysicalMemoryLimit(); 241 242 // Get memory status 243 // Parameters: 244 // memory_load - A number between 0 and 100 that specifies the approximate percentage of physical memory 245 // that is in use (0 indicates no memory use and 100 indicates full memory use). 246 // available_physical - The amount of physical memory currently available, in bytes. 247 // available_page_file - The maximum amount of memory the current process can commit, in bytes. 248 // Remarks: 249 // Any parameter can be null. 250 static void GetMemoryStatus(uint32_t* memory_load, uint64_t* available_physical, uint64_t* available_page_file); 251 252 // 253 // Misc 254 // 255 256 // Flush write buffers of processors that are executing threads of the current process 257 static void FlushProcessWriteBuffers(); 258 259 // Break into a debugger 260 static void DebugBreak(); 261 262 // 263 // Time 264 // 265 266 // Get a high precision performance counter 267 // Return: 268 // The counter value 269 static int64_t QueryPerformanceCounter(); 270 271 // Get a frequency of the high precision performance counter 272 // Return: 273 // The counter frequency 274 static int64_t QueryPerformanceFrequency(); 275 276 // Get a time stamp with a low precision 277 // Return: 278 // Time stamp in milliseconds 279 static uint32_t GetLowPrecisionTimeStamp(); 280 }; 281 282 #endif // __GCENV_OS_H__ 283