Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f0effe6

Browse files
committed
Better resolution for issue #11849: Ensure that free()d memory arenas are really released
on POSIX systems supporting anonymous memory mappings. Patch by Charles-François Natali.
1 parent 61ea8a0 commit f0effe6

5 files changed

Lines changed: 35 additions & 65 deletions

File tree

Misc/NEWS

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ What's New in Python 3.3 Alpha 1?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #11849: Ensure that free()d memory arenas are really released
14+
on POSIX systems supporting anonymous memory mappings. Patch by
15+
Charles-François Natali.
16+
1317
- Issue #13436: Fix a bogus error message when an AST object was passed
1418
an invalid integer value.
1519

@@ -260,10 +264,6 @@ Core and Builtins
260264
interpreter is shutting down; instead, these threads are now killed when
261265
they try to take the GIL.
262266

263-
- Issue #11849: Make it more likely for the system allocator to release
264-
free()d memory arenas on glibc-based systems. Patch by Charles-François
265-
Natali.
266-
267267
- Issue #9756: When calling a method descriptor or a slot wrapper descriptor,
268268
the check of the object type doesn't read the __class__ attribute anymore.
269269
Fix a crash if a class override its __class__ attribute (e.g. a proxy of the

Objects/obmalloc.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
#ifdef WITH_PYMALLOC
44

5-
#ifdef HAVE_MALLOPT_MMAP_THRESHOLD
6-
#include <malloc.h>
5+
#ifdef HAVE_MMAP
6+
#include <sys/mman.h>
7+
#ifdef MAP_ANONYMOUS
8+
#define ARENAS_USE_MMAP
9+
#endif
710
#endif
811

912
#ifdef WITH_VALGRIND
@@ -183,15 +186,15 @@ static int running_on_valgrind = -1;
183186
/*
184187
* The allocator sub-allocates <Big> blocks of memory (called arenas) aligned
185188
* on a page boundary. This is a reserved virtual address space for the
186-
* current process (obtained through a malloc call). In no way this means
187-
* that the memory arenas will be used entirely. A malloc(<Big>) is usually
188-
* an address range reservation for <Big> bytes, unless all pages within this
189-
* space are referenced subsequently. So malloc'ing big blocks and not using
190-
* them does not mean "wasting memory". It's an addressable range wastage...
189+
* current process (obtained through a malloc()/mmap() call). In no way this
190+
* means that the memory arenas will be used entirely. A malloc(<Big>) is
191+
* usually an address range reservation for <Big> bytes, unless all pages within
192+
* this space are referenced subsequently. So malloc'ing big blocks and not
193+
* using them does not mean "wasting memory". It's an addressable range
194+
* wastage...
191195
*
192-
* Therefore, allocating arenas with malloc is not optimal, because there is
193-
* some address space wastage, but this is the most portable way to request
194-
* memory from the system across various platforms.
196+
* Arenas are allocated with mmap() on systems supporting anonymous memory
197+
* mappings to reduce heap fragmentation.
195198
*/
196199
#define ARENA_SIZE (256 << 10) /* 256KB */
197200

@@ -556,11 +559,6 @@ new_arena(void)
556559
#if SIZEOF_SIZE_T <= SIZEOF_INT
557560
if (numarenas > PY_SIZE_MAX / sizeof(*arenas))
558561
return NULL; /* overflow */
559-
#endif
560-
#ifdef HAVE_MALLOPT_MMAP_THRESHOLD
561-
/* Ensure arenas are allocated by mmap to avoid heap fragmentation. */
562-
if (numarenas == INITIAL_ARENA_OBJECTS)
563-
mallopt(M_MMAP_THRESHOLD, ARENA_SIZE);
564562
#endif
565563
nbytes = numarenas * sizeof(*arenas);
566564
arenaobj = (struct arena_object *)realloc(arenas, nbytes);
@@ -594,7 +592,12 @@ new_arena(void)
594592
arenaobj = unused_arena_objects;
595593
unused_arena_objects = arenaobj->nextarena;
596594
assert(arenaobj->address == 0);
595+
#ifdef ARENAS_USE_MMAP
596+
arenaobj->address = (uptr)mmap(NULL, ARENA_SIZE, PROT_READ|PROT_WRITE,
597+
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
598+
#else
597599
arenaobj->address = (uptr)malloc(ARENA_SIZE);
600+
#endif
598601
if (arenaobj->address == 0) {
599602
/* The allocation failed: return NULL after putting the
600603
* arenaobj back.
@@ -1071,7 +1074,11 @@ PyObject_Free(void *p)
10711074
unused_arena_objects = ao;
10721075

10731076
/* Free the entire arena. */
1077+
#ifdef ARENAS_USE_MMAP
1078+
munmap((void *)ao->address, ARENA_SIZE);
1079+
#else
10741080
free((void *)ao->address);
1081+
#endif
10751082
ao->address = 0; /* mark unassociated */
10761083
--narenas_currently_allocated;
10771084

configure

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9401,8 +9401,8 @@ for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
94019401
getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
94029402
getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
94039403
if_nameindex \
9404-
initgroups kill killpg lchmod lchown lockf linkat lstat lutimes memrchr \
9405-
mbrtowc mkdirat mkfifo \
9404+
initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mmap \
9405+
memrchr mbrtowc mkdirat mkfifo \
94069406
mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
94079407
posix_fallocate posix_fadvise pread \
94089408
pthread_init pthread_kill putenv pwrite readlink readlinkat readv realpath renameat \
@@ -9784,34 +9784,6 @@ $as_echo "no" >&6; }
97849784
fi
97859785
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
97869786

9787-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mallopt can set malloc mmap threshold" >&5
9788-
$as_echo_n "checking whether mallopt can set malloc mmap threshold... " >&6; }
9789-
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
9790-
/* end confdefs.h. */
9791-
9792-
#include <malloc.h>
9793-
9794-
int
9795-
main ()
9796-
{
9797-
mallopt(M_MMAP_THRESHOLD, 256 * 1024)
9798-
;
9799-
return 0;
9800-
}
9801-
_ACEOF
9802-
if ac_fn_c_try_compile "$LINENO"; then :
9803-
9804-
$as_echo "#define HAVE_MALLOPT_MMAP_THRESHOLD 1" >>confdefs.h
9805-
9806-
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
9807-
$as_echo "yes" >&6; }
9808-
else
9809-
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
9810-
$as_echo "no" >&6; }
9811-
9812-
fi
9813-
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
9814-
98159787
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for broken unsetenv" >&5
98169788
$as_echo_n "checking for broken unsetenv... " >&6; }
98179789
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -14591,8 +14563,8 @@ esac
1459114563
1459214564
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
1459314565
# Files that config.status was made for.
14594-
config_files="$ac_config_files"
14595-
config_headers="$ac_config_headers"
14566+
config_files="`echo $ac_config_files`"
14567+
config_headers="`echo $ac_config_headers`"
1459614568
1459714569
_ACEOF
1459814570

