ntdll: Implement NtQuerySystemInformationEx(SystemCpuSetInformation).
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7ff591d7de
commit
084519a82b
|
@ -1099,6 +1099,89 @@ static void test_query_logicalprocex(void)
|
||||||
HeapFree(GetProcessHeap(), 0, infoex_group);
|
HeapFree(GetProcessHeap(), 0, infoex_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_query_cpusetinfo(void)
|
||||||
|
{
|
||||||
|
SYSTEM_CPU_SET_INFORMATION *info;
|
||||||
|
unsigned int i, cpu_count;
|
||||||
|
ULONG len, expected_len;
|
||||||
|
NTSTATUS status;
|
||||||
|
SYSTEM_INFO si;
|
||||||
|
HANDLE process;
|
||||||
|
|
||||||
|
if (!pNtQuerySystemInformationEx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
GetSystemInfo(&si);
|
||||||
|
cpu_count = si.dwNumberOfProcessors;
|
||||||
|
expected_len = cpu_count * sizeof(*info);
|
||||||
|
|
||||||
|
process = GetCurrentProcess();
|
||||||
|
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
|
||||||
|
if (status == STATUS_INVALID_INFO_CLASS)
|
||||||
|
{
|
||||||
|
win_skip("SystemCpuSetInformation is not supported\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == expected_len, "Got unexpected length %u.\n", len);
|
||||||
|
|
||||||
|
len = 0xdeadbeef;
|
||||||
|
status = pNtQuerySystemInformation(SystemCpuSetInformation, NULL, 0, &len);
|
||||||
|
ok(status == STATUS_INVALID_PARAMETER || status == STATUS_INVALID_INFO_CLASS,
|
||||||
|
"Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == 0xdeadbeef, "Got unexpected len %u.\n", len);
|
||||||
|
|
||||||
|
len = 0xdeadbeef;
|
||||||
|
process = (HANDLE)0xdeadbeef;
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
|
||||||
|
ok(status == STATUS_INVALID_HANDLE, "Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == 0xdeadbeef, "Got unexpected length %u.\n", len);
|
||||||
|
|
||||||
|
len = 0xdeadbeef;
|
||||||
|
process = NULL;
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, 4 * sizeof(process), NULL, 0, &len);
|
||||||
|
ok((status == STATUS_INVALID_PARAMETER && len == 0xdeadbeef)
|
||||||
|
|| (status == STATUS_BUFFER_TOO_SMALL && len == expected_len),
|
||||||
|
"Got unexpected status %#x, length %u.\n", status, len);
|
||||||
|
|
||||||
|
len = 0xdeadbeef;
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, NULL, sizeof(process), NULL, 0, &len);
|
||||||
|
ok(status == STATUS_INVALID_PARAMETER, "Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == 0xdeadbeef, "Got unexpected length %u.\n", len);
|
||||||
|
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL, 0, &len);
|
||||||
|
ok(status == STATUS_BUFFER_TOO_SMALL, "Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == expected_len, "Got unexpected length %u.\n", len);
|
||||||
|
|
||||||
|
len = 0xdeadbeef;
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), NULL,
|
||||||
|
expected_len, &len);
|
||||||
|
ok(status == STATUS_ACCESS_VIOLATION, "Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == 0xdeadbeef, "Got unexpected length %u.\n", len);
|
||||||
|
|
||||||
|
info = malloc(expected_len);
|
||||||
|
len = 0;
|
||||||
|
status = pNtQuerySystemInformationEx(SystemCpuSetInformation, &process, sizeof(process), info, expected_len, &len);
|
||||||
|
ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status);
|
||||||
|
ok(len == expected_len, "Got unexpected length %u.\n", len);
|
||||||
|
|
||||||
|
for (i = 0; i < cpu_count; ++i)
|
||||||
|
{
|
||||||
|
SYSTEM_CPU_SET_INFORMATION *d = &info[i];
|
||||||
|
|
||||||
|
ok(d->Size == sizeof(*d), "Got unexpected size %u, i %u.\n", d->Size, i);
|
||||||
|
ok(d->Type == CpuSetInformation, "Got unexpected type %u, i %u.\n", d->Type, i);
|
||||||
|
ok(d->CpuSet.Id == 0x100 + i, "Got unexpected Id %#x, i %u.\n", d->CpuSet.Id, i);
|
||||||
|
ok(!d->CpuSet.Group, "Got unexpected Group %u, i %u.\n", d->CpuSet.Group, i);
|
||||||
|
ok(d->CpuSet.LogicalProcessorIndex == i, "Got unexpected LogicalProcessorIndex %u, i %u.\n",
|
||||||
|
d->CpuSet.LogicalProcessorIndex, i);
|
||||||
|
ok(!d->CpuSet.AllFlags, "Got unexpected AllFlags %#x, i %u.\n", d->CpuSet.AllFlags, i);
|
||||||
|
}
|
||||||
|
free(info);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_query_firmware(void)
|
static void test_query_firmware(void)
|
||||||
{
|
{
|
||||||
static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
|
static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
|
||||||
|
@ -3059,6 +3142,7 @@ START_TEST(info)
|
||||||
test_query_regquota();
|
test_query_regquota();
|
||||||
test_query_logicalproc();
|
test_query_logicalproc();
|
||||||
test_query_logicalprocex();
|
test_query_logicalprocex();
|
||||||
|
test_query_cpusetinfo();
|
||||||
test_query_firmware();
|
test_query_firmware();
|
||||||
test_query_data_alignment();
|
test_query_data_alignment();
|
||||||
|
|
||||||
|
|
|
@ -1166,6 +1166,98 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info)
|
||||||
|
{
|
||||||
|
SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *proc_info;
|
||||||
|
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;
|
||||||
|
|
||||||
|
count = NtCurrentTeb()->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)
|
||||||
|
{
|
||||||
|
if (proc_info->Relationship == RelationCache)
|
||||||
|
{
|
||||||
|
if (max_cache_level < proc_info->u.Cache.Level)
|
||||||
|
max_cache_level = proc_info->u.Cache.Level;
|
||||||
|
}
|
||||||
|
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)((BYTE *)proc_info + proc_info->Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(info, 0, count * sizeof(*info));
|
||||||
|
|
||||||
|
core_index = 0;
|
||||||
|
cache_index = 0;
|
||||||
|
proc_info = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *)proc_info_buffer;
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
info[i].Size = sizeof(*info);
|
||||||
|
info[i].Type = CpuSetInformation;
|
||||||
|
info[i].u.CpuSet.Id = 0x100 + i;
|
||||||
|
info[i].u.CpuSet.LogicalProcessorIndex = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; (BYTE *)proc_info != (BYTE *)proc_info_buffer + cpu_info_size; ++i)
|
||||||
|
{
|
||||||
|
if (proc_info->Relationship == RelationProcessorCore)
|
||||||
|
{
|
||||||
|
if (proc_info->u.Processor.GroupCount != 1)
|
||||||
|
{
|
||||||
|
FIXME("Unsupported group count %u.\n", proc_info->u.Processor.GroupCount);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cpu_mask = proc_info->u.Processor.GroupMask[0].Mask;
|
||||||
|
for (j = 0; j < count; ++j)
|
||||||
|
if (((ULONG64)1 << j) & cpu_mask)
|
||||||
|
{
|
||||||
|
info[j].u.CpuSet.CoreIndex = core_index;
|
||||||
|
info[j].u.CpuSet.EfficiencyClass = proc_info->u.Processor.EfficiencyClass;
|
||||||
|
}
|
||||||
|
++core_index;
|
||||||
|
}
|
||||||
|
else if (proc_info->Relationship == RelationCache)
|
||||||
|
{
|
||||||
|
if (proc_info->u.Cache.Level == max_cache_level)
|
||||||
|
{
|
||||||
|
cpu_mask = proc_info->u.Cache.GroupMask.Mask;
|
||||||
|
for (j = 0; j < count; ++j)
|
||||||
|
if (((ULONG64)1 << j) & cpu_mask)
|
||||||
|
info[j].u.CpuSet.LastLevelCacheIndex = cache_index;
|
||||||
|
}
|
||||||
|
++cache_index;
|
||||||
|
}
|
||||||
|
else if (proc_info->Relationship == RelationNumaNode)
|
||||||
|
{
|
||||||
|
cpu_mask = proc_info->u.NumaNode.GroupMask.Mask;
|
||||||
|
for (j = 0; j < count; ++j)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(proc_info_buffer);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
|
|
||||||
static void copy_smbios_string( char **buffer, char *s, size_t len )
|
static void copy_smbios_string( char **buffer, char *s, size_t len )
|
||||||
|
@ -2651,6 +2743,9 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SystemCpuSetInformation:
|
||||||
|
return NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size);
|
||||||
|
|
||||||
case SystemRecommendedSharedDataAlignment:
|
case SystemRecommendedSharedDataAlignment:
|
||||||
{
|
{
|
||||||
len = sizeof(DWORD);
|
len = sizeof(DWORD);
|
||||||
|
@ -2773,6 +2868,31 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SystemCpuSetInformation:
|
||||||
|
{
|
||||||
|
unsigned int cpu_count = NtCurrentTeb()->Peb->NumberOfProcessors;
|
||||||
|
PROCESS_BASIC_INFORMATION pbi;
|
||||||
|
HANDLE process;
|
||||||
|
|
||||||
|
if (!query || query_len < sizeof(HANDLE))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
process = *(HANDLE *)query;
|
||||||
|
if (process && (ret = NtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL)))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (size < (len = cpu_count * sizeof(SYSTEM_CPU_SET_INFORMATION)))
|
||||||
|
{
|
||||||
|
ret = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!info)
|
||||||
|
return STATUS_ACCESS_VIOLATION;
|
||||||
|
|
||||||
|
if ((ret = create_cpuset_info(info)))
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
FIXME( "(0x%08x,%p,%u,%p,%u,%p) stub\n", class, query, query_len, info, size, ret_size );
|
FIXME( "(0x%08x,%p,%u,%p,%u,%p) stub\n", class, query, query_len, info, size, ret_size );
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -6726,6 +6726,47 @@ typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
|
||||||
} DUMMYUNIONNAME;
|
} DUMMYUNIONNAME;
|
||||||
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
|
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX;
|
||||||
|
|
||||||
|
typedef enum _CPU_SET_INFORMATION_TYPE
|
||||||
|
{
|
||||||
|
CpuSetInformation,
|
||||||
|
} CPU_SET_INFORMATION_TYPE, *PCPU_SET_INFORMATION_TYPE;
|
||||||
|
|
||||||
|
typedef struct _SYSTEM_CPU_SET_INFORMATION
|
||||||
|
{
|
||||||
|
DWORD Size;
|
||||||
|
CPU_SET_INFORMATION_TYPE Type;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
DWORD Id;
|
||||||
|
WORD Group;
|
||||||
|
BYTE LogicalProcessorIndex;
|
||||||
|
BYTE CoreIndex;
|
||||||
|
BYTE LastLevelCacheIndex;
|
||||||
|
BYTE NumaNodeIndex;
|
||||||
|
BYTE EfficiencyClass;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
BYTE AllFlags;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
BYTE Parked : 1;
|
||||||
|
BYTE Allocated : 1;
|
||||||
|
BYTE AllocatedToTargetProcess : 1;
|
||||||
|
BYTE RealTime : 1;
|
||||||
|
BYTE ReservedFlags : 4;
|
||||||
|
} DUMMYSTRUCTNAME;
|
||||||
|
} DUMMYUNIONNAME2;
|
||||||
|
union {
|
||||||
|
DWORD Reserved;
|
||||||
|
BYTE SchedulingClass;
|
||||||
|
};
|
||||||
|
DWORD64 AllocationTag;
|
||||||
|
} CpuSet;
|
||||||
|
} DUMMYUNIONNAME;
|
||||||
|
} SYSTEM_CPU_SET_INFORMATION, *PSYSTEM_CPU_SET_INFORMATION;
|
||||||
|
|
||||||
/* Threadpool things */
|
/* Threadpool things */
|
||||||
typedef DWORD TP_VERSION,*PTP_VERSION;
|
typedef DWORD TP_VERSION,*PTP_VERSION;
|
||||||
|
|
||||||
|
|
|
@ -1551,6 +1551,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
|
||||||
SystemFileCacheInformationEx = 81,
|
SystemFileCacheInformationEx = 81,
|
||||||
SystemDynamicTimeZoneInformation = 102,
|
SystemDynamicTimeZoneInformation = 102,
|
||||||
SystemLogicalProcessorInformationEx = 107,
|
SystemLogicalProcessorInformationEx = 107,
|
||||||
|
SystemCpuSetInformation = 175,
|
||||||
SystemHypervisorSharedPageInformation = 197,
|
SystemHypervisorSharedPageInformation = 197,
|
||||||
SystemInformationClassMax
|
SystemInformationClassMax
|
||||||
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
|
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
|
||||||
|
|
Loading…
Reference in New Issue