ntdll: Collect logical processor info at process start.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6aa437de6a
commit
05676e83e9
|
@ -230,6 +230,10 @@ struct smbios_chassis_args
|
|||
#define RSMB 0x52534D42
|
||||
|
||||
SYSTEM_CPU_INFORMATION cpu_info = { 0 };
|
||||
static SYSTEM_LOGICAL_PROCESSOR_INFORMATION *logical_proc_info;
|
||||
static unsigned int logical_proc_info_len, logical_proc_info_alloc_len;
|
||||
static SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *logical_proc_info_ex;
|
||||
static unsigned int logical_proc_info_ex_size, logical_proc_info_ex_alloc_size;
|
||||
|
||||
/*******************************************************************************
|
||||
* Architecture specific feature detection for CPUs
|
||||
|
@ -536,24 +540,34 @@ static void get_cpuinfo( SYSTEM_CPU_INFORMATION *info )
|
|||
|
||||
#endif /* End architecture specific feature detection for CPUs */
|
||||
|
||||
static BOOL grow_logical_proc_buf( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **pdata, DWORD *max_len )
|
||||
static BOOL grow_logical_proc_buf(void)
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION *new_data;
|
||||
unsigned int new_len;
|
||||
|
||||
*max_len *= 2;
|
||||
if (!(new_data = realloc( *pdata, *max_len*sizeof(*new_data) ))) return FALSE;
|
||||
*pdata = new_data;
|
||||
if (logical_proc_info_len < logical_proc_info_alloc_len) return TRUE;
|
||||
|
||||
new_len = max( logical_proc_info_alloc_len * 2, logical_proc_info_len + 1 );
|
||||
if (!(new_data = realloc( logical_proc_info, new_len * sizeof(*new_data) ))) return FALSE;
|
||||
memset( new_data + logical_proc_info_alloc_len, 0,
|
||||
(new_len - logical_proc_info_alloc_len) * sizeof(*new_data) );
|
||||
logical_proc_info = new_data;
|
||||
logical_proc_info_alloc_len = new_len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL grow_logical_proc_ex_buf( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **pdataex, DWORD *max_len )
|
||||
static BOOL grow_logical_proc_ex_buf( unsigned int add_size )
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *new_dataex;
|
||||
DWORD new_len = *max_len * 2;
|
||||
if (!(new_dataex = realloc( *pdataex, new_len ))) return FALSE;
|
||||
memset( (char *)new_dataex + *max_len, 0, new_len - *max_len );
|
||||
*pdataex = new_dataex;
|
||||
*max_len = new_len;
|
||||
DWORD new_len;
|
||||
|
||||
if ( logical_proc_info_ex_size + add_size <= logical_proc_info_ex_alloc_size ) return TRUE;
|
||||
|
||||
new_len = max( logical_proc_info_ex_alloc_size * 2, logical_proc_info_ex_alloc_size + add_size );
|
||||
if (!(new_dataex = realloc( logical_proc_info_ex, new_len ))) return FALSE;
|
||||
memset( (char *)new_dataex + logical_proc_info_ex_alloc_size, 0, new_len - logical_proc_info_ex_alloc_size );
|
||||
logical_proc_info_ex = new_dataex;
|
||||
logical_proc_info_ex_alloc_size = new_len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -580,45 +594,37 @@ static DWORD count_bits( ULONG_PTR mask )
|
|||
* - RelationProcessorPackage: package id ('CPU socket').
|
||||
* - RelationProcessorCore: physical core number.
|
||||
*/
|
||||
static BOOL logical_proc_info_add_by_id( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **pdata,
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **pdataex, DWORD *len,
|
||||
DWORD *pmax_len, LOGICAL_PROCESSOR_RELATIONSHIP rel,
|
||||
DWORD id, ULONG_PTR mask )
|
||||
static BOOL logical_proc_info_add_by_id( LOGICAL_PROCESSOR_RELATIONSHIP rel, DWORD id, ULONG_PTR mask )
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *dataex;
|
||||
unsigned int ofs = 0, i;
|
||||
|
||||
if (pdata)
|
||||
for (i = 0; i < logical_proc_info_len; i++)
|
||||
{
|
||||
for (i = 0; i < *len; i++)
|
||||
if (rel == RelationProcessorPackage && logical_proc_info[i].Relationship == rel
|
||||
&& logical_proc_info[i].u.Reserved[1] == id)
|
||||
{
|
||||
if (rel == RelationProcessorPackage && (*pdata)[i].Relationship == rel && (*pdata)[i].u.Reserved[1] == id)
|
||||
{
|
||||
(*pdata)[i].ProcessorMask |= mask;
|
||||
return TRUE;
|
||||
}
|
||||
else if (rel == RelationProcessorCore && (*pdata)[i].Relationship == rel && (*pdata)[i].u.Reserved[1] == id)
|
||||
return TRUE;
|
||||
logical_proc_info[i].ProcessorMask |= mask;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while (*len == *pmax_len)
|
||||
{
|
||||
if (!grow_logical_proc_buf(pdata, pmax_len)) return FALSE;
|
||||
}
|
||||
|
||||
(*pdata)[i].Relationship = rel;
|
||||
(*pdata)[i].ProcessorMask = mask;
|
||||
if (rel == RelationProcessorCore)
|
||||
(*pdata)[i].u.ProcessorCore.Flags = count_bits(mask) > 1 ? LTP_PC_SMT : 0;
|
||||
(*pdata)[i].u.Reserved[0] = 0;
|
||||
(*pdata)[i].u.Reserved[1] = id;
|
||||
*len = i + 1;
|
||||
return TRUE;
|
||||
else if (rel == RelationProcessorCore && logical_proc_info[i].Relationship == rel
|
||||
&& logical_proc_info[i].u.Reserved[1] == id)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while (ofs < *len)
|
||||
if (!grow_logical_proc_buf()) return FALSE;
|
||||
|
||||
logical_proc_info[i].Relationship = rel;
|
||||
logical_proc_info[i].ProcessorMask = mask;
|
||||
if (rel == RelationProcessorCore)
|
||||
logical_proc_info[i].u.ProcessorCore.Flags = count_bits( mask ) > 1 ? LTP_PC_SMT : 0;
|
||||
logical_proc_info[i].u.Reserved[0] = 0;
|
||||
logical_proc_info[i].u.Reserved[1] = id;
|
||||
logical_proc_info_len = i + 1;
|
||||
|
||||
while (ofs < logical_proc_info_ex_size)
|
||||
{
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)*pdataex) + ofs);
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)logical_proc_info_ex + ofs);
|
||||
if (rel == RelationProcessorPackage && dataex->Relationship == rel && dataex->u.Processor.Reserved[1] == id)
|
||||
{
|
||||
dataex->u.Processor.GroupMask[0].Mask |= mask;
|
||||
|
@ -633,13 +639,9 @@ static BOOL logical_proc_info_add_by_id( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **
|
|||
|
||||
/* TODO: For now, just one group. If more than 64 processors, then we
|
||||
* need another group. */
|
||||
if (!grow_logical_proc_ex_buf( log_proc_ex_size_plus( sizeof(PROCESSOR_RELATIONSHIP) ))) return FALSE;
|
||||
|
||||
while (ofs + log_proc_ex_size_plus( sizeof(PROCESSOR_RELATIONSHIP) ) > *pmax_len)
|
||||
{
|
||||
if (!grow_logical_proc_ex_buf(pdataex, pmax_len)) return FALSE;
|
||||
}
|
||||
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)*pdataex) + ofs);
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)logical_proc_info_ex + ofs);
|
||||
|
||||
dataex->Relationship = rel;
|
||||
dataex->Size = log_proc_ex_size_plus( sizeof(PROCESSOR_RELATIONSHIP) );
|
||||
|
@ -655,52 +657,42 @@ static BOOL logical_proc_info_add_by_id( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **
|
|||
dataex->u.Processor.Reserved[0] = 0;
|
||||
dataex->u.Processor.Reserved[1] = id;
|
||||
|
||||
*len += dataex->Size;
|
||||
logical_proc_info_ex_size += dataex->Size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL logical_proc_info_add_cache( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **pdata,
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **pdataex, DWORD *len,
|
||||
DWORD *pmax_len, ULONG_PTR mask, CACHE_DESCRIPTOR *cache )
|
||||
static BOOL logical_proc_info_add_cache( ULONG_PTR mask, CACHE_DESCRIPTOR *cache )
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *dataex;
|
||||
unsigned int ofs = 0, i;
|
||||
|
||||
if (pdata)
|
||||
for (i = 0; i < logical_proc_info_len; i++)
|
||||
{
|
||||
for (i = 0; i < *len; i++)
|
||||
{
|
||||
if ((*pdata)[i].Relationship==RelationCache && (*pdata)[i].ProcessorMask==mask
|
||||
&& (*pdata)[i].u.Cache.Level==cache->Level && (*pdata)[i].u.Cache.Type==cache->Type)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while (*len == *pmax_len)
|
||||
if (!grow_logical_proc_buf(pdata, pmax_len)) return FALSE;
|
||||
|
||||
(*pdata)[i].Relationship = RelationCache;
|
||||
(*pdata)[i].ProcessorMask = mask;
|
||||
(*pdata)[i].u.Cache = *cache;
|
||||
*len = i + 1;
|
||||
return TRUE;
|
||||
if (logical_proc_info[i].Relationship==RelationCache && logical_proc_info[i].ProcessorMask==mask
|
||||
&& logical_proc_info[i].u.Cache.Level==cache->Level && logical_proc_info[i].u.Cache.Type==cache->Type)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (ofs = 0; ofs < *len; )
|
||||
if (!grow_logical_proc_buf()) return FALSE;
|
||||
|
||||
logical_proc_info[i].Relationship = RelationCache;
|
||||
logical_proc_info[i].ProcessorMask = mask;
|
||||
logical_proc_info[i].u.Cache = *cache;
|
||||
logical_proc_info_len = i + 1;
|
||||
|
||||
for (ofs = 0; ofs < logical_proc_info_ex_size; )
|
||||
{
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)*pdataex) + ofs);
|
||||
if (dataex->Relationship == RelationCache && dataex->u.Cache.GroupMask.Mask == mask &&
|
||||
dataex->u.Cache.Level == cache->Level && dataex->u.Cache.Type == cache->Type)
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)logical_proc_info_ex + ofs);
|
||||
if (dataex->Relationship == RelationCache && dataex->u.Cache.GroupMask.Mask == mask
|
||||
&& dataex->u.Cache.Level == cache->Level && dataex->u.Cache.Type == cache->Type)
|
||||
return TRUE;
|
||||
ofs += dataex->Size;
|
||||
}
|
||||
|
||||
while (ofs + log_proc_ex_size_plus( sizeof(CACHE_RELATIONSHIP) ) > *pmax_len)
|
||||
{
|
||||
if (!grow_logical_proc_ex_buf(pdataex, pmax_len)) return FALSE;
|
||||
}
|
||||
if (!grow_logical_proc_ex_buf( log_proc_ex_size_plus( sizeof(CACHE_RELATIONSHIP) ))) return FALSE;
|
||||
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)*pdataex) + ofs);
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)logical_proc_info_ex + ofs);
|
||||
|
||||
dataex->Relationship = RelationCache;
|
||||
dataex->Size = log_proc_ex_size_plus( sizeof(CACHE_RELATIONSHIP) );
|
||||
|
@ -712,35 +704,25 @@ static BOOL logical_proc_info_add_cache( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **
|
|||
dataex->u.Cache.GroupMask.Mask = mask;
|
||||
dataex->u.Cache.GroupMask.Group = 0;
|
||||
|
||||
*len += dataex->Size;
|
||||
logical_proc_info_ex_size += dataex->Size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL logical_proc_info_add_numa_node( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **pdata,
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **pdataex, DWORD *len,
|
||||
DWORD *pmax_len, ULONG_PTR mask, DWORD node_id )
|
||||
static BOOL logical_proc_info_add_numa_node( ULONG_PTR mask, DWORD node_id )
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *dataex;
|
||||
|
||||
if (pdata)
|
||||
{
|
||||
while (*len == *pmax_len)
|
||||
if (!grow_logical_proc_buf(pdata, pmax_len)) return FALSE;
|
||||
if (!grow_logical_proc_buf()) return FALSE;
|
||||
|
||||
(*pdata)[*len].Relationship = RelationNumaNode;
|
||||
(*pdata)[*len].ProcessorMask = mask;
|
||||
(*pdata)[*len].u.NumaNode.NodeNumber = node_id;
|
||||
(*len)++;
|
||||
return TRUE;
|
||||
}
|
||||
logical_proc_info[logical_proc_info_len].Relationship = RelationNumaNode;
|
||||
logical_proc_info[logical_proc_info_len].ProcessorMask = mask;
|
||||
logical_proc_info[logical_proc_info_len].u.NumaNode.NodeNumber = node_id;
|
||||
++logical_proc_info_len;
|
||||
|
||||
while (*len + log_proc_ex_size_plus( sizeof(NUMA_NODE_RELATIONSHIP) ) > *pmax_len)
|
||||
{
|
||||
if (!grow_logical_proc_ex_buf(pdataex, pmax_len)) return FALSE;
|
||||
}
|
||||
if (!grow_logical_proc_ex_buf( log_proc_ex_size_plus( sizeof(NUMA_NODE_RELATIONSHIP) ))) return FALSE;
|
||||
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)*pdataex) + *len);
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)logical_proc_info_ex + logical_proc_info_ex_size);
|
||||
|
||||
dataex->Relationship = RelationNumaNode;
|
||||
dataex->Size = log_proc_ex_size_plus( sizeof(NUMA_NODE_RELATIONSHIP) );
|
||||
|
@ -748,20 +730,18 @@ static BOOL logical_proc_info_add_numa_node( SYSTEM_LOGICAL_PROCESSOR_INFORMATIO
|
|||
dataex->u.NumaNode.GroupMask.Mask = mask;
|
||||
dataex->u.NumaNode.GroupMask.Group = 0;
|
||||
|
||||
*len += dataex->Size;
|
||||
logical_proc_info_ex_size += dataex->Size;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL logical_proc_info_add_group( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **pdataex,
|
||||
DWORD *len, DWORD *pmax_len, DWORD num_cpus, ULONG_PTR mask )
|
||||
static BOOL logical_proc_info_add_group( DWORD num_cpus, ULONG_PTR mask )
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *dataex;
|
||||
|
||||
while (*len + log_proc_ex_size_plus( sizeof(GROUP_RELATIONSHIP) ) > *pmax_len)
|
||||
if (!grow_logical_proc_ex_buf(pdataex, pmax_len)) return FALSE;
|
||||
if (!grow_logical_proc_ex_buf( log_proc_ex_size_plus( sizeof(GROUP_RELATIONSHIP) ))) return FALSE;
|
||||
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)*pdataex) + *len);
|
||||
dataex = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)(((char *)logical_proc_info_ex) + logical_proc_info_ex_size);
|
||||
|
||||
dataex->Relationship = RelationGroup;
|
||||
dataex->Size = log_proc_ex_size_plus( sizeof(GROUP_RELATIONSHIP) );
|
||||
|
@ -771,7 +751,7 @@ static BOOL logical_proc_info_add_group( SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
|
|||
dataex->u.Group.GroupInfo[0].ActiveProcessorCount = num_cpus;
|
||||
dataex->u.Group.GroupInfo[0].ActiveProcessorMask = mask;
|
||||
|
||||
*len += dataex->Size;
|
||||
logical_proc_info_ex_size += dataex->Size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -838,16 +818,14 @@ static BOOL sysfs_count_list_elements(const char *filename, DWORD *result)
|
|||
}
|
||||
|
||||
/* for 'data', max_len is the array count. for 'dataex', max_len is in bytes */
|
||||
static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **data,
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **dataex,
|
||||
DWORD *max_len, DWORD relation )
|
||||
static NTSTATUS create_logical_proc_info(void)
|
||||
{
|
||||
static const char core_info[] = "/sys/devices/system/cpu/cpu%u/topology/%s";
|
||||
static const char cache_info[] = "/sys/devices/system/cpu/cpu%u/cache/index%u/%s";
|
||||
static const char numa_info[] = "/sys/devices/system/node/node%u/cpumap";
|
||||
|
||||
FILE *fcpu_list, *fnuma_list, *f;
|
||||
DWORD len = 0, beg, end, i, j, r, num_cpus = 0, max_cpus = 0;
|
||||
DWORD beg, end, i, j, r, num_cpus = 0, max_cpus = 0;
|
||||
char op, name[MAX_PATH];
|
||||
ULONG_PTR all_cpus_mask = 0;
|
||||
|
||||
|
@ -879,27 +857,24 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
DWORD phys_core = 0;
|
||||
ULONG_PTR thread_mask = 0;
|
||||
|
||||
if (i > 8*sizeof(ULONG_PTR))
|
||||
if (i > 8 * sizeof(ULONG_PTR))
|
||||
{
|
||||
FIXME("skipping logical processor %d\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (relation == RelationAll || relation == RelationProcessorPackage)
|
||||
sprintf(name, core_info, i, "physical_package_id");
|
||||
f = fopen(name, "r");
|
||||
if (f)
|
||||
{
|
||||
sprintf(name, core_info, i, "physical_package_id");
|
||||
f = fopen(name, "r");
|
||||
if (f)
|
||||
{
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
}
|
||||
else r = 0;
|
||||
if (!logical_proc_info_add_by_id(data, dataex, &len, max_len, RelationProcessorPackage, r, (ULONG_PTR)1 << i))
|
||||
{
|
||||
fclose(fcpu_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
}
|
||||
else r = 0;
|
||||
if (!logical_proc_info_add_by_id( RelationProcessorPackage, r, (ULONG_PTR)1 << i ))
|
||||
{
|
||||
fclose(fcpu_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Sysfs enumerates logical cores (and not physical cores), but Windows enumerates
|
||||
|
@ -912,92 +887,83 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
* on kernel cpu core numbering as opposed to a hardware core ID like provided through
|
||||
* 'core_id', so are suitable as a unique ID.
|
||||
*/
|
||||
if(relation == RelationAll || relation == RelationProcessorCore ||
|
||||
relation == RelationNumaNode || relation == RelationGroup)
|
||||
|
||||
/* Mask of logical threads sharing same physical core in kernel core numbering. */
|
||||
sprintf(name, core_info, i, "thread_siblings");
|
||||
if(!sysfs_parse_bitmap(name, &thread_mask)) thread_mask = 1<<i;
|
||||
|
||||
/* Needed later for NumaNode and Group. */
|
||||
all_cpus_mask |= thread_mask;
|
||||
|
||||
sprintf(name, core_info, i, "thread_siblings_list");
|
||||
f = fopen(name, "r");
|
||||
if (f)
|
||||
{
|
||||
/* Mask of logical threads sharing same physical core in kernel core numbering. */
|
||||
sprintf(name, core_info, i, "thread_siblings");
|
||||
if(!sysfs_parse_bitmap(name, &thread_mask)) thread_mask = 1<<i;
|
||||
fscanf(f, "%d%c", &phys_core, &op);
|
||||
fclose(f);
|
||||
}
|
||||
else phys_core = i;
|
||||
|
||||
/* Needed later for NumaNode and Group. */
|
||||
all_cpus_mask |= thread_mask;
|
||||
|
||||
if (relation == RelationAll || relation == RelationProcessorCore)
|
||||
{
|
||||
sprintf(name, core_info, i, "thread_siblings_list");
|
||||
f = fopen(name, "r");
|
||||
if (f)
|
||||
{
|
||||
fscanf(f, "%d%c", &phys_core, &op);
|
||||
fclose(f);
|
||||
}
|
||||
else phys_core = i;
|
||||
|
||||
if (!logical_proc_info_add_by_id(data, dataex, &len, max_len, RelationProcessorCore, phys_core, thread_mask))
|
||||
{
|
||||
fclose(fcpu_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
if (!logical_proc_info_add_by_id( RelationProcessorCore, phys_core, thread_mask ))
|
||||
{
|
||||
fclose(fcpu_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (relation == RelationAll || relation == RelationCache)
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
for(j = 0; j < 4; j++)
|
||||
CACHE_DESCRIPTOR cache;
|
||||
ULONG_PTR mask = 0;
|
||||
|
||||
sprintf(name, cache_info, i, j, "shared_cpu_map");
|
||||
if(!sysfs_parse_bitmap(name, &mask)) continue;
|
||||
|
||||
sprintf(name, cache_info, i, j, "level");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
cache.Level = r;
|
||||
|
||||
sprintf(name, cache_info, i, j, "ways_of_associativity");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
cache.Associativity = r;
|
||||
|
||||
sprintf(name, cache_info, i, j, "coherency_line_size");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
cache.LineSize = r;
|
||||
|
||||
sprintf(name, cache_info, i, j, "size");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u%c", &r, &op);
|
||||
fclose(f);
|
||||
if(op != 'K')
|
||||
WARN("unknown cache size %u%c\n", r, op);
|
||||
cache.Size = (op=='K' ? r*1024 : r);
|
||||
|
||||
sprintf(name, cache_info, i, j, "type");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%s", name);
|
||||
fclose(f);
|
||||
if (!memcmp(name, "Data", 5))
|
||||
cache.Type = CacheData;
|
||||
else if(!memcmp(name, "Instruction", 11))
|
||||
cache.Type = CacheInstruction;
|
||||
else
|
||||
cache.Type = CacheUnified;
|
||||
|
||||
if (!logical_proc_info_add_cache( mask, &cache ))
|
||||
{
|
||||
CACHE_DESCRIPTOR cache;
|
||||
ULONG_PTR mask = 0;
|
||||
|
||||
sprintf(name, cache_info, i, j, "shared_cpu_map");
|
||||
if(!sysfs_parse_bitmap(name, &mask)) continue;
|
||||
|
||||
sprintf(name, cache_info, i, j, "level");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
cache.Level = r;
|
||||
|
||||
sprintf(name, cache_info, i, j, "ways_of_associativity");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
cache.Associativity = r;
|
||||
|
||||
sprintf(name, cache_info, i, j, "coherency_line_size");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u", &r);
|
||||
fclose(f);
|
||||
cache.LineSize = r;
|
||||
|
||||
sprintf(name, cache_info, i, j, "size");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%u%c", &r, &op);
|
||||
fclose(f);
|
||||
if(op != 'K')
|
||||
WARN("unknown cache size %u%c\n", r, op);
|
||||
cache.Size = (op=='K' ? r*1024 : r);
|
||||
|
||||
sprintf(name, cache_info, i, j, "type");
|
||||
f = fopen(name, "r");
|
||||
if(!f) continue;
|
||||
fscanf(f, "%s", name);
|
||||
fclose(f);
|
||||
if (!memcmp(name, "Data", 5))
|
||||
cache.Type = CacheData;
|
||||
else if(!memcmp(name, "Instruction", 11))
|
||||
cache.Type = CacheInstruction;
|
||||
else
|
||||
cache.Type = CacheUnified;
|
||||
|
||||
if (!logical_proc_info_add_cache(data, dataex, &len, max_len, mask, &cache))
|
||||
{
|
||||
fclose(fcpu_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
fclose(fcpu_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1006,48 +972,39 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
|
||||
num_cpus = count_bits(all_cpus_mask);
|
||||
|
||||
if(relation == RelationAll || relation == RelationNumaNode)
|
||||
fnuma_list = fopen("/sys/devices/system/node/online", "r");
|
||||
if (!fnuma_list)
|
||||
{
|
||||
fnuma_list = fopen("/sys/devices/system/node/online", "r");
|
||||
if (!fnuma_list)
|
||||
if (!logical_proc_info_add_numa_node( all_cpus_mask, 0 ))
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!feof(fnuma_list))
|
||||
{
|
||||
if (!logical_proc_info_add_numa_node(data, dataex, &len, max_len, all_cpus_mask, 0))
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!feof(fnuma_list))
|
||||
if (!fscanf(fnuma_list, "%u%c ", &beg, &op))
|
||||
break;
|
||||
if (op == '-') fscanf(fnuma_list, "%u%c ", &end, &op);
|
||||
else end = beg;
|
||||
|
||||
for (i = beg; i <= end; i++)
|
||||
{
|
||||
if (!fscanf(fnuma_list, "%u%c ", &beg, &op))
|
||||
break;
|
||||
if (op == '-') fscanf(fnuma_list, "%u%c ", &end, &op);
|
||||
else end = beg;
|
||||
ULONG_PTR mask = 0;
|
||||
|
||||
for (i = beg; i <= end; i++)
|
||||
sprintf(name, numa_info, i);
|
||||
if (!sysfs_parse_bitmap( name, &mask )) continue;
|
||||
|
||||
if (!logical_proc_info_add_numa_node( mask, i ))
|
||||
{
|
||||
ULONG_PTR mask = 0;
|
||||
|
||||
sprintf(name, numa_info, i);
|
||||
if (!sysfs_parse_bitmap( name, &mask )) continue;
|
||||
|
||||
if (!logical_proc_info_add_numa_node(data, dataex, &len, max_len, mask, i))
|
||||
{
|
||||
fclose(fnuma_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
fclose(fnuma_list);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
fclose(fnuma_list);
|
||||
}
|
||||
fclose(fnuma_list);
|
||||
}
|
||||
|
||||
if(dataex && (relation == RelationAll || relation == RelationGroup))
|
||||
logical_proc_info_add_group(dataex, &len, max_len, num_cpus, all_cpus_mask);
|
||||
|
||||
if(data)
|
||||
*max_len = len * sizeof(**data);
|
||||
else
|
||||
*max_len = len;
|
||||
logical_proc_info_add_group( num_cpus, all_cpus_mask );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1055,11 +1012,9 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
#elif defined(__APPLE__)
|
||||
|
||||
/* for 'data', max_len is the array count. for 'dataex', max_len is in bytes */
|
||||
static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **data,
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **dataex,
|
||||
DWORD *max_len, DWORD relation)
|
||||
static NTSTATUS create_logical_proc_info(void)
|
||||
{
|
||||
DWORD pkgs_no, cores_no, lcpu_no, lcpu_per_core, cores_per_package, assoc, len = 0;
|
||||
DWORD pkgs_no, cores_no, lcpu_no, lcpu_per_core, cores_per_package, assoc;
|
||||
DWORD cache_ctrs[10] = {0};
|
||||
ULONG_PTR all_cpus_mask = 0;
|
||||
CACHE_DESCRIPTOR cache[10];
|
||||
|
@ -1067,9 +1022,6 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
size_t size;
|
||||
DWORD p,i,j,k;
|
||||
|
||||
if (relation != RelationAll)
|
||||
FIXME("Relationship filtering not implemented: 0x%x\n", relation);
|
||||
|
||||
lcpu_no = peb->NumberOfProcessors;
|
||||
|
||||
size = sizeof(pkgs_no);
|
||||
|
@ -1156,12 +1108,12 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
all_cpus_mask |= mask;
|
||||
|
||||
/* add to package */
|
||||
if(!logical_proc_info_add_by_id(data, dataex, &len, max_len, RelationProcessorPackage, p, mask))
|
||||
if(!logical_proc_info_add_by_id( RelationProcessorPackage, p, mask ))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
/* add new core */
|
||||
phys_core = p * cores_per_package + j;
|
||||
if(!logical_proc_info_add_by_id(data, dataex, &len, max_len, RelationProcessorCore, phys_core, mask))
|
||||
if(!logical_proc_info_add_by_id( RelationProcessorCore, phys_core, mask ))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
for(i = 1; i < 5; ++i)
|
||||
|
@ -1172,7 +1124,7 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
for(k = 0; k < cache_sharing[i]; ++k)
|
||||
mask |= (ULONG_PTR)1 << (j * lcpu_per_core + k);
|
||||
|
||||
if(!logical_proc_info_add_cache(data, dataex, &len, max_len, mask, &cache[i]))
|
||||
if (!logical_proc_info_add_cache( mask, &cache[i] ))
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -1183,24 +1135,17 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
}
|
||||
|
||||
/* OSX doesn't support NUMA, so just make one NUMA node for all CPUs */
|
||||
if(!logical_proc_info_add_numa_node(data, dataex, &len, max_len, all_cpus_mask, 0))
|
||||
if(!logical_proc_info_add_numa_node( all_cpus_mask, 0 ))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if(dataex) logical_proc_info_add_group(dataex, &len, max_len, lcpu_no, all_cpus_mask);
|
||||
|
||||
if(data)
|
||||
*max_len = len * sizeof(**data);
|
||||
else
|
||||
*max_len = len;
|
||||
logical_proc_info_add_group( lcpu_no, all_cpus_mask );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION **data,
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **dataex,
|
||||
DWORD *max_len, DWORD relation )
|
||||
static NTSTATUS create_logical_proc_info(void)
|
||||
{
|
||||
FIXME("stub\n");
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
|
@ -1217,6 +1162,7 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
*/
|
||||
void init_cpu_info(void)
|
||||
{
|
||||
NTSTATUS status;
|
||||
long num;
|
||||
|
||||
#ifdef _SC_NPROCESSORS_ONLN
|
||||
|
@ -1245,34 +1191,42 @@ void init_cpu_info(void)
|
|||
TRACE( "<- CPU arch %d, level %d, rev %d, features 0x%x\n",
|
||||
cpu_info.ProcessorArchitecture, cpu_info.ProcessorLevel, cpu_info.ProcessorRevision,
|
||||
cpu_info.ProcessorFeatureBits );
|
||||
|
||||
if ((status = create_logical_proc_info()))
|
||||
{
|
||||
FIXME( "Failed to get logical processor information, status %#x.\n", status );
|
||||
free( logical_proc_info );
|
||||
logical_proc_info = NULL;
|
||||
logical_proc_info_len = 0;
|
||||
|
||||
free( logical_proc_info_ex );
|
||||
logical_proc_info_ex = NULL;
|
||||
logical_proc_info_ex_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
logical_proc_info = realloc( logical_proc_info, logical_proc_info_len * sizeof(*logical_proc_info) );
|
||||
logical_proc_info_alloc_len = logical_proc_info_len;
|
||||
logical_proc_info_ex = realloc( logical_proc_info_ex, logical_proc_info_ex_size );
|
||||
logical_proc_info_ex_alloc_size = logical_proc_info_ex_size;
|
||||
}
|
||||
}
|
||||
|
||||
static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *proc_info;
|
||||
const SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *proc_info;
|
||||
const DWORD cpu_info_size = logical_proc_info_ex_size;
|
||||
BYTE core_index, cache_index, max_cache_level;
|
||||
unsigned int i, j, count;
|
||||
BYTE *proc_info_buffer;
|
||||
DWORD cpu_info_size;
|
||||
ULONG64 cpu_mask;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!logical_proc_info_ex) return STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
count = peb->NumberOfProcessors;
|
||||
|
||||
cpu_info_size = 3 * sizeof(*proc_info);
|
||||
if (!(proc_info_buffer = malloc(cpu_info_size)))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = create_logical_proc_info(NULL, (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX **)&proc_info_buffer,
|
||||
&cpu_info_size, RelationAll)))
|
||||
{
|
||||
free(proc_info_buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
max_cache_level = 0;
|
||||
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)proc_info_buffer;
|
||||
for (i = 0; (BYTE *)proc_info != proc_info_buffer + cpu_info_size; ++i)
|
||||
proc_info = logical_proc_info_ex;
|
||||
for (i = 0; (char *)proc_info != (char *)logical_proc_info_ex + cpu_info_size; ++i)
|
||||
{
|
||||
if (proc_info->Relationship == RelationCache)
|
||||
{
|
||||
|
@ -1286,7 +1240,7 @@ static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
|
|||
|
||||
core_index = 0;
|
||||
cache_index = 0;
|
||||
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)proc_info_buffer;
|
||||
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)logical_proc_info_ex;
|
||||
for (i = 0; i < count; ++i)
|
||||
{
|
||||
info[i].Size = sizeof(*info);
|
||||
|
@ -1295,7 +1249,7 @@ static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
|
|||
info[i].u.CpuSet.LogicalProcessorIndex = i;
|
||||
}
|
||||
|
||||
for (i = 0; (BYTE *)proc_info != (BYTE *)proc_info_buffer + cpu_info_size; ++i)
|
||||
for (i = 0; (char *)proc_info != (char *)logical_proc_info_ex + cpu_info_size; ++i)
|
||||
{
|
||||
if (proc_info->Relationship == RelationProcessorCore)
|
||||
{
|
||||
|
@ -1331,11 +1285,9 @@ static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
|
|||
if (((ULONG64)1 << j) & cpu_mask)
|
||||
info[j].u.CpuSet.NumaNodeIndex = proc_info->u.NumaNode.NodeNumber;
|
||||
}
|
||||
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((BYTE *)proc_info + proc_info->Size);
|
||||
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)proc_info + proc_info->Size);
|
||||
}
|
||||
|
||||
free(proc_info_buffer);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -3054,28 +3006,18 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
|
|||
|
||||
case SystemLogicalProcessorInformation: /* 73 */
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buf;
|
||||
|
||||
/* Each logical processor may use up to 7 entries in returned table:
|
||||
* core, numa node, package, L1i, L1d, L2, L3 */
|
||||
len = 7 * peb->NumberOfProcessors;
|
||||
buf = malloc( len * sizeof(*buf) );
|
||||
if (!buf)
|
||||
if (!logical_proc_info)
|
||||
{
|
||||
ret = STATUS_NO_MEMORY;
|
||||
ret = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
ret = create_logical_proc_info(&buf, NULL, &len, RelationAll);
|
||||
if (!ret)
|
||||
len = logical_proc_info_len * sizeof(*logical_proc_info);
|
||||
if (size >= len)
|
||||
{
|
||||
if (size >= len)
|
||||
{
|
||||
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
||||
else memcpy( info, buf, len);
|
||||
}
|
||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
||||
else memcpy( info, logical_proc_info, len);
|
||||
}
|
||||
free( buf );
|
||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3233,31 +3175,34 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class,
|
|||
{
|
||||
case SystemLogicalProcessorInformationEx:
|
||||
{
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *buf;
|
||||
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *p;
|
||||
DWORD relation;
|
||||
|
||||
if (!query || query_len < sizeof(DWORD))
|
||||
{
|
||||
ret = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
len = 3 * sizeof(*buf);
|
||||
if (!(buf = malloc( len )))
|
||||
if (!logical_proc_info_ex)
|
||||
{
|
||||
ret = STATUS_NO_MEMORY;
|
||||
ret = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
ret = create_logical_proc_info(NULL, &buf, &len, *(DWORD *)query);
|
||||
if (!ret)
|
||||
|
||||
relation = *(DWORD *)query;
|
||||
len = 0;
|
||||
p = logical_proc_info_ex;
|
||||
while ((char *)p != (char *)logical_proc_info_ex + logical_proc_info_ex_size)
|
||||
{
|
||||
if (size >= len)
|
||||
if (relation == RelationAll || p->Relationship == relation)
|
||||
{
|
||||
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
||||
else memcpy(info, buf, len);
|
||||
if (len + p->Size <= size)
|
||||
memcpy( (char *)info + len, p, p->Size );
|
||||
len += p->Size;
|
||||
}
|
||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||
p = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((char *)p + p->Size);
|
||||
}
|
||||
free( buf );
|
||||
ret = size >= len ? STATUS_SUCCESS : STATUS_INFO_LENGTH_MISMATCH;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue