2 * cpu_cygwin.c - module to get cpu usage, for Cygwin
4 * Copyright (c) 2001 Seiichi SATO <ssato@sh.rim.or.jp>
6 * licensed under the GPL
19 #include <w32api/windows.h>
20 #include <w32api/windef.h>
21 #include <w32api/winreg.h>
22 #include <w32api/winbase.h>
24 #define WIN32_9x 1 /* 95, 98, Me */
25 #define WIN32_NT 2 /* NT, 2000, XP */
28 #define LONGINT2DOUBLE(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart))
30 * The following both data structures aren't defined anywhere in the Microsoft
31 * header files. Taken from DNA's libraly licensed under GPL.
32 * (http://estu.nit.ac.jp/~e982457/freesoft/freesoft.html)
34 typedef struct _SYSTEM_BASIC_INFORMATION
{ /* Info Class 0 */
39 BYTE bKeNumberProcessors
;
42 } SYSTEM_BASIC_INFORMATION
;
44 typedef struct _SYSTEM_PERFORMANCE_INFORMATION
{ /* Info Class 2 */
45 LARGE_INTEGER IdleTime
;
47 } SYSTEM_PERFORMANCE_INFORMATION
;
49 typedef struct _SYSTEM_TIME_INFORMATION
{ /* Info Class 3 */
50 LARGE_INTEGER liKeBootTime
;
51 LARGE_INTEGER liKeSystemTime
;
52 LARGE_INTEGER liExpTimeZoneBias
;
53 ULONG uCurrentTimeZoneId
;
55 } SYSTEM_TIME_INFORMATION
;
57 #define SystemBasicInformation 0
58 #define SystemPerformanceInformation 2
59 #define SystemTimeInformation 3
60 /* end of NT, 2000, XP */
62 static int platform
= 0;
67 OSVERSIONINFO os_ver_info
;
70 os_ver_info
.dwOSVersionInfoSize
= sizeof(os_ver_info
);
71 GetVersionEx(&os_ver_info
);
72 platform
= os_ver_info
.dwPlatformId
;
74 if ((platform
!= WIN32_9x
) && (platform
!= WIN32_NT
)) {
75 fprintf(stderr
, "%s: unknown platform\n", PACKAGE
);
81 * cpu_get_usage_9x(): get cpu usage in percent via registry
84 * 1. query 'PerfStats.StartStat.KERNEL.CPUUsage' to start monitoring
85 * 2. get usage from 'PerfStats.StatData.KERNEL.CPUUsage'
86 * 3. query 'PerfStats.StopStat.KERNEL.CPUUsage' to stop monitoring
88 * If cpu usage is 100% evry time, please reboot.;(
91 cpu_get_usage_9x(cpu_options
*opts
)
95 HKEY hkeys
; /* for monitoring (start, stop) */
96 HKEY hkeyr
; /* for reading usage */
98 DWORD dwsize
= sizeof(DWORD
);
100 if (RegOpenKeyEx(HKEY_DYN_DATA
, "PerfStats\\StatData",
101 0, KEY_READ
, &hkeyr
) != ERROR_SUCCESS
) {
102 fprintf(stderr
, "%s: could not open registry 'PerfStats\\StatData'\n", PACKAGE
);
106 /* start monitoring */
107 RegOpenKeyEx(HKEY_DYN_DATA
, "PerfStats\\StartStat", 0, KEY_READ
, &hkeys
);
108 RegQueryValueEx(hkeys
, "KERNEL\\CPUUsage", 0, NULL
, (LPBYTE
)&dummy
,
113 RegQueryValueEx(hkeyr
, "KERNEL\\CPUUsage", 0, NULL
, (LPBYTE
)&usage
,
117 /* stop monitoring */
118 RegOpenKeyEx(HKEY_DYN_DATA
, "PerfStats\\StopStat", 0, KEY_READ
, &hkeys
);
119 RegQueryValueEx(hkeys
, "KERNEL\\CPUUsage", 0, NULL
, (LPBYTE
)&dummy
,
130 * 1. Load NTDLL.DLL (should use dlopen?)
131 * 2. Get addresses of NtQuerySystemInformation (should use dlsym?)
132 * 3. Get system time and idle time
133 * 4. Calculate cpu usage
134 * 5. Unload NTDLL.DLL (should use dlclose?)
136 * I do not test this function with SMP system, since I do not have SMP system.
139 cpu_get_usage_NT(cpu_options
*opts
)
143 static double pre_total
= 0, pre_used
= 0;
146 FARPROC NtQuerySystemInformation
= NULL
;
148 SYSTEM_BASIC_INFORMATION sbi
;
149 SYSTEM_TIME_INFORMATION sti
;
150 SYSTEM_PERFORMANCE_INFORMATION spi
;
152 if ((h_ntdll
= LoadLibraryEx("NTDLL.DLL", NULL
, 0)) == NULL
) {
153 fprintf(stderr
, "%s: could not load NTDLL.DLL\n", PACKAGE
);
157 NtQuerySystemInformation
= GetProcAddress(h_ntdll
,
158 "NtQuerySystemInformation");
159 if (!NtQuerySystemInformation
) {
160 fprintf(stderr
, "%s: could not find NtQuerySystemInformation()\n", PACKAGE
);
161 FreeLibrary(h_ntdll
);
165 if ((NtQuerySystemInformation(SystemBasicInformation
,
167 sizeof(SYSTEM_BASIC_INFORMATION
),
171 if ((NtQuerySystemInformation(SystemTimeInformation
,
173 sizeof(SYSTEM_TIME_INFORMATION
),
177 if ((NtQuerySystemInformation(SystemPerformanceInformation
,
179 sizeof(SYSTEM_PERFORMANCE_INFORMATION
),
183 total
= LONGINT2DOUBLE(sti
.liKeSystemTime
);
184 used
= total
- LONGINT2DOUBLE(spi
.IdleTime
);
186 if ((pre_total
== 0) || !(total
- pre_total
> 0)) {
189 usage
= (100 * (used
- pre_used
)) / (total
- pre_total
);
192 if (sbi
.bKeNumberProcessors
> 1) {
193 usage
= usage
/ sbi
.bKeNumberProcessors
;
199 FreeLibrary(h_ntdll
);
204 /* return current cpu usage in percent */
206 cpu_get_usage(cpu_options
*opts
)
210 return cpu_get_usage_9x(opts
);
212 return cpu_get_usage_NT(opts
);
213 default: /* make gcc happy */