From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/system.c | 76 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/unix/system.c b/dlls/ntdll/unix/system.c index 7eba7ecdbf9..f87c9b09124 100644 --- a/dlls/ntdll/unix/system.c +++ b/dlls/ntdll/unix/system.c @@ -228,6 +228,7 @@ 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; +static ULONG_PTR system_cpu_mask;
static pthread_mutex_t timezone_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -835,6 +836,7 @@ static BOOL logical_proc_info_add_group( DWORD num_cpus, ULONG_PTR mask ) dataex->Group.GroupInfo[0].ActiveProcessorMask = mask;
logical_proc_info_ex_size += dataex->Size; + system_cpu_mask |= mask; return TRUE; }
@@ -1278,6 +1280,35 @@ static NTSTATUS create_logical_proc_info(void) } #endif
+#ifdef linux + +static double tsc_from_jiffies[MAXIMUM_PROCESSORS]; + +static void init_tsc_frequency(void) +{ + unsigned long clk_tck = sysconf( _SC_CLK_TCK ); + char filename[128]; + unsigned long val; + unsigned int i; + FILE *f; + + for (i = 0; i < MAXIMUM_PROCESSORS; ++i) + { + if (system_cpu_mask && !(system_cpu_mask & ((ULONG_PTR)1 << i))) continue; + snprintf( filename, sizeof(filename), "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", i ); + if (!(f = fopen( filename, "r" ))) break; + if (fscanf( f, "%lu", &val ) == 1) tsc_from_jiffies[i] = 1000.0 * val / clk_tck; + fclose( f ); + } +} +#else + +static void init_tsc_frequency(void) +{ +} + +#endif + /****************************************************************** * init_cpu_info * @@ -1336,6 +1367,7 @@ void init_cpu_info(void) 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; } + init_tsc_frequency(); }
static NTSTATUS create_cpuset_info(SYSTEM_CPU_SET_INFORMATION *info) @@ -2124,6 +2156,47 @@ static void get_performance_info( SYSTEM_PERFORMANCE_INFORMATION *info ) info->TotalCommitLimit = (totalram + totalswap) / page_size; }
+#ifdef linux + +static void get_cpu_idle_cycle_times( ULONG64 *times ) +{ + unsigned int index, host_index, count; + char line[256], name[32]; + unsigned long long idle; + FILE *f; + + memset( times, 0, peb->NumberOfProcessors * sizeof(*times) ); + if (!(f = fopen( "/proc/stat", "r" ))) return; + + /* skip combined cpu statistics line. */ + fgets( line, sizeof(line), f ); + + index = 0; + while (fgets( line, sizeof(line), f ) && index < peb->NumberOfProcessors) + { + count = sscanf(line, "%s %*u %*u %*u %llu", name, &idle); + + if (count < 2 || strncmp( name, "cpu", 3 )) break; + host_index = atoi( name + 3 ); + if (system_cpu_mask && !(system_cpu_mask & ((ULONG_PTR)1 << host_index))) continue; + times[index] = idle * tsc_from_jiffies[host_index]; + ++index; + } + + fclose( f ); +} +#else + +static void get_cpu_idle_cycle_times( ULONG64 *times ) +{ + static int once; + + if (!once++) FIXME( "SystemProcessorIdleCycleTimeInformation stub.\n" ); + memset( times, 0, peb->NumberOfProcessors * sizeof(*times) ); +} + +#endif +
/* calculate the mday of dst change date, so that for instance Sun 5 Oct 2007 * (last Sunday in October of 2007) becomes Sun Oct 28 2007 @@ -3422,8 +3495,7 @@ NTSTATUS WINAPI NtQuerySystemInformationEx( SYSTEM_INFORMATION_CLASS class, ret = STATUS_BUFFER_TOO_SMALL; break; } - FIXME( "SystemProcessorIdleCycleTimeInformation stub.\n" ); - memset( info, 0, len ); + get_cpu_idle_cycle_times( info ); ret = STATUS_SUCCESS; break;