@@ -21,7 +21,9 @@ internal enum Vendor {
2121
2222 internal class CPUID {
2323
24+ private readonly int group ;
2425 private readonly int thread ;
26+ private readonly GroupAffinity affinity ;
2527
2628 private readonly Vendor vendor = Vendor . Unknown ;
2729
@@ -68,83 +70,87 @@ private static uint NextLog2(long x) {
6870 return count ;
6971 }
7072
71- public CPUID ( int thread ) {
73+ public static CPUID Get ( int group , int thread ) {
74+ if ( thread >= 64 )
75+ return null ;
76+
77+ var affinity = GroupAffinity . Single ( ( ushort ) group , thread ) ;
78+
79+ var previousAffinity = ThreadAffinity . Set ( affinity ) ;
80+ if ( previousAffinity == GroupAffinity . Undefined )
81+ return null ;
82+
83+ try {
84+ return new CPUID ( group , thread , affinity ) ;
85+ } finally {
86+ ThreadAffinity . Set ( previousAffinity ) ;
87+ }
88+ }
89+
90+ private CPUID ( int group , int thread , GroupAffinity affinity ) {
91+ this . group = group ;
7292 this . thread = thread ;
93+ this . affinity = affinity ;
7394
7495 uint maxCpuid = 0 ;
7596 uint maxCpuidExt = 0 ;
7697
7798 uint eax , ebx , ecx , edx ;
7899
79- if ( thread >= 64 )
80- throw new ArgumentOutOfRangeException ( "thread" ) ;
81- ulong mask = 1UL << thread ;
82-
83- if ( Opcode . CpuidTx ( CPUID_0 , 0 ,
84- out eax , out ebx , out ecx , out edx , mask ) ) {
85- if ( eax > 0 )
86- maxCpuid = eax ;
87- else
88- return ;
89-
90- StringBuilder vendorBuilder = new StringBuilder ( ) ;
91- AppendRegister ( vendorBuilder , ebx ) ;
92- AppendRegister ( vendorBuilder , edx ) ;
93- AppendRegister ( vendorBuilder , ecx ) ;
94- string cpuVendor = vendorBuilder . ToString ( ) ;
95- switch ( cpuVendor ) {
96- case "GenuineIntel" :
97- vendor = Vendor . Intel ;
98- break ;
99- case "AuthenticAMD" :
100- vendor = Vendor . AMD ;
101- break ;
102- default :
103- vendor = Vendor . Unknown ;
104- break ;
105- }
106- eax = ebx = ecx = edx = 0 ;
107- if ( Opcode . CpuidTx ( CPUID_EXT , 0 ,
108- out eax , out ebx , out ecx , out edx , mask ) ) {
109- if ( eax > CPUID_EXT )
110- maxCpuidExt = eax - CPUID_EXT ;
111- else
112- return ;
113- } else {
114- throw new ArgumentOutOfRangeException ( "thread" ) ;
115- }
116- } else {
117- throw new ArgumentOutOfRangeException ( "thread" ) ;
100+ Opcode . Cpuid ( CPUID_0 , 0 , out eax , out ebx , out ecx , out edx ) ;
101+ if ( eax > 0 )
102+ maxCpuid = eax ;
103+ else
104+ return ;
105+
106+ StringBuilder vendorBuilder = new StringBuilder ( ) ;
107+ AppendRegister ( vendorBuilder , ebx ) ;
108+ AppendRegister ( vendorBuilder , edx ) ;
109+ AppendRegister ( vendorBuilder , ecx ) ;
110+ string cpuVendor = vendorBuilder . ToString ( ) ;
111+ switch ( cpuVendor ) {
112+ case "GenuineIntel" :
113+ vendor = Vendor . Intel ;
114+ break ;
115+ case "AuthenticAMD" :
116+ vendor = Vendor . AMD ;
117+ break ;
118+ default :
119+ vendor = Vendor . Unknown ;
120+ break ;
118121 }
122+ eax = ebx = ecx = edx = 0 ;
123+ Opcode . Cpuid ( CPUID_EXT , 0 , out eax , out ebx , out ecx , out edx ) ;
124+ if ( eax > CPUID_EXT )
125+ maxCpuidExt = eax - CPUID_EXT ;
126+ else
127+ return ;
119128
120129 maxCpuid = Math . Min ( maxCpuid , 1024 ) ;
121- maxCpuidExt = Math . Min ( maxCpuidExt , 1024 ) ;
130+ maxCpuidExt = Math . Min ( maxCpuidExt , 1024 ) ;
122131
123132 cpuidData = new uint [ maxCpuid + 1 , 4 ] ;
124133 for ( uint i = 0 ; i < ( maxCpuid + 1 ) ; i ++ )
125- Opcode . CpuidTx ( CPUID_0 + i , 0 ,
134+ Opcode . Cpuid ( CPUID_0 + i , 0 ,
126135 out cpuidData [ i , 0 ] , out cpuidData [ i , 1 ] ,
127- out cpuidData [ i , 2 ] , out cpuidData [ i , 3 ] , mask ) ;
136+ out cpuidData [ i , 2 ] , out cpuidData [ i , 3 ] ) ;
128137
129138 cpuidExtData = new uint [ maxCpuidExt + 1 , 4 ] ;
130139 for ( uint i = 0 ; i < ( maxCpuidExt + 1 ) ; i ++ )
131- Opcode . CpuidTx ( CPUID_EXT + i , 0 ,
132- out cpuidExtData [ i , 0 ] , out cpuidExtData [ i , 1 ] ,
133- out cpuidExtData [ i , 2 ] , out cpuidExtData [ i , 3 ] , mask ) ;
140+ Opcode . Cpuid ( CPUID_EXT + i , 0 ,
141+ out cpuidExtData [ i , 0 ] , out cpuidExtData [ i , 1 ] ,
142+ out cpuidExtData [ i , 2 ] , out cpuidExtData [ i , 3 ] ) ;
134143
135144 StringBuilder nameBuilder = new StringBuilder ( ) ;
136145 for ( uint i = 2 ; i <= 4 ; i ++ ) {
137- if ( Opcode . CpuidTx ( CPUID_EXT + i , 0 ,
138- out eax , out ebx , out ecx , out edx , mask ) )
139- {
140- AppendRegister ( nameBuilder , eax ) ;
141- AppendRegister ( nameBuilder , ebx ) ;
142- AppendRegister ( nameBuilder , ecx ) ;
143- AppendRegister ( nameBuilder , edx ) ;
144- }
146+ Opcode . Cpuid ( CPUID_EXT + i , 0 , out eax , out ebx , out ecx , out edx ) ;
147+ AppendRegister ( nameBuilder , eax ) ;
148+ AppendRegister ( nameBuilder , ebx ) ;
149+ AppendRegister ( nameBuilder , ecx ) ;
150+ AppendRegister ( nameBuilder , edx ) ;
145151 }
146152 nameBuilder . Replace ( '\0 ' , ' ' ) ;
147- cpuBrandString = nameBuilder . ToString ( ) . Trim ( ) ;
153+ cpuBrandString = nameBuilder . ToString ( ) . Trim ( ) ;
148154 nameBuilder . Replace ( "Dual-Core Processor" , "" ) ;
149155 nameBuilder . Replace ( "Triple-Core Processor" , "" ) ;
150156 nameBuilder . Replace ( "Quad-Core Processor" , "" ) ;
@@ -175,7 +181,7 @@ public CPUID(int thread) {
175181 nameBuilder . Replace ( "RADEON R5, 10 COMPUTE CORES 4C+6G" , "" ) ;
176182 nameBuilder . Replace ( "RADEON R7, 10 COMPUTE CORES 4C+6G" , "" ) ;
177183 nameBuilder . Replace ( "RADEON R7, 12 COMPUTE CORES 4C+8G" , "" ) ;
178- nameBuilder . Replace ( "Radeon R5, 6 Compute Cores 2C+4G" , "" ) ;
184+ nameBuilder . Replace ( "Radeon R5, 6 Compute Cores 2C+4G" , "" ) ;
179185 nameBuilder . Replace ( "Radeon R5, 8 Compute Cores 4C+4G" , "" ) ;
180186 nameBuilder . Replace ( "Radeon R6, 10 Compute Cores 4C+6G" , "" ) ;
181187 nameBuilder . Replace ( "Radeon R7, 10 Compute Cores 4C+6G" , "" ) ;
@@ -191,7 +197,7 @@ public CPUID(int thread) {
191197 name = nameBuilder . ToString ( ) ;
192198 if ( name . Contains ( "@" ) )
193199 name = name . Remove ( name . LastIndexOf ( '@' ) ) ;
194- name = name . Trim ( ) ;
200+ name = name . Trim ( ) ;
195201
196202 this . family = ( ( cpuidData [ 1 , 0 ] & 0x0FF00000 ) >> 20 ) +
197203 ( ( cpuidData [ 1 , 0 ] & 0x0F00 ) >> 8 ) ;
@@ -209,14 +215,14 @@ public CPUID(int thread) {
209215 maxCoreIdPerPackage = ( ( cpuidData [ 4 , 0 ] >> 26 ) & 0x3F ) + 1 ;
210216 else
211217 maxCoreIdPerPackage = 1 ;
212- threadMaskWith =
218+ threadMaskWith =
213219 NextLog2 ( maxCoreAndThreadIdPerPackage / maxCoreIdPerPackage ) ;
214220 coreMaskWith = NextLog2 ( maxCoreIdPerPackage ) ;
215221 break ;
216- case Vendor . AMD :
222+ case Vendor . AMD :
217223 if ( this . family == 0x17 ) {
218224 coreMaskWith = ( cpuidExtData [ 8 , 2 ] >> 12 ) & 0xF ;
219- threadMaskWith =
225+ threadMaskWith =
220226 NextLog2 ( ( ( cpuidExtData [ 0x1E , 1 ] >> 8 ) & 0xFF ) + 1 ) ;
221227 } else {
222228 uint corePerPackage ;
@@ -226,7 +232,7 @@ public CPUID(int thread) {
226232 corePerPackage = 1 ;
227233 coreMaskWith = NextLog2 ( corePerPackage ) ;
228234 threadMaskWith = 0 ;
229- }
235+ }
230236 break ;
231237 default :
232238 threadMaskWith = 0 ;
@@ -235,11 +241,11 @@ public CPUID(int thread) {
235241 }
236242
237243 processorId = ( apicId >> ( int ) ( coreMaskWith + threadMaskWith ) ) ;
238- coreId = ( ( apicId >> ( int ) ( threadMaskWith ) )
244+ coreId = ( ( apicId >> ( int ) ( threadMaskWith ) )
239245 - ( processorId << ( int ) ( coreMaskWith ) ) ) ;
240246 threadId = apicId
241247 - ( processorId << ( int ) ( coreMaskWith + threadMaskWith ) )
242- - ( coreId << ( int ) ( threadMaskWith ) ) ;
248+ - ( coreId << ( int ) ( threadMaskWith ) ) ;
243249 }
244250
245251 public string Name {
@@ -250,10 +256,22 @@ public string BrandString {
250256 get { return cpuBrandString ; }
251257 }
252258
259+ public int Group {
260+ get {
261+ return group ;
262+ }
263+ }
264+
253265 public int Thread {
254266 get { return thread ; }
255267 }
256268
269+ public GroupAffinity Affinity {
270+ get {
271+ return affinity ;
272+ }
273+ }
274+
257275 public Vendor Vendor {
258276 get { return vendor ; }
259277 }
0 commit comments