aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog45
-rw-r--r--winsup/cygwin/autoload.cc2
-rw-r--r--winsup/cygwin/fhandler.h19
-rw-r--r--winsup/cygwin/fhandler_proc.cc237
-rw-r--r--winsup/cygwin/fhandler_process.cc522
-rw-r--r--winsup/cygwin/fhandler_registry.cc7
-rw-r--r--winsup/cygwin/fhandler_virtual.cc19
-rw-r--r--winsup/cygwin/ntdll.h210
-rw-r--r--winsup/cygwin/wincap.cc11
-rw-r--r--winsup/cygwin/wincap.h2
10 files changed, 1001 insertions, 73 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 7584ed1..1bbffbd 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,4 +1,47 @@
-2002-05-09 Christopher Faylor <cgf@redhat.com>
+2002-05-10 Christopher January <chris@atomice.net>
+
+ * 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.
+
+2002-05-09 Christopher Faylor <cgf@redhat.com>
* syscalls.cc (_write): Change error to EBADF if attempt to write to a
non-writable fd.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 3a82e38..6592ef2 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -381,6 +381,8 @@ LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
LoadDLLfuncEx (ZwQuerySystemInformation, 16, ntdll, 1)
+LoadDLLfuncEx (ZwQueryInformationProcess, 20, ntdll, 1)
+LoadDLLfuncEx (ZwQueryVirtualMemory, 24, ntdll, 1)
LoadDLLfuncEx (GetProcessMemoryInfo, 12, psapi, 1)
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index aa0b6cc..1a48073 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -1043,8 +1043,9 @@ class fhandler_virtual : public fhandler_base
{
protected:
char *filebuf;
- int bufalloc, filesize;
- __off32_t position;
+ size_t bufalloc, filesize;
+ __off64_t position;
+ int fileid; // unique within each class
public:
fhandler_virtual (DWORD devtype);
@@ -1053,16 +1054,17 @@ class fhandler_virtual : public fhandler_base
virtual int exists(const char *path);
DIR *opendir (path_conv& pc);
__off64_t telldir (DIR *);
- void seekdir (DIR *, __off32_t);
+ void seekdir (DIR *, __off64_t);
void rewinddir (DIR *);
int closedir (DIR *);
int write (const void *ptr, size_t len);
int __stdcall read (void *ptr, size_t len) __attribute__ ((regparm (3)));
- __off64_t lseek (__off32_t, int);
+ __off64_t lseek (__off64_t, int);
int dup (fhandler_base * child);
int open (path_conv *, int flags, mode_t mode = 0);
int close (void);
int __stdcall fstat (struct stat *buf, path_conv *pc) __attribute__ ((regparm (3)));
+ virtual void fill_filebuf ();
};
class fhandler_proc: public fhandler_virtual
@@ -1076,6 +1078,7 @@ class fhandler_proc: public fhandler_virtual
int open (path_conv *real_path, int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
+ void fill_filebuf ();
};
class fhandler_registry: public fhandler_proc
@@ -1085,23 +1088,29 @@ class fhandler_registry: public fhandler_proc
int exists(const char *path);
struct dirent *readdir (DIR *);
__off64_t telldir (DIR *);
- void seekdir (DIR *, __off32_t);
+ void seekdir (DIR *, __off64_t);
void rewinddir (DIR *);
int closedir (DIR *);
int open (path_conv *real_path, int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
HKEY open_key(const char *name, REGSAM access = KEY_READ, bool isValue = false);
+ void fill_filebuf ();
};
+struct _pinfo;
class fhandler_process: public fhandler_proc
{
+ private:
+ pid_t saved_pid;
+ _pinfo *saved_p;
public:
fhandler_process ();
int exists(const char *path);
struct dirent *readdir (DIR *);
int open (path_conv *real_path, int flags, mode_t mode = 0);
int __stdcall fstat (struct __stat64 *buf, path_conv *) __attribute__ ((regparm (3)));
+ void fill_filebuf ();
};
typedef union
diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc
index 3d49469..60e9578 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);
}
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index 7f68d4a..f374d4d 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.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"
@@ -23,6 +24,7 @@ details. */
#include "shared_info.h"
#include "dtable.h"
#include "cygheap.h"
+#include "ntdll.h"
#include <assert.h>
#define _COMPILING_NEWLIB
@@ -38,6 +40,8 @@ static const int PROCESS_GID = 8;
static const int PROCESS_PGID = 9;
static const int PROCESS_SID = 10;
static const int PROCESS_CTTY = 11;
+static const int PROCESS_STAT = 12;
+static const int PROCESS_STATM = 13;
static const char *process_listing[] = {
".",
@@ -52,11 +56,20 @@ static const char *process_listing[] = {
"pgid",
"sid",
"ctty",
+ "stat",
+ "statm",
NULL
};
static const int PROCESS_LINK_COUNT = (sizeof(process_listing) / sizeof(const char *)) - 1;
+static off_t format_process_stat (_pinfo *p, char *destbuf, size_t maxsize);
+static off_t format_process_status (_pinfo *p, char *destbuf, size_t maxsize);
+static off_t format_process_statm (_pinfo *p, char *destbuf, size_t maxsize);
+static int get_process_state (DWORD dwProcessId);
+static bool get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext,
+ unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare);
+
/* Returns 0 if path doesn't exist, >0 if path is a directory,
* <0 if path is a file.
*/
@@ -84,8 +97,26 @@ fhandler_process::fhandler_process ():
int
fhandler_process::fstat (struct __stat64 *buf, path_conv *pc)
{
- int file_type = exists (get_name ());
+ const char *path = get_name ();
+ int file_type = exists (path);
(void) fhandler_base::fstat (buf, pc);
+ path += proc_len + 1;
+ int pid = atoi (path);
+ winpids pids;
+ _pinfo *p;
+ for (unsigned i = 0; i < pids.npids; i++)
+ {
+ p = pids[i];
+
+ if (!proc_exists (p))
+ continue;
+
+ if (p->pid == pid)
+ goto found;
+ }
+ set_errno(ENOENT);
+ return -1;
+found:
buf->st_mode &= ~_IFMT & NO_W;
switch (file_type)
@@ -97,12 +128,18 @@ fhandler_process::fstat (struct __stat64 *buf, path_conv *pc)
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
return 0;
case 2:
+ buf->st_ctime = buf->st_mtime = p->start_time;
+ buf->st_atime = time(NULL);
+ buf->st_uid = p->uid;
+ buf->st_gid = p->gid;
buf->st_mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
buf->st_nlink = PROCESS_LINK_COUNT;
return 0;
default:
case -1:
- buf->st_mode |= S_IFREG;
+ buf->st_uid = p->uid;
+ buf->st_gid = p->gid;
+ buf->st_mode |= S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
return 0;
}
}
@@ -198,7 +235,36 @@ fhandler_process::open (path_conv *pc, int flags, mode_t mode)
res = 0;
goto out;
found:
- switch (process_file_no)
+ fileid = process_file_no;
+ saved_pid = pid;
+ saved_p = p;
+ 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_process::fill_filebuf ()
+{
+ // has this process gone away?
+ if (!proc_exists (saved_p) || saved_p->pid != saved_pid)
+ {
+ if (filebuf)
+ cfree(filebuf);
+ filesize = 0; bufalloc = (size_t) -1;
+ }
+ switch (fileid)
{
case PROCESS_UID:
case PROCESS_GID:
@@ -207,25 +273,31 @@ found:
case PROCESS_CTTY:
case PROCESS_PPID:
{
+ if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
int num;
- switch (process_file_no)
+ switch (fileid)
{
case PROCESS_PPID:
- num = p->ppid;
+ num = saved_p->ppid;
break;
case PROCESS_UID:
- num = p->uid;
+ num = saved_p->uid;
break;
case PROCESS_PGID:
- num = p->pgid;
+ num = saved_p->pgid;
break;
case PROCESS_SID:
- num = p->sid;
+ num = saved_p->sid;
+ break;
+ case PROCESS_GID:
+ num = saved_p->gid;
break;
- default:
case PROCESS_CTTY:
- num = p->ctty;
+ num = saved_p->ctty;
+ break;
+ default: // what's this here for?
+ num = 0;
break;
}
__small_sprintf (filebuf, "%d\n", num);
@@ -234,12 +306,13 @@ found:
}
case PROCESS_EXENAME:
{
+ if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = MAX_PATH);
- if (p->process_state & (PID_ZOMBIE | PID_EXITED))
+ if (saved_p->process_state & (PID_ZOMBIE | PID_EXITED))
strcpy (filebuf, "<defunct>");
else
{
- mount_table->conv_to_posix_path (p->progname, filebuf, 1);
+ mount_table->conv_to_posix_path (saved_p->progname, filebuf, 1);
int len = strlen (filebuf);
if (len > 4)
{
@@ -253,47 +326,428 @@ found:
}
case PROCESS_WINPID:
{
+ if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 40);
- __small_sprintf (filebuf, "%d\n", p->dwProcessId);
+ __small_sprintf (filebuf, "%d\n", saved_p->dwProcessId);
filesize = strlen (filebuf);
break;
}
case PROCESS_WINEXENAME:
{
- int len = strlen (p->progname);
+ int len = strlen (saved_p->progname);
+ if (!filebuf)
filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = (len + 2));
- strcpy (filebuf, p->progname);
+ strcpy (filebuf, saved_p->progname);
filebuf[len] = '\n';
filesize = len + 1;
break;
}
case PROCESS_STATUS:
{
- filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 3);
- filebuf[0] = ' ';
- filebuf[1] = '\n';
- filebuf[2] = 0;
- if (p->process_state & PID_STOPPED)
- filebuf[0] = 'S';
- else if (p->process_state & PID_TTYIN)
- filebuf[0] = 'I';
- else if (p->process_state & PID_TTYOU)
- filebuf[0] = 'O';
- filesize = 2;
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
+ filesize = format_process_status (saved_p, filebuf, bufalloc);
+ break;
+ }
+ case PROCESS_STAT:
+ {
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
+ filesize = format_process_stat (saved_p, filebuf, bufalloc);
break;
}
+ case PROCESS_STATM:
+ {
+ if (!filebuf)
+ filebuf = (char *) cmalloc (HEAP_BUF, bufalloc = 2048);
+ filesize = format_process_statm (saved_p, filebuf, bufalloc);
+ break;
+ }
}
+}
- if (flags & O_APPEND)
- position = filesize;
+static
+off_t
+format_process_stat (_pinfo *p, char *destbuf, size_t maxsize)
+{
+ char cmd[MAX_PATH];
+ int state = 'R';
+ unsigned long fault_count = 0UL,
+ utime = 0UL, stime = 0UL,
+ start_time = 0UL,
+ vmsize = 0UL, vmrss = 0UL, vmmaxrss = 0UL;
+ int priority = 0;
+ if (p->process_state & (PID_ZOMBIE | PID_EXITED))
+ strcpy (cmd, "<defunct");
else
- position = 0;
+ {
+ strcpy(cmd, p->progname);
+ char *last_slash = strrchr (cmd, '\\');
+ if (last_slash != NULL)
+ strcpy (cmd, last_slash + 1);
+ int len = strlen (cmd);
+ if (len > 4)
+ {
+ char *s = cmd + len - 4;
+ if (strcasecmp (s, ".exe") == 0)
+ *s = 0;
+ }
+ }
+ /*
+ * Note: under Windows, a _process_ is always running - it's only _threads_
+ * that get suspended. Therefore the default state is R (runnable).
+ */
+ if (p->process_state & PID_ZOMBIE)
+ state = 'Z';
+ else if (p->process_state & PID_STOPPED)
+ state = 'T';
+ else if (wincap.is_winnt ())
+ state = get_process_state (p->dwProcessId);
+ if (wincap.is_winnt ())
+ {
+ NTSTATUS ret;
+ HANDLE hProcess;
+ VM_COUNTERS vmc;
+ KERNEL_USER_TIMES put;
+ PROCESS_BASIC_INFORMATION pbi;
+ QUOTA_LIMITS ql;
+ SYSTEM_TIME_OF_DAY_INFORMATION stodi;
+ SYSTEM_PROCESSOR_TIMES spt;
+ hProcess = OpenProcess (PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
+ FALSE, p->dwProcessId);
+ if (hProcess != NULL)
+ {
+ ret = ZwQueryInformationProcess (hProcess,
+ ProcessVmCounters,
+ (PVOID) &vmc,
+ sizeof vmc, NULL);
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQueryInformationProcess (hProcess,
+ ProcessTimes,
+ (PVOID) &put,
+ sizeof put, NULL);
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQueryInformationProcess (hProcess,
+ ProcessBasicInformation,
+ (PVOID) &pbi,
+ sizeof pbi, NULL);
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQueryInformationProcess (hProcess,
+ ProcessQuotaLimits,
+ (PVOID) &ql,
+ sizeof ql, NULL);
+ CloseHandle (hProcess);
+ }
+ else
+ {
+ DWORD error = GetLastError ();
+ __seterrno_from_win_error (error);
+ debug_printf("OpenProcess: ret = %d",
+ error);
+ return 0;
+ }
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQuerySystemInformation (SystemTimeOfDayInformation,
+ (PVOID) &stodi,
+ sizeof stodi, NULL);
+ if (ret == STATUS_SUCCESS)
+ ret = ZwQuerySystemInformation (SystemProcessorTimes,
+ (PVOID) &spt,
+ sizeof spt, NULL);
+ if (ret != STATUS_SUCCESS)
+ {
+ __seterrno_from_win_error (RtlNtStatusToDosError (ret));
+ debug_printf("NtQueryInformationProcess: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ return 0;
+ }
+ fault_count = vmc.PageFaultCount;
+ utime = put.UserTime.QuadPart / 100000ULL;
+ stime = put.KernelTime.QuadPart / 100000ULL;
+ if (stodi.CurrentTime.QuadPart > put.CreateTime.QuadPart)
+ start_time = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart +
+ spt.IdleTime.QuadPart + spt.UserTime.QuadPart +
+ spt.DpcTime.QuadPart - stodi.CurrentTime.QuadPart +
+ put.CreateTime.QuadPart) / 100000ULL;
+ else
+ /*
+ * sometimes stodi.CurrentTime is a bit behind
+ * Note: some older versions of procps are broken and can't cope
+ * with process start times > time(NULL).
+ */
+ start_time = (spt.InterruptTime.QuadPart + spt.KernelTime.QuadPart +
+ spt.IdleTime.QuadPart + spt.UserTime.QuadPart +
+ spt.DpcTime.QuadPart) / 100000ULL;
+ priority = pbi.BasePriority;
+ unsigned page_size = getpagesize();
+ vmsize = vmc.VirtualSize;
+ vmrss = vmc.WorkingSetSize / page_size;
+ vmmaxrss = ql.MaximumWorkingSetSize / page_size;
+ }
+ else
+ {
+ start_time = (GetTickCount() / 1000 - time(NULL) + p->start_time) * 100;
+ }
+ return __small_sprintf (destbuf, "%d (%s) %c "
+ "%d %d %d %d %d "
+ "%lu %lu %lu %lu %lu %lu %lu "
+ "%ld %ld %ld %ld %ld %ld "
+ "%lu %lu "
+ "%ld "
+ "%lu",
+ p->pid, cmd,
+ state,
+ p->ppid, p->pgid, p->sid, p->ctty, -1,
+ 0, fault_count, fault_count, 0, 0, utime, stime,
+ utime, stime, priority, 0, 0, 0,
+ start_time, vmsize,
+ vmrss, vmmaxrss
+ );
+}
-success:
- res = 1;
- set_open_status ();
- set_flags (flags);
+static
+off_t
+format_process_status (_pinfo *p, char *destbuf, size_t maxsize)
+{
+ char cmd[MAX_PATH];
+ int state = 'R';
+ const char *state_str = "unknown";
+ unsigned long vmsize = 0UL, vmrss = 0UL, vmdata = 0UL, vmlib = 0UL, vmtext = 0UL,
+ vmshare = 0UL;
+ if (p->process_state & (PID_ZOMBIE | PID_EXITED))
+ strcpy (cmd, "<defunct>");
+ else
+ {
+ strcpy(cmd, p->progname);
+ char *last_slash = strrchr (cmd, '\\');
+ if (last_slash != NULL)
+ strcpy (cmd, last_slash + 1);
+ int len = strlen (cmd);
+ if (len > 4)
+ {
+ char *s = cmd + len - 4;
+ if (strcasecmp (s, ".exe") == 0)
+ *s = 0;
+ }
+ }
+ /*
+ * Note: under Windows, a _process_ is always running - it's only _threads_
+ * that get suspended. Therefore the default state is R (runnable).
+ */
+ if (p->process_state & PID_ZOMBIE)
+ state = 'Z';
+ else if (p->process_state & PID_STOPPED)
+ state = 'T';
+ else if (wincap.is_winnt ())
+ state = get_process_state (p->dwProcessId);
+ switch (state)
+ {
+ case 'O':
+ state_str = "running";
+ break;
+ case 'D':
+ case 'S':
+ state_str = "sleeping";
+ break;
+ case 'R':
+ state_str = "runnable";
+ break;
+ case 'Z':
+ state_str = "zombie";
+ break;
+ case 'T':
+ state_str = "stopped";
+ break;
+ }
+ if (wincap.is_winnt ())
+ {
+ if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare))
+ return 0;
+ unsigned page_size = getpagesize();
+ vmsize *= page_size; vmrss *= page_size; vmdata *= page_size;
+ vmtext *= page_size; vmlib *= page_size;
+ }
+ return __small_sprintf (destbuf, "Name: %s\n"
+ "State: %c (%s)\n"
+ "Tgid: %d\n"
+ "Pid: %d\n"
+ "PPid: %d\n"
+ "Uid: %d %d %d %d\n"
+ "Gid: %d %d %d %d\n"
+ "VmSize: %8d kB\n"
+ "VmLck: %8d kB\n"
+ "VmRSS: %8d kB\n"
+ "VmData: %8d kB\n"
+ "VmStk: %8d kB\n"
+ "VmExe: %8d kB\n"
+ "VmLib: %8d kB\n"
+ "SigPnd: %016x\n"
+ "SigBlk: %016x\n"
+ "SigIgn: %016x\n",
+ cmd,
+ state, state_str,
+ p->pgid,
+ p->pid,
+ p->ppid,
+ p->uid, cygheap->user.real_uid, cygheap->user.real_uid, p->uid,
+ p->gid, cygheap->user.real_gid, cygheap->user.real_gid, p->gid,
+ vmsize >> 10, 0, vmrss >> 10, vmdata >> 10, 0, vmtext >> 10, vmlib >> 10,
+ 0, 0, p->getsigmask ()
+ );
+}
+
+static
+off_t
+format_process_statm (_pinfo *p, char *destbuf, size_t maxsize)
+{
+ unsigned long vmsize = 0UL, vmrss = 0UL, vmtext = 0UL, vmdata = 0UL, vmlib = 0UL,
+ vmshare = 0UL;
+ if (wincap.is_winnt ())
+ {
+ if (!get_mem_values (p->dwProcessId, &vmsize, &vmrss, &vmtext, &vmdata, &vmlib, &vmshare))
+ return 0;
+ }
+ return __small_sprintf (destbuf, "%ld %ld %ld %ld %ld %ld %ld",
+ vmsize, vmrss, vmshare, vmtext, vmlib, vmdata, 0
+ );
+}
+
+static
+int
+get_process_state (DWORD dwProcessId)
+{
+ /*
+ * This isn't really heavy magic - just go through the processes'
+ * threads one by one and return a value accordingly
+ * Errors are silently ignored.
+ */
+ NTSTATUS ret;
+ SYSTEM_PROCESSES *sp;
+ ULONG n = 0x1000;
+ PULONG p = new ULONG[n];
+ int state =' ';
+ while (STATUS_INFO_LENGTH_MISMATCH ==
+ (ret = ZwQuerySystemInformation (SystemProcessesAndThreadsInformation,
+ (PVOID) p,
+ n * sizeof *p, NULL)))
+ delete [] p, p = new ULONG[n *= 2];
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf("NtQuerySystemInformation: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ goto out;
+ }
+ state = 'Z';
+ sp = (SYSTEM_PROCESSES *) p;
+ for (;;)
+ {
+ if (sp->ProcessId == dwProcessId)
+ {
+ SYSTEM_THREADS *st;
+ if (wincap.has_process_io_counters ())
+ /*
+ * Windows 2000 and XP have an extra member in SYSTEM_PROCESSES
+ * which means the offset of the first SYSTEM_THREADS entry is
+ * different on these operating systems compared to NT 4.
+ */
+ st = &sp->Threads[0];
+ else
+ /*
+ * 136 is the offset of the first SYSTEM_THREADS entry on
+ * Windows NT 4.
+ */
+ st = (SYSTEM_THREADS *) ((char *) sp + 136);
+ state = 'S';
+ for (unsigned i = 0; i < sp->ThreadCount; i++)
+ {
+ if (st->State == StateRunning ||
+ st->State == StateReady)
+ {
+ state = 'R';
+ goto out;
+ }
+ st++;
+ }
+ break;
+ }
+ if (!sp->NextEntryDelta)
+ break;
+ sp = (SYSTEM_PROCESSES *) ((char *) sp + sp->NextEntryDelta);
+ }
out:
- syscall_printf ("%d = fhandler_proc::open (%p, %d)", res, flags, mode);
+ delete [] p;
+ return state;
+}
+
+static
+bool
+get_mem_values(DWORD dwProcessId, unsigned long *vmsize, unsigned long *vmrss, unsigned long *vmtext,
+ unsigned long *vmdata, unsigned long *vmlib, unsigned long *vmshare)
+{
+ bool res = true;
+ NTSTATUS ret;
+ HANDLE hProcess;
+ VM_COUNTERS vmc;
+ MEMORY_WORKING_SET_LIST *mwsl;
+ ULONG n = 0x1000, length;
+ PULONG p = new ULONG[n];
+ unsigned page_size = getpagesize();
+ hProcess = OpenProcess (PROCESS_QUERY_INFORMATION,
+ FALSE, dwProcessId);
+ if (hProcess == NULL)
+ {
+ DWORD error = GetLastError();
+ __seterrno_from_win_error (error);
+ debug_printf("OpenProcess: ret = %d",
+ error);
+ return false;
+ }
+ while ((ret = ZwQueryVirtualMemory (hProcess, 0,
+ MemoryWorkingSetList,
+ (PVOID) p,
+ n * sizeof *p, &length)),
+ (ret == STATUS_SUCCESS || ret == STATUS_INFO_LENGTH_MISMATCH) &&
+ length >= n * sizeof *p)
+ delete [] p, p = new ULONG[n *= 2];
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf("NtQueryVirtualMemory: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ res = false;
+ goto out;
+ }
+ mwsl = (MEMORY_WORKING_SET_LIST *) p;
+ for (unsigned long i = 0; i < mwsl->NumberOfPages; i++)
+ {
+ ++*vmrss;
+ unsigned flags = mwsl->WorkingSetList[i] & 0x0FFF;
+ if (flags & (WSLE_PAGE_EXECUTE | WSLE_PAGE_SHAREABLE) == (WSLE_PAGE_EXECUTE | WSLE_PAGE_SHAREABLE))
+ ++*vmlib;
+ else if (flags & WSLE_PAGE_SHAREABLE)
+ ++*vmshare;
+ else if (flags & WSLE_PAGE_EXECUTE)
+ ++*vmtext;
+ else
+ ++*vmdata;
+ }
+ ret = ZwQueryInformationProcess (hProcess,
+ ProcessVmCounters,
+ (PVOID) &vmc,
+ sizeof vmc, NULL);
+ if (ret != STATUS_SUCCESS)
+ {
+ debug_printf("NtQueryInformationProcess: ret = %d, "
+ "Dos(ret) = %d",
+ ret, RtlNtStatusToDosError (ret));
+ res = false;
+ goto out;
+ }
+ *vmsize = vmc.VirtualSize / page_size;
+out:
+ delete [] p;
+ CloseHandle (hProcess);
return res;
}
diff --git a/winsup/cygwin/fhandler_registry.cc b/winsup/cygwin/fhandler_registry.cc
index e0938e7..4fc5024 100644
--- a/winsup/cygwin/fhandler_registry.cc
+++ b/winsup/cygwin/fhandler_registry.cc
@@ -292,7 +292,7 @@ fhandler_registry::telldir (DIR * dir)
}
void
-fhandler_registry::seekdir (DIR * dir, __off32_t loc)
+fhandler_registry::seekdir (DIR * dir, __off64_t loc)
{
/* Unfortunately cannot simply set __d_position due to transition from sub-keys to
* values.
@@ -490,6 +490,11 @@ out:
return res;
}
+void
+fhandler_registry::fill_filebuf ()
+{
+}
+
/* Auxillary member function to open registry keys. */
HKEY
fhandler_registry::open_key (const char *name, REGSAM access, bool isValue)
diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc
index fa774f0..29b7ceb 100644
--- a/winsup/cygwin/fhandler_virtual.cc
+++ b/winsup/cygwin/fhandler_virtual.cc
@@ -27,7 +27,8 @@ details. */
#include <dirent.h>
fhandler_virtual::fhandler_virtual (DWORD devtype):
- fhandler_base (devtype), filebuf (NULL), bufalloc (-1)
+ fhandler_base (devtype), filebuf (NULL), bufalloc ((size_t) -1),
+ fileid (-1)
{
}
@@ -89,7 +90,7 @@ __off64_t fhandler_virtual::telldir (DIR * dir)
}
void
-fhandler_virtual::seekdir (DIR * dir, __off32_t loc)
+fhandler_virtual::seekdir (DIR * dir, __off64_t loc)
{
dir->__d_position = loc;
return;
@@ -109,8 +110,13 @@ fhandler_virtual::closedir (DIR * dir)
}
__off64_t
-fhandler_virtual::lseek (__off32_t offset, int whence)
+fhandler_virtual::lseek (__off64_t offset, int whence)
{
+ /*
+ * On Linux, when you lseek within a /proc file,
+ * the contents of the file are updated.
+ */
+ fill_filebuf ();
switch (whence)
{
case SEEK_SET:
@@ -124,7 +130,7 @@ fhandler_virtual::lseek (__off32_t offset, int whence)
break;
default:
set_errno (EINVAL);
- return (__off32_t) -1;
+ return (__off64_t) -1;
}
return position;
}
@@ -214,3 +220,8 @@ fhandler_virtual::exists (const char *path)
{
return 0;
}
+
+void
+fhandler_virtual::fill_filebuf ()
+{
+}
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index e1ec33b..f2a96aa 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -10,11 +10,28 @@
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#define FILE_SYNCHRONOUS_IO_NONALERT 32
+#define PDI_MODULES 0x01
+#define PDI_HEAPS 0x04
+#define LDRP_IMAGE_DLL 0x00000004
+#define WSLE_PAGE_READONLY 0x001
+#define WSLE_PAGE_EXECUTE 0x002
+#define WSLE_PAGE_EXECUTE_READ 0x003
+#define WSLE_PAGE_READWRITE 0x004
+#define WSLE_PAGE_WRITECOPY 0x005
+#define WSLE_PAGE_EXECUTE_READWRITE 0x006
+#define WSLE_PAGE_EXECUTE_WRITECOPY 0x007
+#define WSLE_PAGE_SHARE_COUNT_MASK 0x0E0
+#define WSLE_PAGE_SHAREABLE 0x100
+
+typedef ULONG KAFFINITY;
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation = 0,
+ SystemPerformanceInformation = 2,
+ SystemTimeOfDayInformation = 3,
SystemProcessesAndThreadsInformation = 5,
+ SystemProcessorTimes = 8,
/* There are a lot more of these... */
} SYSTEM_INFORMATION_CLASS;
@@ -30,9 +47,19 @@ typedef struct _SYSTEM_BASIC_INFORMATION
ULONG LowestUserAddress;
ULONG HighestUserAddress;
ULONG ActiveProcessors;
- ULONG NumberProcessors;
+ UCHAR NumberProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
+typedef struct _SYSTEM_PROCESSOR_TIMES
+{
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+ LARGE_INTEGER DpcTime;
+ LARGE_INTEGER InterruptTime;
+ ULONG InterruptCount;
+} SYSTEM_PROCESSOR_TIMES, *PSYSTEM_PROCESSOR_TIMES;
+
typedef LONG KPRIORITY;
typedef struct _VM_COUNTERS
{
@@ -112,12 +139,13 @@ typedef struct _SYSTEM_THREADS
ULONG ContextSwitchCount;
THREAD_STATE State;
KWAIT_REASON WaitReason;
+ DWORD Reserved;
} SYSTEM_THREADS, *PSYSTEM_THREADS;
typedef struct _SYSTEM_PROCESSES
{
ULONG NextEntryDelta;
- ULONG Threadcount;
+ ULONG ThreadCount;
ULONG Reserved1[6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
@@ -139,6 +167,180 @@ typedef struct _IO_STATUS_BLOCK
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+typedef struct _SYSTEM_PERFORMANCE_INFORMATION
+{
+ LARGE_INTEGER IdleTime;
+ LARGE_INTEGER ReadTransferCount;
+ LARGE_INTEGER WriteTransferCount;
+ LARGE_INTEGER OtherTransferCount;
+ ULONG ReadOperationCount;
+ ULONG WriteOperationCount;
+ ULONG OtherOperationCount;
+ ULONG AvailablePages;
+ ULONG TotalCommittedPages;
+ ULONG TotalCommitLimit;
+ ULONG PeakCommitment;
+ ULONG PageFaults;
+ ULONG WriteCopyFaults;
+ ULONG TransitionFaults;
+ ULONG Reserved1;
+ ULONG DemandZeroFaults;
+ ULONG PagesRead;
+ ULONG PageReadIos;
+ ULONG Reserved2[2];
+ ULONG PagefilePagesWritten;
+ ULONG PagefilePageWriteIos;
+ ULONG MappedFilePagesWritten;
+ ULONG MappedFilePageWriteIos;
+ ULONG PagedPoolUsage;
+ ULONG NonPagedPoolUsage;
+ ULONG PagedPoolAllocs;
+ ULONG PagedPoolFrees;
+ ULONG NonPagedPoolAllocs;
+ ULONG NonPagedPoolFrees;
+ ULONG TotalFreeSystemPtes;
+ ULONG SystemCodePage;
+ ULONG TotalSystemDriverPages;
+ ULONG TotalSystemCodePages;
+ ULONG SmallNonPagedLookasideListAllocateHits;
+ ULONG SmallPagedLookasideListAllocateHits;
+ ULONG Reserved3;
+ ULONG MmSystemCachePage;
+ ULONG PagedPoolPage;
+ ULONG SystemDriverPage;
+ ULONG FastReadNoWait;
+ ULONG FastReadWait;
+ ULONG FastReadResourceMiss;
+ ULONG FastReadNotPossible;
+ ULONG FastMdlReadNoWait;
+ ULONG FastMdlReadWait;
+ ULONG FastMdlReadResourceMiss;
+ ULONG FastMdlReadNotPossible;
+ ULONG MapDataNoWait;
+ ULONG MapDataWait;
+ ULONG MapDataNoWaitMiss;
+ ULONG MapDataWaitMiss;
+ ULONG PinMappedDataCount;
+ ULONG PinReadNoWait;
+ ULONG PinReadWait;
+ ULONG PinReadNoWaitMiss;
+ ULONG PinReadWaitMiss;
+ ULONG CopyReadNoWait;
+ ULONG CopyReadWait;
+ ULONG CopyReadNoWaitMiss;
+ ULONG CopyReadWaitMiss;
+ ULONG MdlReadNoWait;
+ ULONG MdlReadWait;
+ ULONG MdlReadNoWaitMiss;
+ ULONG MdlReadWaitMiss;
+ ULONG ReadAheadIos;
+ ULONG LazyWriteIos;
+ ULONG LazyWritePages;
+ ULONG DataFlushes;
+ ULONG DataPages;
+ ULONG ContextSwitches;
+ ULONG FirstLevelTbFills;
+ ULONG SecondLevelTbFills;
+ ULONG SystemCalls;
+} SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION;
+
+typedef struct _SYSTEM_TIME_OF_DAY_INFORMATION
+{
+ LARGE_INTEGER BootTime;
+ LARGE_INTEGER CurrentTime;
+ LARGE_INTEGER TimeZoneBias;
+ ULONG CurrentTimeZoneId;
+} SYSTEM_TIME_OF_DAY_INFORMATION, *PSYSTEM_TIME_OF_DAY_INFORMATION;
+
+typedef enum _PROCESSINFOCLASS
+{
+ ProcessBasicInformation = 0,
+ ProcessQuotaLimits = 1,
+ ProcessVmCounters = 3,
+ ProcessTimes =4,
+} PROCESSINFOCLASS;
+
+typedef struct _DEBUG_BUFFER
+{
+ HANDLE SectionHandle;
+ PVOID SectionBase;
+ PVOID RemoteSectionBase;
+ ULONG SectionBaseDelta;
+ HANDLE EventPairHandle;
+ ULONG Unknown[2];
+ HANDLE RemoteThreadHandle;
+ ULONG InfoClassMask;
+ ULONG SizeOfInfo;
+ ULONG AllocatedSize;
+ ULONG SectionSize;
+ PVOID ModuleInformation;
+ PVOID BackTraceInformation;
+ PVOID HeapInformation;
+ PVOID LockInformation;
+ PVOID Reserved[9];
+} DEBUG_BUFFER, *PDEBUG_BUFFER;
+
+typedef struct _DEBUG_HEAP_INFORMATION
+{
+ ULONG Base;
+ ULONG Flags;
+ USHORT Granularity;
+ USHORT Unknown;
+ ULONG Allocated;
+ ULONG Committed;
+ ULONG TagCount;
+ ULONG BlockCount;
+ ULONG Reserved[7];
+ PVOID Tags;
+ PVOID Blocks;
+} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;
+
+typedef struct _DEBUG_MODULE_INFORMATION
+{
+ ULONG Reserved[2];
+ ULONG Base;
+ ULONG Size;
+ ULONG Flags;
+ USHORT Index;
+ USHORT Unknown;
+ USHORT LoadCount;
+ USHORT ModuleNameOffset;
+ CHAR ImageName[256];
+} DEBUG_MODULE_INFORMATION, *PDEBUG_MODULE_INFORMATION;
+
+typedef struct _KERNEL_USER_TIMES
+{
+ LARGE_INTEGER CreateTime;
+ LARGE_INTEGER ExitTime;
+ LARGE_INTEGER KernelTime;
+ LARGE_INTEGER UserTime;
+} KERNEL_USER_TIMES, *PKERNEL_USER_TIMES;
+
+typedef void *PPEB;
+
+typedef struct _PROCESS_BASIC_INFORMATION
+{
+ NTSTATUS ExitStatus;
+ PPEB PebBaseAddress;
+ KAFFINITY AffinityMask;
+ KPRIORITY BasePriority;
+ ULONG UniqueProcessId;
+ ULONG InheritedFromUniqueProcessId;
+} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
+
+typedef enum _MEMORY_INFORMATION_CLASS
+{
+ MemoryBasicInformation,
+ MemoryWorkingSetList,
+ MemorySectionName,
+ MemoryBaiscVlmInformation
+} MEMORY_INFORMATION_CLASS;
+
+typedef struct _MEMORY_WORKING_SET_LIST {
+ ULONG NumberOfPages;
+ ULONG WorkingSetList[1];
+} MEMORY_WORKING_SET_LIST, *PMEMORY_WORKING_SET_LIST;
+
/* Function declarations for ntdll.dll. These don't appear in any
standard Win32 header. */
extern "C"
@@ -162,4 +364,8 @@ extern "C"
NTSTATUS NTAPI ZwQuerySystemInformation (IN SYSTEM_INFORMATION_CLASS,
IN OUT PVOID, IN ULONG,
OUT PULONG);
+ NTSTATUS NTAPI ZwQueryInformationProcess (IN HANDLE, IN PROCESSINFOCLASS,
+ OUT PVOID, IN ULONG, OUT PULONG);
+ NTSTATUS NTAPI ZwQueryVirtualMemory (IN HANDLE, IN PVOID, IN MEMORY_INFORMATION_CLASS,
+ OUT PVOID, IN ULONG, OUT PULONG);
}
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 09e95fb..1b3fd4b 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -46,6 +46,7 @@ static NO_COPY wincaps wincap_unknown = {
has_raw_devices:false,
has_valid_processorlevel:false,
has_64bit_file_access:false,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_95 = {
@@ -83,6 +84,7 @@ static NO_COPY wincaps wincap_95 = {
has_raw_devices:false,
has_valid_processorlevel:false,
has_64bit_file_access:false,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_95osr2 = {
@@ -120,6 +122,7 @@ static NO_COPY wincaps wincap_95osr2 = {
has_raw_devices:false,
has_valid_processorlevel:false,
has_64bit_file_access:false,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_98 = {
@@ -157,6 +160,7 @@ static NO_COPY wincaps wincap_98 = {
has_raw_devices:false,
has_valid_processorlevel:true,
has_64bit_file_access:false,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_98se = {
@@ -194,6 +198,7 @@ static NO_COPY wincaps wincap_98se = {
has_raw_devices:false,
has_valid_processorlevel:true,
has_64bit_file_access:false,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_me = {
@@ -231,6 +236,7 @@ static NO_COPY wincaps wincap_me = {
has_raw_devices:false,
has_valid_processorlevel:true,
has_64bit_file_access:false,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_nt3 = {
@@ -268,6 +274,7 @@ static NO_COPY wincaps wincap_nt3 = {
has_raw_devices:true,
has_valid_processorlevel:true,
has_64bit_file_access:true,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_nt4 = {
@@ -305,6 +312,7 @@ static NO_COPY wincaps wincap_nt4 = {
has_raw_devices:true,
has_valid_processorlevel:true,
has_64bit_file_access:true,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_nt4sp4 = {
@@ -342,6 +350,7 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_raw_devices:true,
has_valid_processorlevel:true,
has_64bit_file_access:true,
+ has_process_io_counters:false,
};
static NO_COPY wincaps wincap_2000 = {
@@ -379,6 +388,7 @@ static NO_COPY wincaps wincap_2000 = {
has_raw_devices:true,
has_valid_processorlevel:true,
has_64bit_file_access:true,
+ has_process_io_counters:true,
};
static NO_COPY wincaps wincap_xp = {
@@ -416,6 +426,7 @@ static NO_COPY wincaps wincap_xp = {
has_raw_devices:true,
has_valid_processorlevel:true,
has_64bit_file_access:true,
+ has_process_io_counters:true,
};
wincapc NO_COPY wincap;
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 088907a..c33c3cf 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -47,6 +47,7 @@ struct wincaps
unsigned has_raw_devices : 1;
unsigned has_valid_processorlevel : 1;
unsigned has_64bit_file_access : 1;
+ unsigned has_process_io_counters : 1;
};
class wincapc
@@ -99,6 +100,7 @@ public:
bool IMPLEMENT (has_raw_devices)
bool IMPLEMENT (has_valid_processorlevel)
bool IMPLEMENT (has_64bit_file_access)
+ bool IMPLEMENT (has_process_io_counters)
#undef IMPLEMENT
};