* 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.
This commit is contained in:
Corinna Vinschen 2005-10-18 18:51:33 +00:00
parent a92822b747
commit 1f5c3042d5
10 changed files with 160 additions and 14 deletions

View File

@ -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

View File

@ -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)

View File

@ -953,6 +953,8 @@ _modff = modff NOSIGFE
mount SIGFE
_mount = mount SIGFE
mprotect SIGFE
mlock SIGFE
munlock SIGFE
mrand48 NOSIGFE
msgctl SIGFE
msgget SIGFE

View File

@ -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

View File

@ -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
};

View File

@ -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:
*

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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
};