Initial dockapps git repo
[dockapps.git] / wmcpuload-1.0.0 / src / cpu_cygwin.c
blobf751e11f46c5837fd2b2b94f7ba3268b173414d7
1 /*
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
7 */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include "cpu.h"
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 */
27 /* 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 */
35 DWORD unused1;
36 ULONG unused2[6];
37 PVOID unused3[2];
38 ULONG unused4;
39 BYTE bKeNumberProcessors;
40 BYTE unused5;
41 WORD unused6;
42 } SYSTEM_BASIC_INFORMATION;
44 typedef struct _SYSTEM_PERFORMANCE_INFORMATION { /* Info Class 2 */
45 LARGE_INTEGER IdleTime;
46 DWORD unused[76];
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;
54 DWORD dwReserved;
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;
64 void
65 cpu_init(void)
67 OSVERSIONINFO os_ver_info;
69 /* which version? */
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);
76 exit (1);
81 * cpu_get_usage_9x(): get cpu usage in percent via registry
83 * How to get:
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.;(
90 static int
91 cpu_get_usage_9x(cpu_options *opts)
93 int usage = 0;
95 HKEY hkeys; /* for monitoring (start, stop) */
96 HKEY hkeyr; /* for reading usage */
97 DWORD dummy;
98 DWORD dwsize = sizeof(DWORD);
100 if (RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\\StatData",
101 0, KEY_READ, &hkeyr) != ERROR_SUCCESS) {
102 fprintf(stderr, "%s: can't open registry 'PerfStats\\StatData'\n", PACKAGE);
103 return 0;
106 /* start monitoring */
107 RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\\StartStat", 0, KEY_READ, &hkeys);
108 RegQueryValueEx(hkeys, "KERNEL\\CPUUsage", 0, NULL, (LPBYTE)&dummy,
109 &dwsize);
110 RegCloseKey(hkeys);
112 /* get usage */
113 RegQueryValueEx(hkeyr, "KERNEL\\CPUUsage", 0, NULL, (LPBYTE)&usage,
114 &dwsize);
115 RegCloseKey(hkeyr);
117 /* stop monitoring */
118 RegOpenKeyEx(HKEY_DYN_DATA, "PerfStats\\StopStat", 0, KEY_READ, &hkeys);
119 RegQueryValueEx(hkeys, "KERNEL\\CPUUsage", 0, NULL, (LPBYTE)&dummy,
120 &dwsize);
121 RegCloseKey(hkeys);
123 return usage;
127 * cpu_get_usage_NT:
129 * How to get:
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.
138 static int
139 cpu_get_usage_NT(cpu_options *opts)
141 int usage;
142 double total, used;
143 static double pre_total = 0, pre_used = 0;
145 HINSTANCE h_ntdll;
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: can't load NTDLL.DLL\n", PACKAGE);
154 exit (1);
157 NtQuerySystemInformation = GetProcAddress(h_ntdll,
158 "NtQuerySystemInformation");
159 if (!NtQuerySystemInformation) {
160 fprintf(stderr, "%s: can't find NtQuerySystemInformation()\n", PACKAGE);
161 FreeLibrary(h_ntdll);
162 return 0;
165 if ((NtQuerySystemInformation(SystemBasicInformation,
166 &sbi,
167 sizeof(SYSTEM_BASIC_INFORMATION),
168 NULL)) != NO_ERROR)
169 return 0;
171 if ((NtQuerySystemInformation(SystemTimeInformation,
172 &sti,
173 sizeof(SYSTEM_TIME_INFORMATION),
174 0)) != NO_ERROR)
175 return 0;
177 if ((NtQuerySystemInformation(SystemPerformanceInformation,
178 &spi,
179 sizeof(SYSTEM_PERFORMANCE_INFORMATION),
180 0)) != NO_ERROR)
181 return 0;
183 total = LONGINT2DOUBLE(sti.liKeSystemTime);
184 used = total - LONGINT2DOUBLE(spi.IdleTime);
186 if ((pre_total == 0) || !(total - pre_total > 0)) {
187 usage = 0;
188 } else {
189 usage = (100 * (used - pre_used)) / (total - pre_total);
192 if (sbi.bKeNumberProcessors > 1) {
193 usage = usage / sbi.bKeNumberProcessors;
196 pre_used = used;
197 pre_total = total;
199 FreeLibrary(h_ntdll);
201 return usage;
204 /* return current cpu usage in percent */
206 cpu_get_usage(cpu_options *opts)
208 switch (platform) {
209 case WIN32_9x:
210 return cpu_get_usage_9x(opts);
211 case WIN32_NT:
212 return cpu_get_usage_NT(opts);
213 default: /* make gcc happy */
214 break;
216 return 0;