configure.in

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2567,8 +2567,8 @@ AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
25672567
getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
25682568
getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
25692569
if_nameindex \
2570-
initgroups kill killpg lchmod lchown lockf linkat lstat lutimes memrchr \
2571-
mbrtowc mkdirat mkfifo \
2570+
initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mmap \
2571+
memrchr mbrtowc mkdirat mkfifo \
25722572
mkfifoat mknod mknodat mktime mremap nice openat pathconf pause pipe2 plock poll \
25732573
posix_fallocate posix_fadvise pread \
25742574
pthread_init pthread_kill putenv pwrite readlink readlinkat readv realpath renameat \
@@ -2679,15 +2679,6 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
26792679
[AC_MSG_RESULT(no)
26802680
])
26812681

2682-
AC_MSG_CHECKING(whether mallopt can set malloc mmap threshold)
2683-
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
2684-
#include <malloc.h>
2685-
]], [[mallopt(M_MMAP_THRESHOLD, 256 * 1024)]])],
2686-
[AC_DEFINE(HAVE_MALLOPT_MMAP_THRESHOLD, 1, Define if mallopt can set malloc mmap threshold.)
2687-
AC_MSG_RESULT(yes)],
2688-
[AC_MSG_RESULT(no)
2689-
])
2690-
26912682
AC_MSG_CHECKING(for broken unsetenv)
26922683
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
26932684
#include <stdlib.h>

pyconfig.h.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,6 @@
512512
/* Define this if you have the makedev macro. */
513513
#undef HAVE_MAKEDEV
514514

515-
/* Define if mallopt can set malloc mmap threshold. */
516-
#undef HAVE_MALLOPT_MMAP_THRESHOLD
517-
518515
/* Define to 1 if you have the `mbrtowc' function. */
519516
#undef HAVE_MBRTOWC
520517

@@ -545,6 +542,9 @@
545542
/* Define to 1 if you have the `mktime' function. */
546543
#undef HAVE_MKTIME
547544

545+
/* Define to 1 if you have the `mmap' function. */
546+
#undef HAVE_MMAP
547+
548548
/* Define to 1 if you have the `mremap' function. */
549549
#undef HAVE_MREMAP
550550

0 commit comments

Comments
 (0)