Commit 4cdd14ea authored by Eli Zaretskii's avatar Eli Zaretskii

Implement getrlimit and setrlimit for MS-Windows

* src/w32heap.c (getrlimit, setrlimit): New functions.
Include w32.h.
* src/emacs.c (main): Use 'rlim_t', not 'long', for values that
should be compatible with 'struct rlimit' members.

* nt/inc/sys/resource.h: New header file.

* nt/mingw-cfg.site (ac_cv_func_getrlimit, ac_cv_func_setrlimit):
Set to "yes".
parent 6cdd1c33
/* A limited emulation of sys/resource.h.
Copyright (C) 2016 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef INC_SYS_RESOURCE_H_
#define INC_SYS_RESOURCE_H_
/* We only support RLIMIT_STACK and RLIMIT_NOFILE for now. */
enum rlimit_resource {
RLIMIT_STACK = 0,
#define RLIMIT_STACK RLIMIT_STACK
RLIMIT_NOFILE = 1,
#define RLIMIT_NOFILE RLIMIT_NOFILE
RLIMIT_NLIMITS
#define RLIMIT_NLIMITS RLIMIT_NLIMITS
};
typedef enum rlimit_resource rlimit_resource_t;
/* We use a 64-bit data type because some values could potentially be
64-bit wide even in 32-bit builds. */
typedef long long rlim_t;
#define RLIMIT_INFINITY ((rlim_t) -1)
struct rlimit {
rlim_t rlim_cur; /* current soft limit */
rlim_t rlim_max; /* hard limit */
};
extern int getrlimit (rlimit_resource_t, struct rlimit *);
extern int setrlimit (rlimit_resource_t, const struct rlimit *);
#endif /* INC_SYS_RESOURCE_H_ */
......@@ -131,5 +131,7 @@ ac_cv_func_random=yes
gl_cv_func_svid_putenv=yes
# Implemented in w32heap.c
ac_cv_func_sbrk=yes
ac_cv_func_getrlimit=yes
ac_cv_func_setrlimit=yes
# GCC warnings that produce too much noise
gl_cv_warn_c__Wredundant_decls=no
......@@ -829,7 +829,7 @@ main (int argc, char **argv)
if (getrlimit (RLIMIT_STACK, &rlim) == 0
&& 0 <= rlim.rlim_cur && rlim.rlim_cur <= LONG_MAX)
{
long lim = rlim.rlim_cur;
rlim_t lim = rlim.rlim_cur;
/* Approximate the amount regex.c needs per unit of
re_max_failures, then add 33% to cover the size of the
......@@ -848,7 +848,7 @@ main (int argc, char **argv)
if (try_to_grow_stack)
{
long newlim = re_max_failures * ratio + extra;
rlim_t newlim = re_max_failures * ratio + extra;
/* Round the new limit to a page boundary; this is needed
for Darwin kernel 15.4.0 (see Bug#23622) and perhaps
......
......@@ -50,9 +50,11 @@
#include <errno.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include "w32common.h"
#include "w32heap.h"
#include "lisp.h"
#include "w32.h" /* for FD_SETSIZE */
/* We chose to leave those declarations here. They are used only in
this file. The RtlCreateHeap is available since XP. It is located
......@@ -317,6 +319,9 @@ init_heap (void)
cache_system_info ();
}
/* malloc, realloc, free. */
#undef malloc
#undef realloc
#undef free
......@@ -623,9 +628,12 @@ sbrk (ptrdiff_t increment)
return data_region_end;
}
#define MAX_BUFFER_SIZE (512 * 1024 * 1024)
/* MMAP allocation for buffers. */
#define MAX_BUFFER_SIZE (512 * 1024 * 1024)
void *
mmap_alloc (void **var, size_t nbytes)
{
......@@ -788,3 +796,78 @@ mmap_realloc (void **var, size_t nbytes)
/* Not enlarging, not shrinking by more than one page. */
return *var;
}
/* Emulation of getrlimit and setrlimit. */
int
getrlimit (rlimit_resource_t rltype, struct rlimit *rlp)
{
int retval = -1;
switch (rltype)
{
case RLIMIT_STACK:
{
MEMORY_BASIC_INFORMATION m;
/* Implementation note: Posix says that RLIMIT_STACK returns
information about the stack size for the main thread. The
implementation below returns the stack size for the calling
thread, so it's more like pthread_attr_getstacksize. But
Emacs clearly wants the latter, given how it uses the
results, so the implementation below is more future-proof,
if what's now the main thread will become some other thread
at some future point. */
if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
errno = EPERM;
else
{
rlp->rlim_cur = (DWORD_PTR) &m - (DWORD_PTR) m.AllocationBase;
rlp->rlim_max =
(DWORD_PTR) m.BaseAddress + m.RegionSize
- (DWORD_PTR) m.AllocationBase;
/* The last page is the guard page, so subtract that. */
rlp->rlim_cur -= getpagesize ();
rlp->rlim_max -= getpagesize ();
retval = 0;
}
}
break;
case RLIMIT_NOFILE:
/* Implementation note: The real value is returned by
_getmaxstdio. But our FD_SETSIZE is smaller, to cater to
Windows 9X, and process.c includes some logic that's based on
the assumption that the handle resource is inherited to child
processes. We want to avoid that logic, so we tell process.c
our current limit is already equal to FD_SETSIZE. */
rlp->rlim_cur = FD_SETSIZE;
rlp->rlim_max = 2048; /* see _setmaxstdio documentation */
retval = 0;
break;
default:
/* Note: we could return meaningful results for other RLIMIT_*
requests, but Emacs doesn't currently need that, so we just
punt for them. */
errno = ENOSYS;
break;
}
return retval;
}
int
setrlimit (rlimit_resource_t rltype, const struct rlimit *rlp)
{
switch (rltype)
{
case RLIMIT_STACK:
case RLIMIT_NOFILE:
/* We cannot modfy these limits, so we always fail. */
errno = EPERM;
break;
default:
errno = ENOSYS;
break;
}
return -1;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment