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 using Microsoft.Win32.SafeHandles; 6 using System.ComponentModel; 7 8 namespace System.Diagnostics 9 { 10 public partial class ProcessThread 11 { 12 /// <summary>Sets the processor that this thread would ideally like to run on.</summary> 13 public int IdealProcessor 14 { 15 set 16 { 17 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION)) 18 { 19 if (Interop.Kernel32.SetThreadIdealProcessor(threadHandle, value) < 0) 20 { 21 throw new Win32Exception(); 22 } 23 } 24 } 25 } 26 27 /// <summary> 28 /// Resets the ideal processor so there is no ideal processor for this thread (e.g. 29 /// any processor is ideal). 30 /// </summary> ResetIdealProcessor()31 public void ResetIdealProcessor() 32 { 33 // MAXIMUM_PROCESSORS == 32 on 32-bit or 64 on 64-bit, and means the thread has no preferred processor 34 int MAXIMUM_PROCESSORS = IntPtr.Size == 4 ? 32 : 64; 35 IdealProcessor = MAXIMUM_PROCESSORS; 36 } 37 38 /// <summary> 39 /// Returns or sets whether this thread would like a priority boost if the user interacts 40 /// with user interface associated with this thread. 41 /// </summary> 42 private bool PriorityBoostEnabledCore 43 { 44 get 45 { 46 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_QUERY_INFORMATION)) 47 { 48 bool disabled; 49 if (!Interop.Kernel32.GetThreadPriorityBoost(threadHandle, out disabled)) 50 { 51 throw new Win32Exception(); 52 } 53 return !disabled; 54 } 55 } 56 set 57 { 58 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION)) 59 { 60 if (!Interop.Kernel32.SetThreadPriorityBoost(threadHandle, !value)) 61 throw new Win32Exception(); 62 } 63 } 64 } 65 66 /// <summary> 67 /// Returns or sets the priority level of the associated thread. The priority level is 68 /// not an absolute level, but instead contributes to the actual thread priority by 69 /// considering the priority class of the process. 70 /// </summary> 71 private ThreadPriorityLevel PriorityLevelCore 72 { 73 get 74 { 75 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_QUERY_INFORMATION)) 76 { 77 int value = Interop.Kernel32.GetThreadPriority(threadHandle); 78 if (value == 0x7fffffff) 79 { 80 throw new Win32Exception(); 81 } 82 return (ThreadPriorityLevel)value; 83 } 84 } 85 set 86 { 87 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION)) 88 { 89 if (!Interop.Kernel32.SetThreadPriority(threadHandle, (int)value)) 90 { 91 throw new Win32Exception(); 92 } 93 } 94 } 95 } 96 97 /// <summary> 98 /// Sets which processors the associated thread is allowed to be scheduled to run on. 99 /// Each processor is represented as a bit: bit 0 is processor one, bit 1 is processor 100 /// two, etc. For example, the value 1 means run on processor one, 2 means run on 101 /// processor two, 3 means run on processor one or two. 102 /// </summary> 103 public IntPtr ProcessorAffinity 104 { 105 set 106 { 107 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_SET_INFORMATION | Interop.Kernel32.ThreadOptions.THREAD_QUERY_INFORMATION)) 108 { 109 if (Interop.Kernel32.SetThreadAffinityMask(threadHandle, value) == IntPtr.Zero) 110 { 111 throw new Win32Exception(); 112 } 113 } 114 } 115 } 116 117 /// <summary> 118 /// Returns the amount of time the thread has spent running code inside the operating 119 /// system core. 120 /// </summary> 121 public TimeSpan PrivilegedProcessorTime 122 { 123 get { return GetThreadTimes().PrivilegedProcessorTime; } 124 } 125 126 /// <summary>Returns the time the associated thread was started.</summary> 127 public DateTime StartTime 128 { 129 get { return GetThreadTimes().StartTime; } 130 } 131 132 /// <summary> 133 /// Returns the amount of time the associated thread has spent utilizing the CPU. 134 /// It is the sum of the System.Diagnostics.ProcessThread.UserProcessorTime and 135 /// System.Diagnostics.ProcessThread.PrivilegedProcessorTime. 136 /// </summary> 137 public TimeSpan TotalProcessorTime 138 { 139 get { return GetThreadTimes().TotalProcessorTime; } 140 } 141 142 /// <summary> 143 /// Returns the amount of time the associated thread has spent running code 144 /// inside the application (not the operating system core). 145 /// </summary> 146 public TimeSpan UserProcessorTime 147 { 148 get { return GetThreadTimes().UserProcessorTime; } 149 } 150 151 // ----------------------------- 152 // ---- PAL layer ends here ---- 153 // ----------------------------- 154 155 /// <summary>Gets timing information for the thread.</summary> GetThreadTimes()156 private ProcessThreadTimes GetThreadTimes() 157 { 158 using (SafeThreadHandle threadHandle = OpenThreadHandle(Interop.Kernel32.ThreadOptions.THREAD_QUERY_INFORMATION)) 159 { 160 var threadTimes = new ProcessThreadTimes(); 161 if (!Interop.Kernel32.GetThreadTimes(threadHandle, 162 out threadTimes._create, out threadTimes._exit, 163 out threadTimes._kernel, out threadTimes._user)) 164 { 165 throw new Win32Exception(); 166 } 167 return threadTimes; 168 } 169 } 170 171 /// <summary>Open a handle to the thread.</summary> OpenThreadHandle(int access)172 private SafeThreadHandle OpenThreadHandle(int access) 173 { 174 EnsureState(State.IsLocal); 175 return ProcessManager.OpenThread((int)_threadInfo._threadId, access); 176 } 177 } 178 } 179