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);
|
||||
}
|
||||
|
||||
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 const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
|
||||
|
@ -3059,6 +3142,7 @@ START_TEST(info)
|
|||
test_query_regquota();
|
||||
test_query_logicalproc();
|
||||
test_query_logicalprocex();
|
||||
test_query_cpusetinfo();
|
||||
test_query_firmware();
|
||||
test_query_data_alignment();
|
||||
|
||||
|
|
|
@ -1166,6 +1166,98 @@ static NTSTATUS create_logical_proc_info( SYSTEM_LOGICAL_PROCESSOR_INFORMATION *
|
|||
}
|
||||
#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
|
||||
|
||||
static void copy_smbios_string( char **buffer, char *s, size_t len )
|
||||
|
@ -2651,6 +2743,9 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
|
|||
break;
|
||||
}
|
||||
|
||||
case SystemCpuSetInformation:
|
||||
return NtQuerySystemInformationEx(class, NULL, 0, info, size, ret_size);
|
||||
|
||||
case SystemRecommendedSharedDataAlignment:
|
||||
{
|
||||
len = sizeof(DWORD);
|
||||
|
@ -2773,6 +2868,31 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class,
|
|||
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:
|
||||
FIXME( "(0x%08x,%p,%u,%p,%u,%p) stub\n", class, query, query_len, info, size, ret_size );
|
||||
break;
|
||||
|
|
|
@ -6726,6 +6726,47 @@ typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX
|
|||
} DUMMYUNIONNAME;
|
||||
} 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 */
|
||||
typedef DWORD TP_VERSION,*PTP_VERSION;
|
||||
|
||||
|
|
|
@ -1551,6 +1551,7 @@ typedef enum _SYSTEM_INFORMATION_CLASS {
|
|||
SystemFileCacheInformationEx = 81,
|
||||
SystemDynamicTimeZoneInformation = 102,
|
||||
SystemLogicalProcessorInformationEx = 107,
|
||||
SystemCpuSetInformation = 175,
|
||||
SystemHypervisorSharedPageInformation = 197,
|
||||
SystemInformationClassMax
|
||||
} SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS;
|
||||
|
|
Loading…
Reference in New Issue