Aric Stewart : ntdll: Implement SystemProcessorPerformanceInformation for Linux (/ proc filesystems) and Mac OS X.
Alexandre Julliard
julliard at winehq.org
Mon Oct 20 08:01:03 CDT 2008
Module: wine
Branch: master
Commit: a226f6609f6fcec61331cbe4b47c9bc4e5f56d62
URL: http://source.winehq.org/git/wine.git/?a=commit;h=a226f6609f6fcec61331cbe4b47c9bc4e5f56d62
Author: Aric Stewart <aric at codeweavers.com>
Date: Fri Oct 17 15:25:30 2008 -0500
ntdll: Implement SystemProcessorPerformanceInformation for Linux (/proc filesystems) and Mac OS X.
---
dlls/ntdll/nt.c | 120 +++++++++++++++++++++++++++++++++++++++++++++--
dlls/ntdll/tests/info.c | 20 +++++++-
2 files changed, 134 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 3ca1755..a8365dc 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -37,6 +37,12 @@
#include "ntdll_misc.h"
#include "wine/server.h"
+#ifdef __APPLE__
+#include <mach/mach_init.h>
+#include <mach/mach_host.h>
+#include <mach/vm_map.h>
+#endif
+
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
/*
@@ -900,18 +906,122 @@ NTSTATUS WINAPI NtQuerySystemInformation(
break;
case SystemProcessorPerformanceInformation:
{
- SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION sppi;
+ SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL;
+ unsigned int cpus = 0;
+ int out_cpus = Length / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
+
+ if (out_cpus == 0)
+ {
+ len = 0;
+ ret = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+ else
+#ifdef __APPLE__
+ {
+ processor_cpu_load_info_data_t *pinfo;
+ mach_msg_type_number_t info_count;
+
+ if (host_processor_info (mach_host_self (),
+ PROCESSOR_CPU_LOAD_INFO,
+ &cpus,
+ (processor_info_array_t*)&pinfo,
+ &info_count) == 0)
+ {
+ int i;
+ cpus = min(cpus,out_cpus);
+ len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * cpus;
+ sppi = RtlAllocateHeap(GetProcessHeap(), 0,len);
+ for (i = 0; i < cpus; i++)
+ {
+ sppi[i].liIdleTime.QuadPart = pinfo[i].cpu_ticks[CPU_STATE_IDLE];
+ sppi[i].liKernelTime.QuadPart = pinfo[i].cpu_ticks[CPU_STATE_SYSTEM];
+ sppi[i].liUserTime.QuadPart = pinfo[i].cpu_ticks[CPU_STATE_USER];
+ }
+ vm_deallocate (mach_task_self (), (vm_address_t) pinfo, info_count);
+ }
+ }
+#else
+ {
+ FILE *cpuinfo = fopen("/proc/stat","r");
+ if (cpuinfo)
+ {
+ unsigned usr,nice,sys;
+ unsigned long idle;
+ int count;
+ char name[10];
+
+ /* first line is combined usage */
+ count = fscanf(cpuinfo,"%s %u %u %u %lu",name, &usr, &nice,
+ &sys, &idle);
+ /* we set this up in the for older non-smp enabled kernels */
+ if (count == 5 && strcmp(name,"cpu")==0)
+ {
+ sppi = RtlAllocateHeap(GetProcessHeap(), 0,
+ sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
+ sppi->liIdleTime.QuadPart = idle;
+ sppi->liKernelTime.QuadPart = sys;
+ sppi->liUserTime.QuadPart = usr;
+ cpus = 1;
+ len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
+ }
+
+ do
+ {
+ count = fscanf(cpuinfo,"%s %u %u %u %lu",name, &usr,
+ &nice, &sys, &idle);
+ if (count == 5 && strncmp(name,"cpu",3)==0)
+ {
+ out_cpus --;
+ if (name[3]=='0') /* first cpu */
+ {
+ sppi->liIdleTime.QuadPart = idle;
+ sppi->liKernelTime.QuadPart = sys;
+ sppi->liUserTime.QuadPart = usr;
+ }
+ else /* new cpu */
+ {
+ len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * (cpus+1);
+ sppi = RtlReAllocateHeap(GetProcessHeap(), 0, sppi, len);
+ sppi[cpus].liIdleTime.QuadPart = idle;
+ sppi[cpus].liKernelTime.QuadPart = sys;
+ sppi[cpus].liUserTime.QuadPart = usr;
+ cpus++;
+ }
+ }
+ else
+ break;
+ } while (out_cpus > 0);
+ fclose(cpuinfo);
+ }
+ }
+#endif
+
+ if (cpus == 0)
+ {
+ static int i = 1;
+
+ sppi = RtlAllocateHeap(GetProcessHeap(),0,sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
- memset(&sppi, 0 , sizeof(sppi)); /* FIXME */
- len = sizeof(sppi);
+ memset(sppi, 0 , sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION));
+ FIXME("stub info_class SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION\n");
+
+ /* many programs expect these values to change so fake change */
+ len = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
+ sppi->liKernelTime.QuadPart = 1 * i;
+ sppi->liUserTime.QuadPart = 2 * i;
+ sppi->liIdleTime.QuadPart = 3 * i;
+ i++;
+ }
if (Length >= len)
{
if (!SystemInformation) ret = STATUS_ACCESS_VIOLATION;
- else memcpy( SystemInformation, &sppi, len);
+ else memcpy( SystemInformation, sppi, len);
}
else ret = STATUS_INFO_LENGTH_MISMATCH;
- FIXME("info_class SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION\n");
+
+ RtlFreeHeap(GetProcessHeap(),0,sppi);
}
break;
case SystemModuleInformation:
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 74f180e..d93e0bc 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -344,23 +344,41 @@ static void test_query_procperf(void)
ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
/* Try it for 1 processor */
+ sppi->KernelTime.QuadPart = 0xdeaddead;
+ sppi->UserTime.QuadPart = 0xdeaddead;
+ sppi->IdleTime.QuadPart = 0xdeaddead;
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi,
sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) == ReturnLength,
"Inconsistent length %d\n", ReturnLength);
-
+ ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
+ ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
+ ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
+
/* Try it for all processors */
+ sppi->KernelTime.QuadPart = 0xdeaddead;
+ sppi->UserTime.QuadPart = 0xdeaddead;
+ sppi->IdleTime.QuadPart = 0xdeaddead;
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength, &ReturnLength);
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
+ ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
+ ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
+ ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
/* A too large given buffer size */
sppi = HeapReAlloc(GetProcessHeap(), 0, sppi , NeededLength + 2);
+ sppi->KernelTime.QuadPart = 0xdeaddead;
+ sppi->UserTime.QuadPart = 0xdeaddead;
+ sppi->IdleTime.QuadPart = 0xdeaddead;
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, sppi, NeededLength + 2, &ReturnLength);
ok( status == STATUS_SUCCESS || status == STATUS_INFO_LENGTH_MISMATCH /* vista */,
"Expected STATUS_SUCCESS or STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
ok( NeededLength == ReturnLength, "Inconsistent length (%d) <-> (%d)\n", NeededLength, ReturnLength);
+ ok (sppi->KernelTime.QuadPart != 0xdeaddead, "KernelTime unchanged\n");
+ ok (sppi->UserTime.QuadPart != 0xdeaddead, "UserTime unchanged\n");
+ ok (sppi->IdleTime.QuadPart != 0xdeaddead, "IdleTime unchanged\n");
HeapFree( GetProcessHeap(), 0, sppi);
}
More information about the wine-cvs
mailing list