Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2002-05-12 05:37:48 +0400
committerChristopher Faylor <me@cgf.cx>2002-05-12 05:37:48 +0400
commit9ba913a56dd6eb5af664cb3e29fa3e9a8d7a3752 (patch)
tree383aa2254cb793d0b3e606e8c981894b2b778d5a /winsup/cygwin/fhandler_proc.cc
parent558ab81ed169c70460dcd502050f76b3d47fb9b0 (diff)
* autoload.cc: Add dynamic load statements for 'ZwQueryInformationProcess' and
'ZwQueryVirtualMemory'. * fhandler.h: Change type of bufalloc and filesize members of fhandler_virtual from int to size_t. Change type of position member from __off32_t to __off64_t. Add new fileid member to fhandler_virtual class. Make seekdir take an __off64_t argument. Make lseek take an __off64_t argument. Add fill_filebuf method to fhandler_virtual. Add fill_filebuf method to fhandler_proc. Add fill_filebuf method to fhandler_registry. Add fill_filebuf method to fhandler_process. Add saved_pid and saved_p members to fhandler_process. * fhandler_proc.cc (proc_listing_array): Add 'loadavg', 'meminfo', and 'stat'. (proc_fhandlers array): Ditto. (fhandler_proc::open): Use fill_filebuf to flesh out the file contents. (fhandler_proc::fill_filebuf): New method. (fhandler_proc::format_proc_meminfo): Ditto. (fhandler_proc::format_proc_stat): Ditto. (fhandler_proc::format_proc_uptime): Ditto. * fhandler_process.cc (process_listing): Add 'stat' and 'statm'. (fhandler_process::fstat): Find the _pinfo structure for the process named in the filename. Return ENOENT if the process is no longer around. Set the gid and uid fields of the stat structure. (fhandler_process::open): Store pid and pointer to _pinfo structure in saved_pid and saved_p respectively. Use fill_filebuf to flesh out file contents. (fhandler_proc::fill_filebuf): New method. (format_process_stat): New function. (format_process_status): Ditto. (format_process_statm): Ditto. (get_process_state): Ditto. (get_mem_values): Ditto. * fhandler_registry.cc (fhandler_registry::seekdir): Change argument type from __off32_t to __off64_t. (fhandler_registry::fill_filebuf): New method. * fhandler_virtual.cc (fhandler_virtual::seekdir): Change argument type from __off32_t to __off64_t. (fhandler_virtual::lseek): Ditto. (fhandler_virtual::fill_filebuf): New method. (fhandler_virtual::fhandler_virtual): Initialise fileid to -1. * wincap.cc: Set flag has_process_io_counters appropriately. * wincap.h: Add flag has_process_io_counters.
Diffstat (limited to 'winsup/cygwin/fhandler_proc.cc')
-rw-r--r--winsup/cygwin/fhandler_proc.cc237
1 files changed, 211 insertions, 26 deletions
diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc
index 3d4946998..60e95780d 100644
--- a/winsup/cygwin/fhandler_proc.cc
+++ b/winsup/cygwin/fhandler_proc.cc
@@ -14,6 +14,7 @@ details. */
#include <unistd.h>
#include <stdlib.h>
#include <sys/cygwin.h>
+#include <ntdef.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
@@ -24,20 +25,27 @@ details. */
#include "cygheap.h"
#include <assert.h>
#include <sys/utsname.h>
+#include "ntdll.h"
#define _COMPILING_NEWLIB
#include <dirent.h>
/* offsets in proc_listing */
-static const int PROC_REGISTRY = 2; // /proc/registry
-static const int PROC_VERSION = 3; // /proc/version
-static const int PROC_UPTIME = 4; // /proc/uptime
+static const int PROC_LOADAVG = 2; // /proc/loadavg
+static const int PROC_MEMINFO = 3; // /proc/meminfo
+static const int PROC_REGISTRY = 4; // /proc/registry
+static const int PROC_STAT = 5; // /proc/stat
+static const int PROC_VERSION = 6; // /proc/version
+static const int PROC_UPTIME = 7; // /proc/uptime
/* names of objects in /proc */
static const char *proc_listing[] = {
".",
"..",
+ "loadavg",
+ "meminfo",
"registry",
+ "stat",
"version",
"uptime",
NULL
@@ -48,11 +56,14 @@ static const int PROC_LINK_COUNT = (sizeof(proc_listing) / sizeof(const char *))
/* FH_PROC in the table below means the file/directory is handles by
* fhandler_proc.
*/
-static const DWORD proc_fhandlers[] = {
+static const DWORD proc_fhandlers[PROC_LINK_COUNT] = {
+ FH_PROC,
+ FH_PROC,
FH_PROC,
FH_PROC,
FH_REGISTRY,
FH_PROC,
+ FH_PROC,
FH_PROC
};
@@ -60,6 +71,10 @@ static const DWORD proc_fhandlers[] = {
const char proc[] = "/proc";
const int proc_len = sizeof (proc) - 1;
+static off_t format_proc_meminfo (char *destbuf, size_t maxsize);
+static off_t format_proc_stat (char *destbuf, size_t maxsize);
+static off_t format_proc_uptime (char *destbuf, size_t maxsize);
+
/* auxillary function that returns the fhandler associated with the given path
* this is where it would be nice to have pattern matching in C - polymorphism
* just doesn't cut it
@@ -291,44 +306,214 @@ fhandler_proc::open (path_conv *pc, int flags, mode_t mode)
res = 0;
goto out;
}
- switch (proc_file_no)
+
+ fileid = proc_file_no;
+ fill_filebuf ();
+
+ if (flags & O_APPEND)
+ position = filesize;
+ else
+ position = 0;
+
+success:
+ res = 1;
+ set_open_status ();
+ set_flags (flags);
+out:
+ syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode);
+ return res;
+}
+
+void
+fhandler_proc::fill_filebuf ()
+{
+ switch (fileid)
{
case PROC_VERSION:
{
+ if (!filebuf)
+ {
struct utsname uts_name;
uname (&uts_name);
- filesize = bufalloc = strlen (uts_name.sysname) + 1 +
- strlen (uts_name.release) + 1 + strlen (uts_name.version) + 2;
+ bufalloc = strlen (uts_name.sysname) + 1 + strlen (uts_name.release) +
+ 1 + strlen (uts_name.version) + 2;
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc);
- __small_sprintf (filebuf, "%s %s %s\n", uts_name.sysname,
+ filesize = __small_sprintf (filebuf, "%s %s %s\n", uts_name.sysname,
uts_name.release, uts_name.version);
+ }
break;
}
case PROC_UPTIME:
{
- /* GetTickCount() wraps after 49 days - on WinNT/2000/XP, should use
- * perfomance counters but I don't know Redhat's policy on
- * NT only dependancies.
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 80);
+ filesize = format_proc_uptime (filebuf, bufalloc);
+ break;
+ }
+ case PROC_STAT:
+ {
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
+ filesize = format_proc_stat (filebuf, bufalloc);
+ break;
+ }
+ case PROC_LOADAVG:
+ {
+ /*
+ * not really supported - Windows doesn't keep track of these values
+ * Windows 95/98/me does have the KERNEL/CPUUsage performance counter
+ * which is similar.
*/
- DWORD ticks = GetTickCount ();
- filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
- __small_sprintf (filebuf, "%d.%02d\n", ticks / 1000,
- (ticks / 10) % 100);
- filesize = strlen (filebuf);
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 16);
+ filesize = __small_sprintf (filebuf, "%u.%02u %u.%02u %u.%02u\n",
+ 0, 0, 0, 0, 0, 0);
+ break;
+ }
+ case PROC_MEMINFO:
+ {
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
+ filesize = format_proc_meminfo (filebuf, bufalloc);
break;
}
}
+}
- if (flags & O_APPEND)
- position = filesize;
+static
+off_t
+format_proc_meminfo (char *destbuf, size_t maxsize)
+{
+ unsigned long mem_total = 0UL, mem_free = 0UL, swap_total = 0UL,
+ swap_free = 0UL;
+ MEMORYSTATUS memory_status;
+ GlobalMemoryStatus (&memory_status);
+ mem_total = memory_status.dwTotalPhys;
+ mem_free = memory_status.dwAvailPhys;
+ swap_total = memory_status.dwTotalPageFile;
+ swap_free = memory_status.dwAvailPageFile;
+ return __small_sprintf (destbuf, " total: used: free:\n"
+ "Mem: %10lu %10lu %10lu\n"
+ "Swap: %10lu %10lu %10lu\n"
+ "MemTotal: %10lu kB\n"
+ "MemFree: %10lu kB\n"
+ "MemShared: 0 kB\n"
+ "HighTotal: 0 kB\n"
+ "HighFree: 0 kB\n"
+ "LowTotal: %10lu kB\n"
+ "LowFree: %10lu kB\n"
+ "SwapTotal: %10lu kB\n"
+ "SwapFree: %10lu kB\n",
+ mem_total, mem_total - mem_free, mem_free,
+ swap_total, swap_total - swap_free, swap_free,
+ mem_total >> 10, mem_free >> 10,
+ mem_total >> 10, mem_free >> 10,
+ swap_total >> 10, swap_free >> 10);
+}
+
+static
+off_t
+format_proc_uptime (char *destbuf, size_t maxsize)
+{
+ unsigned long long uptime = 0ULL, idle_time = 0ULL;
+ SYSTEM_PROCESSOR_TIMES spt;
+
+ NTSTATUS ret = ZwQuerySystemInformation (SystemProcessorTimes, (PVOID) &spt,
+ sizeof spt, NULL);
+ if (!ret && GetLastError () == ERROR_PROC_NOT_FOUND)
+ uptime = GetTickCount() / 10;
+ else if (ret != STATUS_SUCCESS)
+ {
+ __seterrno_from_win_error (RtlNtStatusToDosError (ret));
+ debug_printf("NtQuerySystemInformation: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ return 0;
+ }
else
- position = 0;
+ {
+ idle_time = spt.IdleTime.QuadPart / 100000ULL;
+ uptime = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart +
+ spt.IdleTime.QuadPart + spt.UserTime.QuadPart +
+ spt.DpcTime.QuadPart) / 100000ULL;
+ }
-success:
- res = 1;
- set_open_status ();
- set_flags (flags);
-out:
- syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode);
- return res;
+ return __small_sprintf (destbuf, "%U.%02u %U.%02u\n",
+ uptime / 100, long (uptime % 100),
+ idle_time / 100, long (idle_time % 100));
+}
+
+static
+off_t
+format_proc_stat (char *destbuf, size_t maxsize)
+{
+ unsigned long long user_time = 0ULL, kernel_time = 0ULL, idle_time = 0ULL;
+ unsigned long pages_in = 0UL, pages_out = 0UL, interrupt_count = 0UL,
+ context_switches = 0UL, swap_in = 0UL, swap_out = 0UL;
+ time_t boot_time = 0;
+
+ if (wincap.is_winnt ())
+ {
+ NTSTATUS ret;
+ SYSTEM_PROCESSOR_TIMES spt;
+ SYSTEM_PERFORMANCE_INFORMATION spi;
+ SYSTEM_TIME_OF_DAY_INFORMATION stodi;
+ ret = ZwQuerySystemInformation (SystemProcessorTimes,
+ (PVOID) &spt,
+ sizeof spt, NULL);
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQuerySystemInformation (SystemPerformanceInformation,
+ (PVOID) &spi,
+ sizeof spi, NULL);
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQuerySystemInformation (SystemTimeOfDayInformation,
+ (PVOID) &stodi,
+ sizeof stodi, NULL);
+ if (ret != STATUS_SUCCESS)
+ {
+ __seterrno_from_win_error (RtlNtStatusToDosError (ret));
+ debug_printf("NtQuerySystemInformation: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ return 0;
+ }
+ kernel_time = (spt.KernelTime.QuadPart + spt.InterruptTime.QuadPart + spt.DpcTime.QuadPart) / 100000ULL;
+ user_time = spt.UserTime.QuadPart / 100000ULL;
+ idle_time = spt.IdleTime.QuadPart / 100000ULL;
+ interrupt_count = spt.InterruptCount;
+ pages_in = spi.PagesRead;
+ pages_out = spi.PagefilePagesWritten + spi.MappedFilePagesWritten;
+ /*
+ * Note: there is no distinction made in this structure between pages
+ * read from the page file and pages read from mapped files, but there
+ * is such a distinction made when it comes to writing. Goodness knows
+ * why. The value of swap_in, then, will obviously be wrong but its our
+ * best guess.
+ */
+ swap_in = spi.PagesRead;
+ swap_out = spi.PagefilePagesWritten;
+ context_switches = spi.ContextSwitches;
+ boot_time = to_time_t ((FILETIME *) &stodi.BootTime.QuadPart);
+ }
+ /*
+ * else
+ * {
+ * There are only two relevant performance counters on Windows 95/98/me,
+ * VMM/cPageIns and VMM/cPageOuts. The extra effort needed to read these
+ * counters is by no means worth it.
+ * }
+ */
+ return __small_sprintf (destbuf, "cpu %U %U %U %U\n"
+ "page %u %u\n"
+ "swap %u %u\n"
+ "intr %u\n"
+ "ctxt %u\n"
+ "btime %u\n",
+ user_time, 0ULL,
+ kernel_time, idle_time,
+ pages_in, pages_out,
+ swap_in, swap_out,
+ interrupt_count,
+ context_switches,
+ boot_time);
}