aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog22
-rw-r--r--winsup/cygwin/autoload.cc4
-rw-r--r--winsup/cygwin/cygwin.din2
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/sys/mman.h2
-rw-r--r--winsup/cygwin/mmap.cc92
-rw-r--r--winsup/cygwin/ntdll.h6
-rw-r--r--winsup/cygwin/sysconf.cc2
-rw-r--r--winsup/cygwin/wincap.cc39
-rw-r--r--winsup/cygwin/wincap.h2
10 files changed, 160 insertions, 14 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index cb6dcb5..eb1382e 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,25 @@
+2005-10-18 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (NtLockVirtualMemory): Import.
+ (NtUnlockVirtualMemory): Import.
+ (GetProcessWorkingSetSize): Import.
+ (SetProcessWorkingSetSize): Import.
+ * cygwin.din (mlock): Export.
+ (munlock): Export.
+ * mmap.cc (mlock): New function.
+ (munlock): Ditto.
+ * ntdll.h (STATUS_WORKING_SET_QUOTA): Define.
+ (LOCK_VM_IN_WSL): Define.
+ (LOCK_VM_IN_RAM): Define.
+ (NtLockVirtualMemory): Declare.
+ (NtUnlockVirtualMemory): Declare.
+ * sysconf.cc (sysconf): Implement _SC_MEMLOCK_RANGE.
+ * wincap.h: Implement has_working_virtual_lock throughout.
+ * wincap.cc: Ditto.
+ * include/cygwin/version.h: Bump API minor version.
+ * include/sys/mman.h (mlock): Declare,
+ (munlock): Declare.
+
2005-10-18 Christopher Faylor <cgf@timesys.com>
* sigproc.cc (child_info::sync): Use correct name when closing to
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 8ac707e..87564f5 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -379,6 +379,7 @@ LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
LoadDLLfuncEx (NtCreateFile, 44, ntdll, 1)
LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1)
+LoadDLLfuncEx (NtLockVirtualMemory, 16, ntdll, 1)
LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1)
LoadDLLfuncEx (NtOpenSection, 12, ntdll, 1)
@@ -390,6 +391,7 @@ LoadDLLfuncEx (NtQuerySecurityObject, 20, ntdll, 1)
LoadDLLfuncEx (NtQueryVirtualMemory, 24, ntdll, 1)
LoadDLLfuncEx (NtQueryVolumeInformationFile, 20, ntdll, 1)
LoadDLLfuncEx (NtSetSecurityObject, 12, ntdll, 1)
+LoadDLLfuncEx (NtUnlockVirtualMemory, 16, ntdll, 1)
LoadDLLfuncEx (NtUnmapViewOfSection, 8, ntdll, 1)
LoadDLLfuncEx (RtlInitUnicodeString, 8, ntdll, 1)
LoadDLLfuncEx (RtlNtStatusToDosError, 4, ntdll, 1)
@@ -508,6 +510,7 @@ LoadDLLfuncEx2 (GetCompressedFileSizeA, 8, kernel32, 1, 0xffffffff)
LoadDLLfuncEx (GetConsoleWindow, 0, kernel32, 1)
LoadDLLfuncEx (GetDiskFreeSpaceEx, 16, kernel32, 1)
LoadDLLfuncEx (GetNativeSystemInfo, 4, kernel32, 1)
+LoadDLLfuncEx (GetProcessWorkingSetSize, 12, kernel32, 1)
LoadDLLfuncEx (GetSystemTimes, 12, kernel32, 1)
LoadDLLfuncEx (GetVolumeNameForVolumeMountPointA, 12, kernel32, 1)
LoadDLLfuncEx2 (IsDebuggerPresent, 0, kernel32, 1, 1)
@@ -516,6 +519,7 @@ LoadDLLfuncEx (IsWow64Process, 8, kernel32, 1);
LoadDLLfuncEx (Process32First, 8, kernel32, 1)
LoadDLLfuncEx (Process32Next, 8, kernel32, 1)
LoadDLLfuncEx (RegisterServiceProcess, 8, kernel32, 1)
+LoadDLLfuncEx (SetProcessWorkingSetSize, 12, kernel32, 1)
LoadDLLfuncEx (SignalObjectAndWait, 16, kernel32, 1)
LoadDLLfuncEx (SwitchToThread, 0, kernel32, 1)
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 4543352..f172f14 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -953,6 +953,8 @@ _modff = modff NOSIGFE
mount SIGFE
_mount = mount SIGFE
mprotect SIGFE
+mlock SIGFE
+munlock SIGFE
mrand48 NOSIGFE
msgctl SIGFE
msgget SIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 32dfa41..9edd898 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -277,12 +277,13 @@ details. */
138: Export readdir_r.
139: Start using POSIX definition of struct msghdr and WinSock2
IPPROTO_IP values.
+ 140: Export mlock, munlock.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 139
+#define CYGWIN_VERSION_API_MINOR 140
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/sys/mman.h b/winsup/cygwin/include/sys/mman.h
index 21bf697..5290a62 100644
--- a/winsup/cygwin/include/sys/mman.h
+++ b/winsup/cygwin/include/sys/mman.h
@@ -49,6 +49,8 @@ extern void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd
extern int munmap (void *__addr, size_t __len);
extern int mprotect (void *__addr, size_t __len, int __prot);
extern int msync (void *__addr, size_t __len, int __flags);
+extern int mlock (const void *__addr, size_t __len);
+extern int munlock (const void *__addr, size_t __len);
#ifdef __cplusplus
};
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index d85186f..ad47cb9 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -977,6 +977,98 @@ mprotect (void *addr, size_t len, int prot)
return 0;
}
+extern "C" int
+mlock (const void *addr, size_t len)
+{
+ if (!wincap.has_working_virtual_lock ())
+ return 0;
+
+ int ret = -1;
+
+ /* Instead of using VirtualLock, which does not guarantee that the pages
+ aren't swapped out when the process is inactive, we're using
+ ZwLockVirtualMemory with the LOCK_VM_IN_RAM flag to do what mlock on
+ POSIX systems does. On NT, this requires SeLockMemoryPrivilege,
+ which is given only to SYSTEM by default. */
+
+ push_thread_privilege (SE_LOCK_MEMORY_PRIV, true);
+
+ /* Align address and length values to page size. */
+ PVOID base = (PVOID) ((uintptr_t) addr & ~(getpagesize () - 1));
+ ULONG size = ((uintptr_t) addr - (uintptr_t) base) + len;
+ size = (size + getpagesize () - 1) & ~(getpagesize () - 1);
+ NTSTATUS status = 0;
+ do
+ {
+ status = NtLockVirtualMemory (hMainProc, &base, &size, LOCK_VM_IN_RAM);
+ if (status == STATUS_WORKING_SET_QUOTA)
+ {
+ /* The working set is too small, try to increase it so that the
+ requested locking region fits in. Unfortunately I don't know
+ any function which would return the currently locked pages of
+ a process (no go with NtQueryVirtualMemory).
+
+ So, except for the border cases, what we do here is something
+ really embarrassing. We raise the working set by 64K at a time
+ and retry, until either we fail to raise the working set size
+ further, or until NtLockVirtualMemory returns successfully (or
+ with another error). */
+ ULONG min, max;
+ if (!GetProcessWorkingSetSize (hMainProc, &min, &max))
+ {
+ set_errno (ENOMEM);
+ break;
+ }
+ if (min < size)
+ min = size + 12 * getpagesize (); /* Evaluated by testing */
+ else if (size < 65536)
+ min += size;
+ else
+ min += 65536;
+ if (max < min)
+ max = min;
+ if (!SetProcessWorkingSetSize (hMainProc, min, max))
+ {
+ set_errno (ENOMEM);
+ break;
+ }
+ }
+ else if (!NT_SUCCESS (status))
+ __seterrno_from_nt_status (status);
+ else
+ ret = 0;
+ }
+ while (status == STATUS_WORKING_SET_QUOTA);
+
+ pop_thread_privilege ();
+
+ return ret;
+}
+
+extern "C" int
+munlock (const void *addr, size_t len)
+{
+ if (!wincap.has_working_virtual_lock ())
+ return 0;
+
+ int ret = -1;
+
+ push_thread_privilege (SE_LOCK_MEMORY_PRIV, true);
+
+ PVOID base = (PVOID) addr;
+ ULONG size = len;
+ NTSTATUS status = NtUnlockVirtualMemory (hMainProc, &base, &size,
+ LOCK_VM_IN_RAM);
+ if (!NT_SUCCESS (status))
+ __seterrno_from_nt_status (status);
+ else
+ ret = 0;
+
+ pop_thread_privilege ();
+
+ return ret;
+}
+
/*
* Base implementation:
*
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 5a43df5..26ae8ff 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -10,6 +10,7 @@
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xc0000004)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS) 0xc0000023)
+#define STATUS_WORKING_SET_QUOTA ((NTSTATUS) 0xc00000a1L)
#define PDI_MODULES 0x01
#define PDI_HEAPS 0x04
#define LDRP_IMAGE_DLL 0x00000004
@@ -25,6 +26,9 @@
#define AT_ROUND_TO_PAGE 0x40000000
+#define LOCK_VM_IN_WSL 1
+#define LOCK_VM_IN_RAM 2
+
typedef ULONG KAFFINITY;
typedef enum _SYSTEM_INFORMATION_CLASS
@@ -480,6 +484,7 @@ extern "C"
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
PTOKEN_PRIMARY_GROUP, PTOKEN_DEFAULT_DACL,
PTOKEN_SOURCE);
+ NTSTATUS NTAPI NtLockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
NTSTATUS NTAPI NtMapViewOfSection (HANDLE, HANDLE, PVOID *, ULONG, ULONG,
PLARGE_INTEGER, PULONG, SECTION_INHERIT,
ULONG, ULONG);
@@ -503,6 +508,7 @@ extern "C"
FS_INFORMATION_CLASS);
NTSTATUS NTAPI NtSetSecurityObject (HANDLE, SECURITY_INFORMATION,
PSECURITY_DESCRIPTOR);
+ NTSTATUS NTAPI NtUnlockVirtualMemory (HANDLE, PVOID *, ULONG *, ULONG);
NTSTATUS NTAPI NtUnmapViewOfSection (HANDLE, PVOID);
VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
ULONG NTAPI RtlNtStatusToDosError (NTSTATUS);
diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc
index b50688f..7bd8cb6 100644
--- a/winsup/cygwin/sysconf.cc
+++ b/winsup/cygwin/sysconf.cc
@@ -123,6 +123,8 @@ sysconf (int in)
return RTSIG_MAX;
case _SC_TTY_NAME_MAX:
return TTY_NAME_MAX;
+ case _SC_MEMLOCK_RANGE:
+ return _POSIX_MEMLOCK_RANGE;
}
/* Invalid input or unimplemented sysconf name */
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 2cfffc2..955a620 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -60,7 +60,8 @@ static NO_COPY wincaps wincap_unknown = {
has_guid_volumes:false,
detect_win16_exe:true,
has_null_console_handler_routine:false,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:false
};
static NO_COPY wincaps wincap_95 = {
@@ -112,7 +113,8 @@ static NO_COPY wincaps wincap_95 = {
has_guid_volumes:false,
detect_win16_exe:true,
has_null_console_handler_routine:false,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:false
};
static NO_COPY wincaps wincap_95osr2 = {
@@ -164,7 +166,8 @@ static NO_COPY wincaps wincap_95osr2 = {
has_guid_volumes:false,
detect_win16_exe:true,
has_null_console_handler_routine:false,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:false
};
static NO_COPY wincaps wincap_98 = {
@@ -216,7 +219,8 @@ static NO_COPY wincaps wincap_98 = {
has_guid_volumes:false,
detect_win16_exe:true,
has_null_console_handler_routine:false,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:false
};
static NO_COPY wincaps wincap_98se = {
@@ -268,7 +272,8 @@ static NO_COPY wincaps wincap_98se = {
has_guid_volumes:false,
detect_win16_exe:true,
has_null_console_handler_routine:false,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:false
};
static NO_COPY wincaps wincap_me = {
@@ -320,7 +325,8 @@ static NO_COPY wincaps wincap_me = {
has_guid_volumes:false,
detect_win16_exe:true,
has_null_console_handler_routine:false,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:false
};
static NO_COPY wincaps wincap_nt3 = {
@@ -372,7 +378,8 @@ static NO_COPY wincaps wincap_nt3 = {
has_guid_volumes:false,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:true
};
static NO_COPY wincaps wincap_nt4 = {
@@ -424,7 +431,8 @@ static NO_COPY wincaps wincap_nt4 = {
has_guid_volumes:false,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:true
};
static NO_COPY wincaps wincap_nt4sp4 = {
@@ -476,7 +484,8 @@ static NO_COPY wincaps wincap_nt4sp4 = {
has_guid_volumes:false,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:true
};
static NO_COPY wincaps wincap_2000 = {
@@ -528,7 +537,8 @@ static NO_COPY wincaps wincap_2000 = {
has_guid_volumes:true,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:false
+ has_disk_ex_ioctls:false,
+ has_working_virtual_lock:true
};
static NO_COPY wincaps wincap_xp = {
@@ -580,7 +590,8 @@ static NO_COPY wincaps wincap_xp = {
has_guid_volumes:true,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:true
+ has_disk_ex_ioctls:true,
+ has_working_virtual_lock:true
};
static NO_COPY wincaps wincap_2003 = {
@@ -632,7 +643,8 @@ static NO_COPY wincaps wincap_2003 = {
has_guid_volumes:true,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:true
+ has_disk_ex_ioctls:true,
+ has_working_virtual_lock:true
};
static NO_COPY wincaps wincap_vista = {
@@ -684,7 +696,8 @@ static NO_COPY wincaps wincap_vista = {
has_guid_volumes:true,
detect_win16_exe:false,
has_null_console_handler_routine:true,
- has_disk_ex_ioctls:true
+ has_disk_ex_ioctls:true,
+ has_working_virtual_lock:true
};
wincapc wincap;
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index 7bc3d5c..02c1fa4 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -62,6 +62,7 @@ struct wincaps
unsigned detect_win16_exe : 1;
unsigned has_null_console_handler_routine : 1;
unsigned has_disk_ex_ioctls : 1;
+ unsigned has_working_virtual_lock : 1;
};
class wincapc
@@ -128,6 +129,7 @@ public:
bool IMPLEMENT (detect_win16_exe)
bool IMPLEMENT (has_null_console_handler_routine)
bool IMPLEMENT (has_disk_ex_ioctls)
+ bool IMPLEMENT (has_working_virtual_lock)
#undef IMPLEMENT
};