]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - manual/memory.texi
nptl/tst-cancel25 needs to be an internal test
[thirdparty/glibc.git] / manual / memory.texi
index e64dc8d9dc1785e293f04d7fdf70aef986cc6e91..b565dd69f2bff950f5d8d8017b642dae1706f371 100644 (file)
@@ -5,9 +5,9 @@
 @cindex storage allocation
 
 This chapter describes how processes manage and use memory in a system
-that uses the GNU C library.
+that uses @theglibc{}.
 
-The GNU C Library has several functions for dynamically allocating
+@Theglibc{} has several functions for dynamically allocating
 virtual memory in various ways.  They vary in generality and in
 efficiency.  The library also provides functions for controlling paging
 and allocation of real memory.
@@ -16,8 +16,9 @@ and allocation of real memory.
 @menu
 * Memory Concepts::             An introduction to concepts and terminology.
 * Memory Allocation::           Allocating storage for your program data
-* Locking Pages::               Preventing page faults
 * Resizing the Data Segment::   @code{brk}, @code{sbrk}
+* Memory Protection::           Controlling access to memory regions.
+* Locking Pages::               Preventing page faults
 @end menu
 
 Memory mapped I/O is not discussed in this chapter.  @xref{Memory-mapped I/O}.
@@ -31,7 +32,7 @@ One of the most basic resources a process has available to it is memory.
 There are a lot of different ways systems organize memory, but in a
 typical one, each process has one linear virtual address space, with
 addresses running from zero to some huge maximum.  It need not be
-contiguous; i.e.  not all of these addresses actually can be used to
+contiguous; i.e., not all of these addresses actually can be used to
 store data.
 
 The virtual memory is divided into pages (4 kilobytes is typical).
@@ -47,7 +48,7 @@ just a flag saying it is all zeroes.
 
 The same frame of real memory or backing store can back multiple virtual
 pages belonging to multiple processes.  This is normally the case, for
-example, with virtual memory occupied by GNU C library code.  The same
+example, with virtual memory occupied by @glibcadj{} code.  The same
 real memory frame containing the @code{printf} function backs a virtual
 memory page in each of the existing processes that has a @code{printf}
 call in its program.
@@ -100,7 +101,7 @@ Allocation and C}).
 @cindex constants
 
 Once that program begins to execute, it uses programmatic allocation to
-gain additional memory.  In a C program with the GNU C library, there
+gain additional memory.  In a C program with @theglibc{}, there
 are two kinds of programmatic allocation: automatic and dynamic.
 @xref{Memory Allocation and C}.
 
@@ -158,13 +159,16 @@ grows, but doesn't shrink when the stack shrinks.
 
 This section covers how ordinary programs manage storage for their data,
 including the famous @code{malloc} function and some fancier facilities
-special the GNU C library and GNU Compiler.
+special to @theglibc{} and GNU Compiler.
 
 @menu
 * Memory Allocation and C::     How to get different kinds of allocation in C.
+* The GNU Allocator::          An overview of the GNU @code{malloc}
+                               implementation.
 * Unconstrained Allocation::    The @code{malloc} facility allows fully general
                                 dynamic allocation.
 * Allocation Debugging::        Finding memory leaks and not freed memory.
+* Replacing malloc::            Using your own @code{malloc}-style allocator.
 * Obstacks::                    Obstacks are less general than malloc
                                 but more efficient and convenient.
 * Variable Size Automatic::     Allocation of variable-sized blocks
@@ -202,7 +206,7 @@ that varies.  In other C implementations, it must be a constant.
 @end itemize
 
 A third important kind of memory allocation, @dfn{dynamic allocation},
-is not supported by C variables but is available via GNU C library
+is not supported by C variables but is available via @glibcadj{}
 functions.
 @cindex dynamic memory allocation
 
@@ -234,8 +238,8 @@ as you want.
 Dynamic allocation is not supported by C variables; there is no storage
 class ``dynamic'', and there can never be a C variable whose value is
 stored in dynamically allocated space.  The only way to get dynamically
-allocated memory is via a system call (which is generally via a GNU C
-library function call), and the only way to refer to dynamically
+allocated memory is via a system call (which is generally via a @glibcadj{}
+function call), and the only way to refer to dynamically
 allocated space is through a pointer.  Because it is less convenient,
 and because the actual process of dynamic allocation requires more
 computation time, programmers generally use dynamic allocation only when
@@ -258,6 +262,48 @@ address of the space.  Then you can use the operators @samp{*} and
 @}
 @end smallexample
 
+@node The GNU Allocator
+@subsection The GNU Allocator
+@cindex gnu allocator
+
+The @code{malloc} implementation in @theglibc{} is derived from ptmalloc
+(pthreads malloc), which in turn is derived from dlmalloc (Doug Lea malloc).
+This malloc may allocate memory in two different ways depending on their size
+and certain parameters that may be controlled by users. The most common way is
+to allocate portions of memory (called chunks) from a large contiguous area of
+memory and manage these areas to optimize their use and reduce wastage in the
+form of unusable chunks. Traditionally the system heap was set up to be the one
+large memory area but the @glibcadj{} @code{malloc} implementation maintains
+multiple such areas to optimize their use in multi-threaded applications.  Each
+such area is internally referred to as an @dfn{arena}.
+
+As opposed to other versions, the @code{malloc} in @theglibc{} does not round
+up chunk sizes to powers of two, neither for large nor for small sizes.
+Neighboring chunks can be coalesced on a @code{free} no matter what their size
+is.  This makes the implementation suitable for all kinds of allocation
+patterns without generally incurring high memory waste through fragmentation.
+The presence of multiple arenas allows multiple threads to allocate
+memory simultaneously in separate arenas, thus improving performance.
+
+The other way of memory allocation is for very large blocks, i.e. much larger
+than a page. These requests are allocated with @code{mmap} (anonymous or via
+@file{/dev/zero}; @pxref{Memory-mapped I/O})). This has the great advantage
+that these chunks are returned to the system immediately when they are freed.
+Therefore, it cannot happen that a large chunk becomes ``locked'' in between
+smaller ones and even after calling @code{free} wastes memory.  The size
+threshold for @code{mmap} to be used is dynamic and gets adjusted according to
+allocation patterns of the program.  @code{mallopt} can be used to statically
+adjust the threshold using @code{M_MMAP_THRESHOLD} and the use of @code{mmap}
+can be disabled completely with @code{M_MMAP_MAX};
+@pxref{Malloc Tunable Parameters}.
+
+A more detailed technical description of the GNU Allocator is maintained in
+the @glibcadj{} wiki. See
+@uref{https://sourceware.org/glibc/wiki/MallocInternals}.
+
+It is possible to use your own custom @code{malloc} instead of the
+built-in allocator provided by @theglibc{}.  @xref{Replacing malloc}.
+
 @node Unconstrained Allocation
 @subsection Unconstrained Allocation
 @cindex unconstrained memory allocation
@@ -278,8 +324,6 @@ any time (or never).
                                 bigger or smaller.
 * Allocating Cleared Space::    Use @code{calloc} to allocate a
                                 block and clear it.
-* Efficiency and Malloc::       Efficiency considerations in use of
-                                these functions.
 * Aligned Memory Blocks::       Allocating specially aligned memory.
 * Malloc Tunable Parameters::   Use @code{mallopt} to adjust allocation
                                  parameters.
@@ -299,9 +343,245 @@ To allocate a block of memory, call @code{malloc}.  The prototype for
 this function is in @file{stdlib.h}.
 @pindex stdlib.h
 
-@comment malloc.h stdlib.h
-@comment ISO
 @deftypefun {void *} malloc (size_t @var{size})
+@standards{ISO, malloc.h}
+@standards{ISO, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c Malloc hooks and __morecore pointers, as well as such parameters as
+@c max_n_mmaps and max_mmapped_mem, are accessed without guards, so they
+@c could pose a thread safety issue; in order to not declare malloc
+@c MT-unsafe, it's modifying the hooks and parameters while multiple
+@c threads are active that is regarded as unsafe.  An arena's next field
+@c is initialized and never changed again, except for main_arena's,
+@c that's protected by list_lock; next_free is only modified while
+@c list_lock is held too.  All other data members of an arena, as well
+@c as the metadata of the memory areas assigned to it, are only modified
+@c while holding the arena's mutex (fastbin pointers use catomic ops
+@c because they may be modified by free without taking the arena's
+@c lock).  Some reassurance was needed for fastbins, for it wasn't clear
+@c how they were initialized.  It turns out they are always
+@c zero-initialized: main_arena's, for being static data, and other
+@c arena's, for being just-mmapped memory.
+
+@c Leaking file descriptors and memory in case of cancellation is
+@c unavoidable without disabling cancellation, but the lock situation is
+@c a bit more complicated: we don't have fallback arenas for malloc to
+@c be safe to call from within signal handlers.  Error-checking mutexes
+@c or trylock could enable us to try and use alternate arenas, even with
+@c -DPER_THREAD (enabled by default), but supporting interruption
+@c (cancellation or signal handling) while holding the arena list mutex
+@c would require more work; maybe blocking signals and disabling async
+@c cancellation while manipulating the arena lists?
+
+@c __libc_malloc @asulock @aculock @acsfd @acsmem
+@c  force_reg ok
+@c  *malloc_hook unguarded
+@c  arena_lock @asulock @aculock @acsfd @acsmem
+@c   mutex_lock @asulock @aculock
+@c   arena_get2 @asulock @aculock @acsfd @acsmem
+@c    get_free_list @asulock @aculock
+@c     mutex_lock (list_lock) dup @asulock @aculock
+@c     mutex_unlock (list_lock) dup @aculock
+@c     mutex_lock (arena lock) dup @asulock @aculock [returns locked]
+@c    __get_nprocs ext ok @acsfd
+@c    NARENAS_FROM_NCORES ok
+@c    catomic_compare_and_exchange_bool_acq ok
+@c    _int_new_arena ok @asulock @aculock @acsmem
+@c     new_heap ok @acsmem
+@c      mmap ok @acsmem
+@c      munmap ok @acsmem
+@c      mprotect ok
+@c     chunk2mem ok
+@c     set_head ok
+@c     tsd_setspecific dup ok
+@c     mutex_init ok
+@c     mutex_lock (just-created mutex) ok, returns locked
+@c     mutex_lock (list_lock) dup @asulock @aculock
+@c     atomic_write_barrier ok
+@c     mutex_unlock (list_lock) @aculock
+@c    catomic_decrement ok
+@c    reused_arena @asulock @aculock
+@c      reads&writes next_to_use and iterates over arena next without guards
+@c      those are harmless as long as we don't drop arenas from the
+@c      NEXT list, and we never do; when a thread terminates,
+@c      __malloc_arena_thread_freeres prepends the arena to the free_list
+@c      NEXT_FREE list, but NEXT is never modified, so it's safe!
+@c     mutex_trylock (arena lock) @asulock @aculock
+@c     mutex_lock (arena lock) dup @asulock @aculock
+@c     tsd_setspecific dup ok
+@c  _int_malloc @acsfd @acsmem
+@c   checked_request2size ok
+@c    REQUEST_OUT_OF_RANGE ok
+@c    request2size ok
+@c   get_max_fast ok
+@c   fastbin_index ok
+@c   fastbin ok
+@c   catomic_compare_and_exhange_val_acq ok
+@c   malloc_printerr dup @mtsenv
+@c     if we get to it, we're toast already, undefined behavior must have
+@c     been invoked before
+@c    libc_message @mtsenv [no leaks with cancellation disabled]
+@c     FATAL_PREPARE ok
+@c      pthread_setcancelstate disable ok
+@c     libc_secure_getenv @mtsenv
+@c      getenv @mtsenv
+@c     open_not_cancel_2 dup @acsfd
+@c     strchrnul ok
+@c     WRITEV_FOR_FATAL ok
+@c      writev ok
+@c     mmap ok @acsmem
+@c     munmap ok @acsmem
+@c     BEFORE_ABORT @acsfd
+@c      backtrace ok
+@c      write_not_cancel dup ok
+@c      backtrace_symbols_fd @aculock
+@c      open_not_cancel_2 dup @acsfd
+@c      read_not_cancel dup ok
+@c      close_not_cancel_no_status dup @acsfd
+@c     abort ok
+@c    itoa_word ok
+@c    abort ok
+@c   check_remalloced_chunk ok/disabled
+@c   chunk2mem dup ok
+@c   alloc_perturb ok
+@c   in_smallbin_range ok
+@c   smallbin_index ok
+@c   bin_at ok
+@c   last ok
+@c   malloc_consolidate ok
+@c    get_max_fast dup ok
+@c    clear_fastchunks ok
+@c    unsorted_chunks dup ok
+@c    fastbin dup ok
+@c    atomic_exchange_acq ok
+@c    check_inuse_chunk dup ok/disabled
+@c    chunk_at_offset dup ok
+@c    chunksize dup ok
+@c    inuse_bit_at_offset dup ok
+@c    unlink dup ok
+@c    clear_inuse_bit_at_offset dup ok
+@c    in_smallbin_range dup ok
+@c    set_head dup ok
+@c    malloc_init_state ok
+@c     bin_at dup ok
+@c     set_noncontiguous dup ok
+@c     set_max_fast dup ok
+@c     initial_top ok
+@c      unsorted_chunks dup ok
+@c    check_malloc_state ok/disabled
+@c   set_inuse_bit_at_offset ok
+@c   check_malloced_chunk ok/disabled
+@c   largebin_index ok
+@c   have_fastchunks ok
+@c   unsorted_chunks ok
+@c    bin_at ok
+@c   chunksize ok
+@c   chunk_at_offset ok
+@c   set_head ok
+@c   set_foot ok
+@c   mark_bin ok
+@c    idx2bit ok
+@c   first ok
+@c   unlink ok
+@c    malloc_printerr dup ok
+@c    in_smallbin_range dup ok
+@c   idx2block ok
+@c   idx2bit dup ok
+@c   next_bin ok
+@c   sysmalloc @acsfd @acsmem
+@c    MMAP @acsmem
+@c    set_head dup ok
+@c    check_chunk ok/disabled
+@c    chunk2mem dup ok
+@c    chunksize dup ok
+@c    chunk_at_offset dup ok
+@c    heap_for_ptr ok
+@c    grow_heap ok
+@c     mprotect ok
+@c    set_head dup ok
+@c    new_heap @acsmem
+@c     MMAP dup @acsmem
+@c     munmap @acsmem
+@c    top ok
+@c    set_foot dup ok
+@c    contiguous ok
+@c    MORECORE ok
+@c     *__morecore ok unguarded
+@c      __default_morecore
+@c       sbrk ok
+@c    force_reg dup ok
+@c    *__after_morecore_hook unguarded
+@c    set_noncontiguous ok
+@c    malloc_printerr dup ok
+@c    _int_free (have_lock) @acsfd @acsmem [@asulock @aculock]
+@c     chunksize dup ok
+@c     mutex_unlock dup @aculock/!have_lock
+@c     malloc_printerr dup ok
+@c     check_inuse_chunk ok/disabled
+@c     chunk_at_offset dup ok
+@c     mutex_lock dup @asulock @aculock/@have_lock
+@c     chunk2mem dup ok
+@c     free_perturb ok
+@c     set_fastchunks ok
+@c      catomic_and ok
+@c     fastbin_index dup ok
+@c     fastbin dup ok
+@c     catomic_compare_and_exchange_val_rel ok
+@c     chunk_is_mmapped ok
+@c     contiguous dup ok
+@c     prev_inuse ok
+@c     unlink dup ok
+@c     inuse_bit_at_offset dup ok
+@c     clear_inuse_bit_at_offset ok
+@c     unsorted_chunks dup ok
+@c     in_smallbin_range dup ok
+@c     set_head dup ok
+@c     set_foot dup ok
+@c     check_free_chunk ok/disabled
+@c     check_chunk dup ok/disabled
+@c     have_fastchunks dup ok
+@c     malloc_consolidate dup ok
+@c     systrim ok
+@c      MORECORE dup ok
+@c      *__after_morecore_hook dup unguarded
+@c      set_head dup ok
+@c      check_malloc_state ok/disabled
+@c     top dup ok
+@c     heap_for_ptr dup ok
+@c     heap_trim @acsfd @acsmem
+@c      top dup ok
+@c      chunk_at_offset dup ok
+@c      prev_chunk ok
+@c      chunksize dup ok
+@c      prev_inuse dup ok
+@c      delete_heap @acsmem
+@c       munmap dup @acsmem
+@c      unlink dup ok
+@c      set_head dup ok
+@c      shrink_heap @acsfd
+@c       check_may_shrink_heap @acsfd
+@c        open_not_cancel_2 @acsfd
+@c        read_not_cancel ok
+@c        close_not_cancel_no_status @acsfd
+@c       MMAP dup ok
+@c       madvise ok
+@c     munmap_chunk @acsmem
+@c      chunksize dup ok
+@c      chunk_is_mmapped dup ok
+@c      chunk2mem dup ok
+@c      malloc_printerr dup ok
+@c      munmap dup @acsmem
+@c    check_malloc_state ok/disabled
+@c  arena_get_retry @asulock @aculock @acsfd @acsmem
+@c   mutex_unlock dup @aculock
+@c   mutex_lock dup @asulock @aculock
+@c   arena_get2 dup @asulock @aculock @acsfd @acsmem
+@c  mutex_unlock @aculock
+@c  mem2chunk ok
+@c  chunk_is_mmapped ok
+@c  arena_for_chunk ok
+@c   chunk_non_main_arena ok
+@c   heap_for_ptr ok
 This function returns a pointer to a newly allocated block @var{size}
 bytes long, or a null pointer if the block could not be allocated.
 @end deftypefun
@@ -311,7 +591,7 @@ The contents of the block are undefined; you must initialize it yourself
 Normally you would cast the value as a pointer to the kind of object
 that you want to store in the block.  Here we show an example of doing
 so, and of initializing the space with zeros using the library function
-@code{memset} (@pxref{Copying and Concatenation}):
+@code{memset} (@pxref{Copying Strings and Arrays}):
 
 @smallexample
 struct foo *ptr;
@@ -355,7 +635,7 @@ it is:
 void *
 xmalloc (size_t size)
 @{
-  register void *value = malloc (size);
+  void *value = malloc (size);
   if (value == 0)
     fatal ("virtual memory exhausted");
   return value;
@@ -371,7 +651,7 @@ a newly allocated null-terminated string:
 char *
 savestring (const char *ptr, size_t len)
 @{
-  register char *value = (char *) xmalloc (len + 1);
+  char *value = (char *) xmalloc (len + 1);
   value[len] = '\0';
   return (char *) memcpy (value, ptr, len);
 @}
@@ -379,11 +659,11 @@ savestring (const char *ptr, size_t len)
 @end smallexample
 
 The block that @code{malloc} gives you is guaranteed to be aligned so
-that it can hold any type of data.  In the GNU system, the address is
-always a multiple of eight on most systems, and a multiple of 16 on
+that it can hold any type of data.  On @gnusystems{}, the address is
+always a multiple of eight on 32-bit systems, and a multiple of 16 on
 64-bit systems.  Only rarely is any higher boundary (such as a page
-boundary) necessary; for those cases, use @code{memalign},
-@code{posix_memalign} or @code{valloc} (@pxref{Aligned Memory Blocks}).
+boundary) necessary; for those cases, use @code{aligned_alloc} or
+@code{posix_memalign} (@pxref{Aligned Memory Blocks}).
 
 Note that the memory located after the end of the block is likely to be
 in use for something else; perhaps a block already allocated by another
@@ -404,20 +684,28 @@ function @code{free} to make the block available to be allocated again.
 The prototype for this function is in @file{stdlib.h}.
 @pindex stdlib.h
 
-@comment malloc.h stdlib.h
-@comment ISO
 @deftypefun void free (void *@var{ptr})
+@standards{ISO, malloc.h}
+@standards{ISO, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c __libc_free @asulock @aculock @acsfd @acsmem
+@c   releasing memory into fastbins modifies the arena without taking
+@c   its mutex, but catomic operations ensure safety.  If two (or more)
+@c   threads are running malloc and have their own arenas locked when
+@c   each gets a signal whose handler free()s large (non-fastbin-able)
+@c   blocks from each other's arena, we deadlock; this is a more general
+@c   case of @asulock.
+@c  *__free_hook unguarded
+@c  mem2chunk ok
+@c  chunk_is_mmapped ok, chunk bits not modified after allocation
+@c  chunksize ok
+@c  munmap_chunk dup @acsmem
+@c  arena_for_chunk dup ok
+@c  _int_free (!have_lock) dup @asulock @aculock @acsfd @acsmem
 The @code{free} function deallocates the block of memory pointed at
 by @var{ptr}.
 @end deftypefun
 
-@comment stdlib.h
-@comment Sun
-@deftypefun void cfree (void *@var{ptr})
-This function does the same thing as @code{free}.  It's provided for
-backward compatibility with SunOS; you should use @code{free} instead.
-@end deftypefun
-
 Freeing a block alters the contents of the block.  @strong{Do not expect to
 find any data (such as a pointer to the next block in a chain of blocks) in
 the block after freeing it.}  Copy whatever you need out of the block before
@@ -464,13 +752,55 @@ be a buffer that you use to hold a line being read from a file; no matter
 how long you make the buffer initially, you may encounter a line that is
 longer.
 
-You can make the block longer by calling @code{realloc}.  This function
-is declared in @file{stdlib.h}.
+You can make the block longer by calling @code{realloc} or
+@code{reallocarray}.  These functions are declared in @file{stdlib.h}.
 @pindex stdlib.h
 
-@comment malloc.h stdlib.h
-@comment ISO
 @deftypefun {void *} realloc (void *@var{ptr}, size_t @var{newsize})
+@standards{ISO, malloc.h}
+@standards{ISO, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c It may call the implementations of malloc and free, so all of their
+@c issues arise, plus the realloc hook, also accessed without guards.
+
+@c __libc_realloc @asulock @aculock @acsfd @acsmem
+@c  *__realloc_hook unguarded
+@c  __libc_free dup @asulock @aculock @acsfd @acsmem
+@c  __libc_malloc dup @asulock @aculock @acsfd @acsmem
+@c  mem2chunk dup ok
+@c  chunksize dup ok
+@c  malloc_printerr dup ok
+@c  checked_request2size dup ok
+@c  chunk_is_mmapped dup ok
+@c  mremap_chunk
+@c   chunksize dup ok
+@c   __mremap ok
+@c   set_head dup ok
+@c  MALLOC_COPY ok
+@c   memcpy ok
+@c  munmap_chunk dup @acsmem
+@c  arena_for_chunk dup ok
+@c  mutex_lock (arena mutex) dup @asulock @aculock
+@c  _int_realloc @acsfd @acsmem
+@c   malloc_printerr dup ok
+@c   check_inuse_chunk dup ok/disabled
+@c   chunk_at_offset dup ok
+@c   chunksize dup ok
+@c   set_head_size dup ok
+@c   chunk_at_offset dup ok
+@c   set_head dup ok
+@c   chunk2mem dup ok
+@c   inuse dup ok
+@c   unlink dup ok
+@c   _int_malloc dup @acsfd @acsmem
+@c   mem2chunk dup ok
+@c   MALLOC_COPY dup ok
+@c   _int_free (have_lock) dup @acsfd @acsmem
+@c   set_inuse_bit_at_offset dup ok
+@c   set_head dup ok
+@c  mutex_unlock (arena mutex) dup @aculock
+@c  _int_free (!have_lock) dup @asulock @aculock @acsfd @acsmem
+
 The @code{realloc} function changes the size of the block whose address is
 @var{ptr} to be @var{newsize}.
 
@@ -487,9 +817,29 @@ behavior, and will probably crash when @code{realloc} is passed a null
 pointer.
 @end deftypefun
 
-Like @code{malloc}, @code{realloc} may return a null pointer if no
-memory space is available to make the block bigger.  When this happens,
-the original block is untouched; it has not been modified or relocated.
+@deftypefun {void *} reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+@standards{BSD, malloc.h}
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+
+The @code{reallocarray} function changes the size of the block whose address
+is @var{ptr} to be long enough to contain a vector of @var{nmemb} elements,
+each of size @var{size}.  It is equivalent to @samp{realloc (@var{ptr},
+@var{nmemb} * @var{size})}, except that @code{reallocarray} fails safely if
+the multiplication overflows, by setting @code{errno} to @code{ENOMEM},
+returning a null pointer, and leaving the original block unchanged.
+
+@code{reallocarray} should be used instead of @code{realloc} when the new size
+of the allocated block is the result of a multiplication that might overflow.
+
+@strong{Portability Note:} This function is not part of any standard.  It was
+first introduced in OpenBSD 5.6.
+@end deftypefun
+
+Like @code{malloc}, @code{realloc} and @code{reallocarray} may return a null
+pointer if no memory space is available to make the block bigger.  When this
+happens, the original block is untouched; it has not been modified or
+relocated.
 
 In most cases it makes no difference what happens to the original block
 when @code{realloc} fails, because the application program cannot continue
@@ -502,23 +852,24 @@ as @code{xmalloc} does for @code{malloc}:
 void *
 xrealloc (void *ptr, size_t size)
 @{
-  register void *value = realloc (ptr, size);
+  void *value = realloc (ptr, size);
   if (value == 0)
     fatal ("Virtual memory exhausted");
   return value;
 @}
 @end smallexample
 
-You can also use @code{realloc} to make a block smaller.  The reason you
-would do this is to avoid tying up a lot of memory space when only a little
-is needed.
+You can also use @code{realloc} or @code{reallocarray} to make a block
+smaller.  The reason you would do this is to avoid tying up a lot of memory
+space when only a little is needed.
 @comment The following is no longer true with the new malloc.
 @comment But it seems wise to keep the warning for other implementations.
 In several allocation implementations, making a block smaller sometimes
 necessitates copying it, so it can fail if no other space is available.
 
-If the new size you specify is the same as the old size, @code{realloc}
-is guaranteed to change nothing and return the same address that you gave.
+If the new size you specify is the same as the old size, @code{realloc} and
+@code{reallocarray} are guaranteed to change nothing and return the same
+address that you gave.
 
 @node Allocating Cleared Space
 @subsubsection Allocating Cleared Space
@@ -527,9 +878,27 @@ The function @code{calloc} allocates memory and clears it to zero.  It
 is declared in @file{stdlib.h}.
 @pindex stdlib.h
 
-@comment malloc.h stdlib.h
-@comment ISO
 @deftypefun {void *} calloc (size_t @var{count}, size_t @var{eltsize})
+@standards{ISO, malloc.h}
+@standards{ISO, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c Same caveats as malloc.
+
+@c __libc_calloc @asulock @aculock @acsfd @acsmem
+@c  *__malloc_hook dup unguarded
+@c  memset dup ok
+@c  arena_get @asulock @aculock @acsfd @acsmem
+@c   arena_lock dup @asulock @aculock @acsfd @acsmem
+@c  top dup ok
+@c  chunksize dup ok
+@c  heap_for_ptr dup ok
+@c  _int_malloc dup @acsfd @acsmem
+@c  arena_get_retry dup @asulock @aculock @acsfd @acsmem
+@c  mutex_unlock dup @aculock
+@c  mem2chunk dup ok
+@c  chunk_is_mmapped dup ok
+@c  MALLOC_ZERO ok
+@c   memset dup ok
 This function allocates a block long enough to contain a vector of
 @var{count} elements, each of size @var{eltsize}.  Its contents are
 cleared to zero before @code{calloc} returns.
@@ -554,59 +923,6 @@ But in general, it is not guaranteed that @code{calloc} calls
 @code{malloc}/@code{realloc}/@code{free} outside the C library, it
 should always define @code{calloc}, too.
 
-@node Efficiency and Malloc
-@subsubsection Efficiency Considerations for @code{malloc}
-@cindex efficiency and @code{malloc}
-
-
-
-
-@ignore
-
-@c No longer true, see below instead.
-To make the best use of @code{malloc}, it helps to know that the GNU
-version of @code{malloc} always dispenses small amounts of memory in
-blocks whose sizes are powers of two.  It keeps separate pools for each
-power of two.  This holds for sizes up to a page size.  Therefore, if
-you are free to choose the size of a small block in order to make
-@code{malloc} more efficient, make it a power of two.
-@c !!! xref getpagesize
-
-Once a page is split up for a particular block size, it can't be reused
-for another size unless all the blocks in it are freed.  In many
-programs, this is unlikely to happen.  Thus, you can sometimes make a
-program use memory more efficiently by using blocks of the same size for
-many different purposes.
-
-When you ask for memory blocks of a page or larger, @code{malloc} uses a
-different strategy; it rounds the size up to a multiple of a page, and
-it can coalesce and split blocks as needed.
-
-The reason for the two strategies is that it is important to allocate
-and free small blocks as fast as possible, but speed is less important
-for a large block since the program normally spends a fair amount of
-time using it.  Also, large blocks are normally fewer in number.
-Therefore, for large blocks, it makes sense to use a method which takes
-more time to minimize the wasted space.
-
-@end ignore
-
-As opposed to other versions, the @code{malloc} in the GNU C Library
-does not round up block sizes to powers of two, neither for large nor
-for small sizes.  Neighboring chunks can be coalesced on a @code{free}
-no matter what their size is.  This makes the implementation suitable
-for all kinds of allocation patterns without generally incurring high
-memory waste through fragmentation.
-
-Very large blocks (much larger than a page) are allocated with
-@code{mmap} (anonymous or via @code{/dev/zero}) by this implementation.
-This has the great advantage that these chunks are returned to the
-system immediately when they are freed.  Therefore, it cannot happen
-that a large chunk becomes ``locked'' in between smaller ones and even
-after calling @code{free} wastes memory.  The size threshold for
-@code{mmap} to be used can be adjusted with @code{mallopt}.  The use of
-@code{mmap} can also be disabled completely.
-
 @node Aligned Memory Blocks
 @subsubsection Allocating Aligned Memory Blocks
 
@@ -614,30 +930,89 @@ after calling @code{free} wastes memory.  The size threshold for
 @cindex alignment (with @code{malloc})
 @pindex stdlib.h
 The address of a block returned by @code{malloc} or @code{realloc} in
-the GNU system is always a multiple of eight (or sixteen on 64-bit
+@gnusystems{} is always a multiple of eight (or sixteen on 64-bit
 systems).  If you need a block whose address is a multiple of a higher
-power of two than that, use @code{memalign}, @code{posix_memalign}, or
-@code{valloc}.  @code{memalign} is declared in @file{malloc.h} and
-@code{posix_memalign} is declared in @file{stdlib.h}.
+power of two than that, use @code{aligned_alloc} or @code{posix_memalign}.
+@code{aligned_alloc} and @code{posix_memalign} are declared in
+@file{stdlib.h}.
 
-With the GNU library, you can use @code{free} to free the blocks that
-@code{memalign}, @code{posix_memalign}, and @code{valloc} return.  That
-does not work in BSD, however---BSD does not provide any way to free
-such blocks.
+@deftypefun {void *} aligned_alloc (size_t @var{alignment}, size_t @var{size})
+@standards{???, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c Alias to memalign.
+The @code{aligned_alloc} function allocates a block of @var{size} bytes whose
+address is a multiple of @var{alignment}.  The @var{alignment} must be a
+power of two and @var{size} must be a multiple of @var{alignment}.
+
+The @code{aligned_alloc} function returns a null pointer on error and sets
+@code{errno} to one of the following values:
+
+@table @code
+@item ENOMEM
+There was insufficient memory available to satisfy the request.
+
+@item EINVAL
+@var{alignment} is not a power of two.
+
+This function was introduced in @w{ISO C11} and hence may have better
+portability to modern non-POSIX systems than @code{posix_memalign}.
+@end table
+
+@end deftypefun
 
-@comment malloc.h
-@comment BSD
 @deftypefun {void *} memalign (size_t @var{boundary}, size_t @var{size})
+@standards{BSD, malloc.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c Same issues as malloc.  The padding bytes are safely freed in
+@c _int_memalign, with the arena still locked.
+
+@c __libc_memalign @asulock @aculock @acsfd @acsmem
+@c  *__memalign_hook dup unguarded
+@c  __libc_malloc dup @asulock @aculock @acsfd @acsmem
+@c  arena_get dup @asulock @aculock @acsfd @acsmem
+@c  _int_memalign @acsfd @acsmem
+@c   _int_malloc dup @acsfd @acsmem
+@c   checked_request2size dup ok
+@c   mem2chunk dup ok
+@c   chunksize dup ok
+@c   chunk_is_mmapped dup ok
+@c   set_head dup ok
+@c   chunk2mem dup ok
+@c   set_inuse_bit_at_offset dup ok
+@c   set_head_size dup ok
+@c   _int_free (have_lock) dup @acsfd @acsmem
+@c   chunk_at_offset dup ok
+@c   check_inuse_chunk dup ok
+@c  arena_get_retry dup @asulock @aculock @acsfd @acsmem
+@c  mutex_unlock dup @aculock
 The @code{memalign} function allocates a block of @var{size} bytes whose
 address is a multiple of @var{boundary}.  The @var{boundary} must be a
 power of two!  The function @code{memalign} works by allocating a
 somewhat larger block, and then returning an address within the block
 that is on the specified boundary.
+
+The @code{memalign} function returns a null pointer on error and sets
+@code{errno} to one of the following values:
+
+@table @code
+@item ENOMEM
+There was insufficient memory available to satisfy the request.
+
+@item EINVAL
+@var{boundary} is not a power of two.
+
+@end table
+
+The @code{memalign} function is obsolete and @code{aligned_alloc} or
+@code{posix_memalign} should be used instead.
 @end deftypefun
 
-@comment stdlib.h
-@comment POSIX
 @deftypefun int posix_memalign (void **@var{memptr}, size_t @var{alignment}, size_t @var{size})
+@standards{POSIX, stdlib.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
+@c Calls memalign unless the requirements are not met (powerof2 macro is
+@c safe given an automatic variable as an argument) or there's a
+@c memalign hook (accessed unguarded, but safely).
 The @code{posix_memalign} function is similar to the @code{memalign}
 function in that it returns a buffer of @var{size} bytes aligned to a
 multiple of @var{alignment}.  But it adds one requirement to the
@@ -647,15 +1022,51 @@ parameter @var{alignment}: the value must be a power of two multiple of
 If the function succeeds in allocation memory a pointer to the allocated
 memory is returned in @code{*@var{memptr}} and the return value is zero.
 Otherwise the function returns an error value indicating the problem.
+The possible error values returned are:
 
-This function was introduced in POSIX 1003.1d.
+@table @code
+@item ENOMEM
+There was insufficient memory available to satisfy the request.
+
+@item EINVAL
+@var{alignment} is not a power of two multiple of @code{sizeof (void *)}.
+
+@end table
+
+This function was introduced in POSIX 1003.1d.  Although this function is
+superseded by @code{aligned_alloc}, it is more portable to older POSIX
+systems that do not support @w{ISO C11}.
 @end deftypefun
 
-@comment malloc.h stdlib.h
-@comment BSD
 @deftypefun {void *} valloc (size_t @var{size})
+@standards{BSD, malloc.h}
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtunsafe{@mtuinit{}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{} @acsfd{} @acsmem{}}}
+@c __libc_valloc @mtuinit @asuinit @asulock @aculock @acsfd @acsmem
+@c  ptmalloc_init (once) @mtsenv @asulock @aculock @acsfd @acsmem
+@c   _dl_addr @asucorrupt? @aculock
+@c    __rtld_lock_lock_recursive (dl_load_lock) @asucorrupt? @aculock
+@c    _dl_find_dso_for_object ok, iterates over dl_ns and its _ns_loaded objs
+@c      the ok above assumes no partial updates on dl_ns and _ns_loaded
+@c      that could confuse a _dl_addr call in a signal handler
+@c     _dl_addr_inside_object ok
+@c    determine_info ok
+@c    __rtld_lock_unlock_recursive (dl_load_lock) @aculock
+@c   *_environ @mtsenv
+@c   next_env_entry ok
+@c   strcspn dup ok
+@c   __libc_mallopt dup @mtasuconst:mallopt [setting mp_]
+@c   *__malloc_initialize_hook unguarded, ok
+@c  *__memalign_hook dup ok, unguarded
+@c  arena_get dup @asulock @aculock @acsfd @acsmem
+@c  _int_valloc @acsfd @acsmem
+@c   malloc_consolidate dup ok
+@c   _int_memalign dup @acsfd @acsmem
+@c  arena_get_retry dup @asulock @aculock @acsfd @acsmem
+@c  _int_memalign dup @acsfd @acsmem
+@c  mutex_unlock dup @aculock
 Using @code{valloc} is like using @code{memalign} and passing the page size
-as the value of the second argument.  It is implemented like this:
+as the value of the first argument.  It is implemented like this:
 
 @smallexample
 void *
@@ -667,6 +1078,9 @@ valloc (size_t size)
 
 @ref{Query Memory Parameters} for more information about the memory
 subsystem.
+
+The @code{valloc} function is obsolete and @code{aligned_alloc} or
+@code{posix_memalign} should be used instead.
 @end deftypefun
 
 @node Malloc Tunable Parameters
@@ -678,30 +1092,105 @@ interface, defined in @file{malloc.h}.
 @pindex malloc.h
 
 @deftypefun int mallopt (int @var{param}, int @var{value})
+@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasuconst{:mallopt}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{}}}
+@c __libc_mallopt @mtuinit @mtasuconst:mallopt @asuinit @asulock @aculock
+@c  ptmalloc_init (once) dup @mtsenv @asulock @aculock @acsfd @acsmem
+@c  mutex_lock (main_arena->mutex) @asulock @aculock
+@c  malloc_consolidate dup ok
+@c  set_max_fast ok
+@c  mutex_unlock dup @aculock
+
 When calling @code{mallopt}, the @var{param} argument specifies the
 parameter to be set, and @var{value} the new value to be set.  Possible
 choices for @var{param}, as defined in @file{malloc.h}, are:
 
-@table @code
-@item M_TRIM_THRESHOLD
-This is the minimum size (in bytes) of the top-most, releasable chunk
-that will cause @code{sbrk} to be called with a negative argument in
-order to return memory to the system.
-@item M_TOP_PAD
-This parameter determines the amount of extra memory to obtain from the
-system when a call to @code{sbrk} is required.  It also specifies the
-number of bytes to retain when shrinking the heap by calling @code{sbrk}
-with a negative argument.  This provides the necessary hysteresis in
-heap size such that excessive amounts of system calls can be avoided.
+@vtable @code
+@item M_MMAP_MAX
+The maximum number of chunks to allocate with @code{mmap}.  Setting this
+to zero disables all use of @code{mmap}.
+
+The default value of this parameter is @code{65536}.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_MMAP_MAX_} to the desired value.
+
 @item M_MMAP_THRESHOLD
 All chunks larger than this value are allocated outside the normal
 heap, using the @code{mmap} system call.  This way it is guaranteed
 that the memory for these chunks can be returned to the system on
-@code{free}.
-@item M_MMAP_MAX
-The maximum number of chunks to allocate with @code{mmap}.  Setting this
-to zero disables all use of @code{mmap}.
-@end table
+@code{free}.  Note that requests smaller than this threshold might still
+be allocated via @code{mmap}.
+
+If this parameter is not set, the default value is set as 128 KiB and the
+threshold is adjusted dynamically to suit the allocation patterns of the
+program. If the parameter is set, the dynamic adjustment is disabled and the
+value is set statically to the input value.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_MMAP_THRESHOLD_} to the desired value.
+@comment TODO: @item M_MXFAST
+
+@item M_PERTURB
+If non-zero, memory blocks are filled with values depending on some
+low order bits of this parameter when they are allocated (except when
+allocated by @code{calloc}) and freed.  This can be used to debug the
+use of uninitialized or freed heap memory.  Note that this option does not
+guarantee that the freed block will have any specific values.  It only
+guarantees that the content the block had before it was freed will be
+overwritten.
+
+The default value of this parameter is @code{0}.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_MMAP_PERTURB_} to the desired value.
+
+@item M_TOP_PAD
+This parameter determines the amount of extra memory to obtain from the system
+when an arena needs to be extended.  It also specifies the number of bytes to
+retain when shrinking an arena.  This provides the necessary hysteresis in heap
+size such that excessive amounts of system calls can be avoided.
+
+The default value of this parameter is @code{0}.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_TOP_PAD_} to the desired value.
+
+@item M_TRIM_THRESHOLD
+This is the minimum size (in bytes) of the top-most, releasable chunk
+that will trigger a system call in order to return memory to the system.
+
+If this parameter is not set, the default value is set as 128 KiB and the
+threshold is adjusted dynamically to suit the allocation patterns of the
+program. If the parameter is set, the dynamic adjustment is disabled and the
+value is set statically to the provided input.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_TRIM_THRESHOLD_} to the desired value.
+
+@item M_ARENA_TEST
+This parameter specifies the number of arenas that can be created before the
+test on the limit to the number of arenas is conducted. The value is ignored if
+@code{M_ARENA_MAX} is set.
+
+The default value of this parameter is 2 on 32-bit systems and 8 on 64-bit
+systems.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_ARENA_TEST} to the desired value.
+
+@item M_ARENA_MAX
+This parameter sets the number of arenas to use regardless of the number of
+cores in the system.
+
+The default value of this tunable is @code{0}, meaning that the limit on the
+number of arenas is determined by the number of CPU cores online. For 32-bit
+systems the limit is twice the number of cores online and on 64-bit systems, it
+is eight times the number of cores online.  Note that the default value is not
+derived from the default value of M_ARENA_TEST and is computed independently.
+
+This parameter can also be set for the process at startup by setting the
+environment variable @env{MALLOC_ARENA_MAX} to the desired value.
+@end vtable
 
 @end deftypefun
 
@@ -716,9 +1205,19 @@ using the @code{mcheck} function.  This function is a GNU extension,
 declared in @file{mcheck.h}.
 @pindex mcheck.h
 
-@comment mcheck.h
-@comment GNU
 @deftypefun int mcheck (void (*@var{abortfn}) (enum mcheck_status @var{status}))
+@standards{GNU, mcheck.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:mcheck} @mtasuconst{:malloc_hooks}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}}
+@c The hooks must be set up before malloc is first used, which sort of
+@c implies @mtuinit/@asuinit but since the function is a no-op if malloc
+@c was already used, that doesn't pose any safety issues.  The actual
+@c problem is with the hooks, designed for single-threaded
+@c fully-synchronous operation: they manage an unguarded linked list of
+@c allocated blocks, and get temporarily overwritten before calling the
+@c allocation functions recursively while holding the old hooks.  There
+@c are no guards for thread safety, and inconsistent hooks may be found
+@c within signal handlers or left behind in case of cancellation.
+
 Calling @code{mcheck} tells @code{malloc} to perform occasional
 consistency checks.  These will catch things such as writing
 past the end of a block that was allocated with @code{malloc}.
@@ -751,7 +1250,7 @@ End with a line saying just "end".
 >call mcheck(0)
 >continue
 >end
-(gdb) ...
+(gdb) @dots{}
 @end smallexample
 
 This will however only work if no initialization function of any object
@@ -761,6 +1260,18 @@ must be called before the first such function.
 @end deftypefun
 
 @deftypefun {enum mcheck_status} mprobe (void *@var{pointer})
+@safety{@prelim{}@mtunsafe{@mtasurace{:mcheck} @mtasuconst{:malloc_hooks}}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{}}}
+@c The linked list of headers may be modified concurrently by other
+@c threads, and it may find a partial update if called from a signal
+@c handler.  It's mostly read only, so cancelling it might be safe, but
+@c it will modify global state that, if cancellation hits at just the
+@c right spot, may be left behind inconsistent.  This path is only taken
+@c if checkhdr finds an inconsistency.  If the inconsistency could only
+@c occur because of earlier undefined behavior, that wouldn't be an
+@c additional safety issue problem, but because of the other concurrency
+@c issues in the mcheck hooks, the apparent inconsistency could be the
+@c result of mcheck's own internal data race.  So, AC-Unsafe it is.
+
 The @code{mprobe} function lets you explicitly check for inconsistencies
 in a particular allocated block.  You must have already called
 @code{mcheck} at the beginning of the program, to do its occasional
@@ -797,17 +1308,15 @@ The block was already freed.
 
 Another possibility to check for and guard against bugs in the use of
 @code{malloc}, @code{realloc} and @code{free} is to set the environment
-variable @code{MALLOC_CHECK_}.  When @code{MALLOC_CHECK_} is set, a
-special (less efficient) implementation is used which is designed to be
-tolerant against simple errors, such as double calls of @code{free} with
-the same argument, or overruns of a single byte (off-by-one bugs).  Not
-all such errors can be protected against, however, and memory leaks can
-result.  If @code{MALLOC_CHECK_} is set to @code{0}, any detected heap
-corruption is silently ignored; if set to @code{1}, a diagnostic is
-printed on @code{stderr}; if set to @code{2}, @code{abort} is called
-immediately.  This can be useful because otherwise a crash may happen
-much later, and the true cause for the problem is then very hard to
-track down.
+variable @code{MALLOC_CHECK_}.  When @code{MALLOC_CHECK_} is set to a
+non-zero value, a special (less efficient) implementation is used which
+is designed to be tolerant against simple errors, such as double calls
+of @code{free} with the same argument, or overruns of a single byte
+(off-by-one bugs).  Not all such errors can be protected against,
+however, and memory leaks can result.
+
+Any detected heap corruption results in immediate termination of the
+process.
 
 There is one problem with @code{MALLOC_CHECK_}: in SUID or SGID binaries
 it could possibly be exploited since diverging from the normal programs
@@ -828,7 +1337,7 @@ recompile your application.
 @subsubsection Memory Allocation Hooks
 @cindex allocation hooks, for @code{malloc}
 
-The GNU C library lets you modify the behavior of @code{malloc},
+@Theglibc{} lets you modify the behavior of @code{malloc},
 @code{realloc}, and @code{free} by specifying appropriate hook
 functions.  You can use these hooks to help you debug programs that use
 dynamic memory allocation, for example.
@@ -836,9 +1345,8 @@ dynamic memory allocation, for example.
 The hook variables are declared in @file{malloc.h}.
 @pindex malloc.h
 
-@comment malloc.h
-@comment GNU
 @defvar __malloc_hook
+@standards{GNU, malloc.h}
 The value of this variable is a pointer to the function that
 @code{malloc} uses whenever it is called.  You should define this
 function to look like @code{malloc}; that is, like:
@@ -852,9 +1360,8 @@ the @code{malloc} function was called.  This value allows you to trace
 the memory consumption of the program.
 @end defvar
 
-@comment malloc.h
-@comment GNU
 @defvar __realloc_hook
+@standards{GNU, malloc.h}
 The value of this variable is a pointer to function that @code{realloc}
 uses whenever it is called.  You should define this function to look
 like @code{realloc}; that is, like:
@@ -868,9 +1375,8 @@ the @code{realloc} function was called.  This value allows you to trace the
 memory consumption of the program.
 @end defvar
 
-@comment malloc.h
-@comment GNU
 @defvar __free_hook
+@standards{GNU, malloc.h}
 The value of this variable is a pointer to function that @code{free}
 uses whenever it is called.  You should define this function to look
 like @code{free}; that is, like:
@@ -884,19 +1390,20 @@ the @code{free} function was called.  This value allows you to trace the
 memory consumption of the program.
 @end defvar
 
-@comment malloc.h
-@comment GNU
 @defvar __memalign_hook
-The value of this variable is a pointer to function that @code{memalign}
-uses whenever it is called.  You should define this function to look
-like @code{memalign}; that is, like:
+@standards{GNU, malloc.h}
+The value of this variable is a pointer to function that @code{aligned_alloc},
+@code{memalign}, @code{posix_memalign} and @code{valloc} use whenever they
+are called.  You should define this function to look like @code{aligned_alloc};
+that is, like:
 
 @smallexample
-void *@var{function} (size_t @var{size}, size_t @var{alignment}, const void *@var{caller})
+void *@var{function} (size_t @var{alignment}, size_t @var{size}, const void *@var{caller})
 @end smallexample
 
 The value of @var{caller} is the return address found on the stack when
-the @code{memalign} function was called.  This value allows you to trace the
+the @code{aligned_alloc}, @code{memalign}, @code{posix_memalign} or
+@code{valloc} functions are called.  This value allows you to trace the
 memory consumption of the program.
 @end defvar
 
@@ -908,19 +1415,6 @@ should make sure to restore all the hooks to their previous value.  When
 coming back from the recursive call, all the hooks should be resaved
 since a hook might modify itself.
 
-@comment malloc.h
-@comment GNU
-@defvar __malloc_initialize_hook
-The value of this variable is a pointer to a function that is called
-once when the malloc implementation is initialized.  This is a weak
-variable, so it can be overridden in the application with a definition
-like the following:
-
-@smallexample
-void (*@var{__malloc_initialize_hook}) (void) = my_init_hook;
-@end smallexample
-@end defvar
-
 An issue to look out for is the time at which the malloc hook functions
 can be safely installed.  If the hook functions call the malloc-related
 functions recursively, it is necessary that malloc has already properly
@@ -931,11 +1425,6 @@ are assigned to @emph{before} the very first @code{malloc} call has
 completed, because otherwise a chunk obtained from the ordinary,
 un-hooked malloc may later be handed to @code{__free_hook}, for example.
 
-In both cases, the problem can be solved by setting up the hooks from
-within a user-defined function pointed to by
-@code{__malloc_initialize_hook}---then the hooks will be set up safely
-at the right time.
-
 Here is an example showing how to use @code{__malloc_hook} and
 @code{__free_hook} properly.  It installs a function that prints out
 information every time @code{malloc} or @code{free} is called.  We just
@@ -947,15 +1436,12 @@ program.
 #include <malloc.h>
 
 /* Prototypes for our hooks.  */
-static void *my_init_hook (void);
+static void my_init_hook (void);
 static void *my_malloc_hook (size_t, const void *);
 static void my_free_hook (void*, const void *);
 
-/* Override initializing hook from the C library. */
-void (*__malloc_initialize_hook) (void) = my_init_hook;
-
 static void
-my_init_hook (void)
+my_init (void)
 @{
   old_malloc_hook = __malloc_hook;
   old_free_hook = __free_hook;
@@ -983,7 +1469,7 @@ my_malloc_hook (size_t size, const void *caller)
   return result;
 @}
 
-static void *
+static void
 my_free_hook (void *ptr, const void *caller)
 @{
   /* Restore all old hooks */
@@ -1003,7 +1489,8 @@ my_free_hook (void *ptr, const void *caller)
 
 main ()
 @{
-  ...
+  my_init ();
+  @dots{}
 @}
 @end smallexample
 
@@ -1023,9 +1510,8 @@ are declared in @file{malloc.h}; they are an extension of the standard
 SVID/XPG version.
 @pindex malloc.h
 
-@comment malloc.h
-@comment GNU
 @deftp {Data Type} {struct mallinfo}
+@standards{GNU, malloc.h}
 This structure type is used to return information about the dynamic
 memory allocator.  It contains the following members:
 
@@ -1037,8 +1523,8 @@ This is the total size of memory allocated with @code{sbrk} by
 @item int ordblks
 This is the number of chunks not in use.  (The memory allocator
 internally gets chunks of memory from the operating system, and then
-carves them up to satisfy individual @code{malloc} requests; see
-@ref{Efficiency and Malloc}.)
+carves them up to satisfy individual @code{malloc} requests;
+@pxref{The GNU Allocator}.)
 
 @item int smblks
 This field is unused.
@@ -1050,7 +1536,7 @@ This is the total number of chunks allocated with @code{mmap}.
 This is the total size of memory allocated with @code{mmap}, in bytes.
 
 @item int usmblks
-This field is unused.
+This field is unused and always 0.
 
 @item int fsmblks
 This field is unused.
@@ -1064,15 +1550,32 @@ This is the total size of memory occupied by free (not in use) chunks.
 
 @item int keepcost
 This is the size of the top-most releasable chunk that normally
-borders the end of the heap (i.e. the high end of the virtual address
+borders the end of the heap (i.e., the high end of the virtual address
 space's data segment).
 
 @end table
 @end deftp
 
-@comment malloc.h
-@comment SVID
 @deftypefun {struct mallinfo} mallinfo (void)
+@standards{SVID, malloc.h}
+@safety{@prelim{}@mtunsafe{@mtuinit{} @mtasuconst{:mallopt}}@asunsafe{@asuinit{} @asulock{}}@acunsafe{@acuinit{} @aculock{}}}
+@c Accessing mp_.n_mmaps and mp_.max_mmapped_mem, modified with atomics
+@c but non-atomically elsewhere, may get us inconsistent results.  We
+@c mark the statistics as unsafe, rather than the fast-path functions
+@c that collect the possibly inconsistent data.
+
+@c __libc_mallinfo @mtuinit @mtasuconst:mallopt @asuinit @asulock @aculock
+@c  ptmalloc_init (once) dup @mtsenv @asulock @aculock @acsfd @acsmem
+@c  mutex_lock dup @asulock @aculock
+@c  int_mallinfo @mtasuconst:mallopt [mp_ access on main_arena]
+@c   malloc_consolidate dup ok
+@c   check_malloc_state dup ok/disabled
+@c   chunksize dup ok
+@c   fastbin dupo ok
+@c   bin_at dup ok
+@c   last dup ok
+@c  mutex_unlock @aculock
+
 This function returns information about the current dynamic memory usage
 in a structure of type @code{struct mallinfo}.
 @end deftypefun
@@ -1094,6 +1597,11 @@ Malloc}.
 Make a block previously allocated by @code{malloc} larger or smaller,
 possibly by copying it to a new location.  @xref{Changing Block Size}.
 
+@item void *reallocarray (void *@var{ptr}, size_t @var{nmemb}, size_t @var{size})
+Change the size of a block previously allocated by @code{malloc} to
+@code{@var{nmemb} * @var{size}} bytes as with @code{realloc}.  @xref{Changing
+Block Size}.
+
 @item void *calloc (size_t @var{count}, size_t @var{eltsize})
 Allocate a block of @var{count} * @var{eltsize} bytes using
 @code{malloc}, and set its contents to zero.  @xref{Allocating Cleared
@@ -1103,6 +1611,14 @@ Space}.
 Allocate a block of @var{size} bytes, starting on a page boundary.
 @xref{Aligned Memory Blocks}.
 
+@item void *aligned_alloc (size_t @var{size}, size_t @var{alignment})
+Allocate a block of @var{size} bytes, starting on an address that is a
+multiple of @var{alignment}.  @xref{Aligned Memory Blocks}.
+
+@item int posix_memalign (void **@var{memptr}, size_t @var{alignment}, size_t @var{size})
+Allocate a block of @var{size} bytes, starting on an address that is a
+multiple of @var{alignment}.  @xref{Aligned Memory Blocks}.
+
 @item void *memalign (size_t @var{size}, size_t @var{boundary})
 Allocate a block of @var{size} bytes, starting on an address that is a
 multiple of @var{boundary}.  @xref{Aligned Memory Blocks}.
@@ -1125,7 +1641,8 @@ A pointer to a function that @code{realloc} uses whenever it is called.
 A pointer to a function that @code{free} uses whenever it is called.
 
 @item void (*__memalign_hook) (size_t @var{size}, size_t @var{alignment}, const void *@var{caller})
-A pointer to a function that @code{memalign} uses whenever it is called.
+A pointer to a function that @code{aligned_alloc}, @code{memalign},
+@code{posix_memalign} and @code{valloc} use whenever they are called.
 
 @item struct mallinfo mallinfo (void)
 Return information about the current dynamic memory usage.
@@ -1139,11 +1656,11 @@ Return information about the current dynamic memory usage.
 
 A complicated task when programming with languages which do not use
 garbage collected dynamic memory allocation is to find memory leaks.
-Long running programs must assure that dynamically allocated objects are
+Long running programs must ensure that dynamically allocated objects are
 freed at the end of their lifetime.  If this does not happen the system
 runs out of memory, sooner or later.
 
-The @code{malloc} implementation in the GNU C library provides some
+The @code{malloc} implementation in @theglibc{} provides some
 simple means to detect such leaks and obtain some information to find
 the location.  To do this the application must be started in a special
 mode which is enabled by an environment variable.  There are no speed
@@ -1159,9 +1676,22 @@ penalties for the program if the debugging mode is not enabled.
 @node Tracing malloc
 @subsubsection How to install the tracing functionality
 
-@comment mcheck.h
-@comment GNU
 @deftypefun void mtrace (void)
+@standards{GNU, mcheck.h}
+@safety{@prelim{}@mtunsafe{@mtsenv{} @mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtuinit{}}@asunsafe{@asuinit{} @ascuheap{} @asucorrupt{} @asulock{}}@acunsafe{@acuinit{} @acucorrupt{} @aculock{} @acsfd{} @acsmem{}}}
+@c Like the mcheck hooks, these are not designed with thread safety in
+@c mind, because the hook pointers are temporarily modified without
+@c regard to other threads, signals or cancellation.
+
+@c mtrace @mtuinit @mtasurace:mtrace @mtsenv @asuinit @ascuheap @asucorrupt @acuinit @acucorrupt @aculock @acsfd @acsmem
+@c  __libc_secure_getenv dup @mtsenv
+@c  malloc dup @ascuheap @acsmem
+@c  fopen dup @ascuheap @asulock @aculock @acsmem @acsfd
+@c  fcntl dup ok
+@c  setvbuf dup @aculock
+@c  fprintf dup (on newly-created stream) @aculock
+@c  __cxa_atexit (once) dup @asulock @aculock @acsmem
+@c  free dup @ascuheap @acsmem
 When the @code{mtrace} function is called it looks for an environment
 variable named @code{MALLOC_TRACE}.  This variable is supposed to
 contain a valid file name.  The user must have write access.  If the
@@ -1182,9 +1712,13 @@ This function is a GNU extension and generally not available on other
 systems.  The prototype can be found in @file{mcheck.h}.
 @end deftypefun
 
-@comment mcheck.h
-@comment GNU
 @deftypefun void muntrace (void)
+@standards{GNU, mcheck.h}
+@safety{@prelim{}@mtunsafe{@mtasurace{:mtrace} @mtasuconst{:malloc_hooks} @mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acucorrupt{} @acsmem{} @aculock{} @acsfd{}}}
+
+@c muntrace @mtasurace:mtrace @mtslocale @asucorrupt @ascuheap @acucorrupt @acsmem @aculock @acsfd
+@c  fprintf (fputs) dup @mtslocale @asucorrupt @ascuheap @acsmem @aculock @acucorrupt
+@c  fclose dup @ascuheap @asulock @aculock @acsmem @acsfd
 The @code{muntrace} function can be called after @code{mtrace} was used
 to enable tracing the @code{malloc} calls.  If no (successful) call of
 @code{mtrace} was made @code{muntrace} does nothing.
@@ -1221,7 +1755,7 @@ main (int argc, char *argv[])
 @}
 @end example
 
-This is all what is needed if you want to trace the calls during the
+This is all that is needed if you want to trace the calls during the
 whole runtime of the program.  Alternatively you can stop the tracing at
 any time with a call to @code{muntrace}.  It is even possible to restart
 the tracing again with a new call to @code{mtrace}.  But this can cause
@@ -1230,8 +1764,8 @@ not called.  Please note that not only the application uses the traced
 functions, also libraries (including the C library itself) use these
 functions.
 
-This last point is also why it is no good idea to call @code{muntrace}
-before the program terminated.  The libraries are informed about the
+This last point is also why it is not a good idea to call @code{muntrace}
+before the program terminates.  The libraries are informed about the
 termination of the program only after the program returns from
 @code{main} or calls @code{exit} and so cannot free the memory they use
 before this time.
@@ -1307,8 +1841,8 @@ If you take a look at the output it will look similar to this:
 
 What this all means is not really important since the trace file is not
 meant to be read by a human.  Therefore no attention is given to
-readability.  Instead there is a program which comes with the GNU C
-library which interprets the traces and outputs a summary in an
+readability.  Instead there is a program which comes with @theglibc{}
+which interprets the traces and outputs a summary in an
 user-friendly way.  The program is called @code{mtrace} (it is in fact a
 Perl script) and it takes one or two arguments.  In any case the name of
 the file with the trace output must be specified.  If an optional
@@ -1380,6 +1914,67 @@ from line 33 in the source file @file{/home/drepper/tst-mtrace.c} four
 times without freeing this memory before the program terminates.
 Whether this is a real problem remains to be investigated.
 
+@node Replacing malloc
+@subsection Replacing @code{malloc}
+
+@cindex @code{malloc} replacement
+@cindex @code{LD_PRELOAD} and @code{malloc}
+@cindex alternative @code{malloc} implementations
+@cindex customizing @code{malloc}
+@cindex interposing @code{malloc}
+@cindex preempting @code{malloc}
+@cindex replacing @code{malloc}
+@Theglibc{} supports replacing the built-in @code{malloc} implementation
+with a different allocator with the same interface.  For dynamically
+linked programs, this happens through ELF symbol interposition, either
+using shared object dependencies or @code{LD_PRELOAD}.  For static
+linking, the @code{malloc} replacement library must be linked in before
+linking against @code{libc.a} (explicitly or implicitly).
+
+@strong{Note:} Failure to provide a complete set of replacement
+functions (that is, all the functions used by the application,
+@theglibc{}, and other linked-in libraries) can lead to static linking
+failures, and, at run time, to heap corruption and application crashes.
+
+The minimum set of functions which has to be provided by a custom
+@code{malloc} is given in the table below.
+
+@table @code
+@item malloc
+@item free
+@item calloc
+@item realloc
+@end table
+
+These @code{malloc}-related functions are required for @theglibc{} to
+work.@footnote{Versions of @theglibc{} before 2.25 required that a
+custom @code{malloc} defines @code{__libc_memalign} (with the same
+interface as the @code{memalign} function).}
+
+The @code{malloc} implementation in @theglibc{} provides additional
+functionality not used by the library itself, but which is often used by
+other system libraries and applications.  A general-purpose replacement
+@code{malloc} implementation should provide definitions of these
+functions, too.  Their names are listed in the following table.
+
+@table @code
+@item aligned_alloc
+@item malloc_usable_size
+@item memalign
+@item posix_memalign
+@item pvalloc
+@item valloc
+@end table
+
+In addition, very old applications may use the obsolete @code{cfree}
+function.
+
+Further @code{malloc}-related functions such as @code{mallopt} or
+@code{mallinfo} will not have any effect or return incorrect statistics
+when a replacement @code{malloc} is in use.  However, failure to replace
+these functions typically does not result in crashes or other incorrect
+application behavior, but may result in static linking failures.
+
 @node Obstacks
 @subsection Obstacks
 @cindex obstacks
@@ -1421,9 +2016,8 @@ The utilities for manipulating obstacks are declared in the header
 file @file{obstack.h}.
 @pindex obstack.h
 
-@comment obstack.h
-@comment GNU
 @deftp {Data Type} {struct obstack}
+@standards{GNU, obstack.h}
 An obstack is represented by a data structure of type @code{struct
 obstack}.  This structure has a small fixed size; it records the status
 of the obstack and how to find the space in which objects are allocated.
@@ -1493,9 +2087,22 @@ At run time, before the program can use a @code{struct obstack} object
 as an obstack, it must initialize the obstack by calling
 @code{obstack_init}.
 
-@comment obstack.h
-@comment GNU
 @deftypefun int obstack_init (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{@acsmem{}}}
+@c obstack_init @mtsrace:obstack-ptr @acsmem
+@c  _obstack_begin @acsmem
+@c    chunkfun = obstack_chunk_alloc (suggested malloc)
+@c    freefun = obstack_chunk_free (suggested free)
+@c   *chunkfun @acsmem
+@c    obstack_chunk_alloc user-supplied
+@c   *obstack_alloc_failed_handler user-supplied
+@c    -> print_and_abort (default)
+@c
+@c print_and_abort
+@c  _ dup @ascuintl
+@c  fxprintf dup @asucorrupt @aculock @acucorrupt
+@c  exit @acucorrupt?
 Initialize obstack @var{obstack-ptr} for allocation of objects.  This
 function calls the obstack's @code{obstack_chunk_alloc} function.  If
 allocation of memory fails, the function pointed to by
@@ -1523,9 +2130,8 @@ struct obstack *myobstack_ptr
 obstack_init (myobstack_ptr);
 @end smallexample
 
-@comment obstack.h
-@comment GNU
 @defvar obstack_alloc_failed_handler
+@standards{GNU, obstack.h}
 The value of this variable is a pointer to a function that
 @code{obstack} uses when @code{obstack_chunk_alloc} fails to allocate
 memory.  The default action is to print a message and abort.
@@ -1548,9 +2154,12 @@ obstack_alloc_failed_handler = &my_obstack_alloc_failed;
 The most direct way to allocate an object in an obstack is with
 @code{obstack_alloc}, which is invoked almost like @code{malloc}.
 
-@comment obstack.h
-@comment GNU
 @deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_alloc @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_blank dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_finish dup @mtsrace:obstack-ptr @acucorrupt
 This allocates an uninitialized block of @var{size} bytes in an obstack
 and returns its address.  Here @var{obstack-ptr} specifies which obstack
 to allocate the block in; it is the address of the @code{struct obstack}
@@ -1582,18 +2191,24 @@ copystring (char *string)
 To allocate a block with specified contents, use the function
 @code{obstack_copy}, declared like this:
 
-@comment obstack.h
-@comment GNU
 @deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_copy @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_grow dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_finish dup @mtsrace:obstack-ptr @acucorrupt
 This allocates a block and initializes it by copying @var{size}
 bytes of data starting at @var{address}.  It calls
 @code{obstack_alloc_failed_handler} if allocation of memory by
 @code{obstack_chunk_alloc} failed.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_copy0 @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_grow0 dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_finish dup @mtsrace:obstack-ptr @acucorrupt
 Like @code{obstack_copy}, but appends an extra byte containing a null
 character.  This extra byte is not counted in the argument @var{size}.
 @end deftypefun
@@ -1623,13 +2238,16 @@ To free an object allocated in an obstack, use the function
 one object automatically frees all other objects allocated more recently
 in the same obstack.
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_free (struct obstack *@var{obstack-ptr}, void *@var{object})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}}
+@c obstack_free @mtsrace:obstack-ptr @acucorrupt
+@c  (obstack_free) @mtsrace:obstack-ptr @acucorrupt
+@c   *freefun dup user-supplied
 If @var{object} is a null pointer, everything allocated in the obstack
 is freed.  Otherwise, @var{object} must be the address of an object
 allocated in the obstack.  Then @var{object} is freed, along with
-everything allocated in @var{obstack} since @var{object}.
+everything allocated in @var{obstack-ptr} since @var{object}.
 @end deftypefun
 
 Note that if @var{object} is a null pointer, the result is an
@@ -1727,56 +2345,80 @@ While the obstack is in use for a growing object, you cannot use it for
 ordinary allocation of another object.  If you try to do so, the space
 already added to the growing object will become part of the other object.
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_blank (struct obstack *@var{obstack-ptr}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_blank @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  _obstack_newchunk @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c   *chunkfun dup @acsmem
+@c   *obstack_alloc_failed_handler dup user-supplied
+@c   *freefun
+@c  obstack_blank_fast dup @mtsrace:obstack-ptr
 The most basic function for adding to a growing object is
 @code{obstack_blank}, which adds space without initializing it.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_grow @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  memcpy ok
 To add a block of initialized space, use @code{obstack_grow}, which is
 the growing-object analogue of @code{obstack_copy}.  It adds @var{size}
 bytes of data to the growing object, copying the contents from
 @var{data}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_grow0 @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c   (no sequence point between storing NUL and incrementing next_free)
+@c   (multiple changes to next_free => @acucorrupt)
+@c  _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  memcpy ok
 This is the growing-object analogue of @code{obstack_copy0}.  It adds
 @var{size} bytes copied from @var{data}, followed by an additional null
 character.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{c})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_1grow @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_1grow_fast dup @mtsrace:obstack-ptr @acucorrupt @acsmem
 To add one character at a time, use the function @code{obstack_1grow}.
 It adds a single byte containing @var{c} to the growing object.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_ptr_grow (struct obstack *@var{obstack-ptr}, void *@var{data})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_ptr_grow @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_ptr_grow_fast dup @mtsrace:obstack-ptr
 Adding the value of a pointer one can use the function
 @code{obstack_ptr_grow}.  It adds @code{sizeof (void *)} bytes
 containing the value of @var{data}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_int_grow (struct obstack *@var{obstack-ptr}, int @var{data})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_int_grow @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  _obstack_newchunk dup @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c  obstack_int_grow_fast dup @mtsrace:obstack-ptr
 A single value of type @code{int} can be added by using the
 @code{obstack_int_grow} function.  It adds @code{sizeof (int)} bytes to
 the growing object and initializes them with the value of @var{data}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{}}}
+@c obstack_finish @mtsrace:obstack-ptr @acucorrupt
 When you are finished growing the object, use the function
 @code{obstack_finish} to close it off and return its final address.
 
@@ -1793,9 +2435,9 @@ the object, because you can find out the length from the obstack just
 before finishing the object with the function @code{obstack_object_size},
 declared as follows:
 
-@comment obstack.h
-@comment GNU
 @deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
 This function returns the current size of the growing object, in bytes.
 Remember to call this function @emph{before} finishing the object.
 After it is finished, @code{obstack_object_size} will return zero.
@@ -1836,43 +2478,48 @@ more efficiently, then you make the program faster.
 The function @code{obstack_room} returns the amount of room available
 in the current chunk.  It is declared as follows:
 
-@comment obstack.h
-@comment GNU
 @deftypefun int obstack_room (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
 This returns the number of bytes that can be added safely to the current
 growing object (or to an object about to be started) in obstack
-@var{obstack} using the fast growth functions.
+@var{obstack-ptr} using the fast growth functions.
 @end deftypefun
 
 While you know there is room, you can use these fast growth functions
 for adding data to a growing object:
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_1grow_fast (struct obstack *@var{obstack-ptr}, char @var{c})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acunsafe{@acucorrupt{} @acsmem{}}}
+@c obstack_1grow_fast @mtsrace:obstack-ptr @acucorrupt @acsmem
+@c   (no sequence point between copying c and incrementing next_free)
 The function @code{obstack_1grow_fast} adds one byte containing the
 character @var{c} to the growing object in obstack @var{obstack-ptr}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_ptr_grow_fast (struct obstack *@var{obstack-ptr}, void *@var{data})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
+@c obstack_ptr_grow_fast @mtsrace:obstack-ptr
 The function @code{obstack_ptr_grow_fast} adds @code{sizeof (void *)}
 bytes containing the value of @var{data} to the growing object in
 obstack @var{obstack-ptr}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_int_grow_fast (struct obstack *@var{obstack-ptr}, int @var{data})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
+@c obstack_int_grow_fast @mtsrace:obstack-ptr
 The function @code{obstack_int_grow_fast} adds @code{sizeof (int)} bytes
 containing the value of @var{data} to the growing object in obstack
 @var{obstack-ptr}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
+@c obstack_blank_fast @mtsrace:obstack-ptr
 The function @code{obstack_blank_fast} adds @var{size} bytes to the
 growing object in obstack @var{obstack-ptr} without initializing them.
 @end deftypefun
@@ -1900,7 +2547,7 @@ add_string (struct obstack *obstack, const char *ptr, int len)
       int room = obstack_room (obstack);
       if (room == 0)
         @{
-          /* @r{Not enough room. Add one character slowly,}
+          /* @r{Not enough room.  Add one character slowly,}
              @r{which may copy to a new chunk and make room.}  */
           obstack_1grow (obstack, *ptr++);
           len--;
@@ -1928,9 +2575,9 @@ Here are functions that provide information on the current status of
 allocation in an obstack.  You can use them to learn about an object while
 still growing it.
 
-@comment obstack.h
-@comment GNU
 @deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}}
 This function returns the tentative address of the beginning of the
 currently growing object in @var{obstack-ptr}.  If you finish the object
 immediately, it will have that address.  If you make it larger first, it
@@ -1941,18 +2588,19 @@ allocate will start (once again assuming it fits in the current
 chunk).
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acsafe{}}
 This function returns the address of the first free byte in the current
 chunk of obstack @var{obstack-ptr}.  This is the end of the currently
 growing object.  If no object is growing, @code{obstack_next_free}
 returns the same value as @code{obstack_base}.
 @end deftypefun
 
-@comment obstack.h
-@comment GNU
 @deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@c dup
+@safety{@prelim{}@mtsafe{@mtsrace{:obstack-ptr}}@assafe{}@acsafe{}}
 This function returns the size in bytes of the currently growing object.
 This is equivalent to
 
@@ -1967,19 +2615,22 @@ obstack_next_free (@var{obstack-ptr}) - obstack_base (@var{obstack-ptr})
 
 Each obstack has an @dfn{alignment boundary}; each object allocated in
 the obstack automatically starts on an address that is a multiple of the
-specified boundary.  By default, this boundary is 4 bytes.
+specified boundary.  By default, this boundary is aligned so that
+the object can hold any type of data.
 
 To access an obstack's alignment boundary, use the macro
 @code{obstack_alignment_mask}, whose function prototype looks like
 this:
 
-@comment obstack.h
-@comment GNU
 @deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 The value is a bit mask; a bit that is 1 indicates that the corresponding
 bit in the address of an object should be 0.  The mask value should be one
 less than a power of 2; the effect is that all object addresses are
-multiples of that power of 2.  The default value of the mask is 3, so that
+multiples of that power of 2.  The default value of the mask is a value
+that allows aligned objects to hold any type of data: for example, if
+its value is 3, any type of data can be stored at locations whose
 addresses are multiples of 4.  A mask value of 0 means an object can start
 on any multiple of 1 (that is, no alignment is required).
 
@@ -2038,9 +2689,9 @@ power of 2.  The default chunk size, 4096, was chosen because it is long
 enough to satisfy many typical requests on the obstack yet short enough
 not to waste too much memory in the portion of the last chunk not yet used.
 
-@comment obstack.h
-@comment GNU
 @deftypefn Macro int obstack_chunk_size (struct obstack *@var{obstack-ptr})
+@standards{GNU, obstack.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 This returns the chunk size of the given obstack.
 @end deftypefn
 
@@ -2157,9 +2808,10 @@ The prototype for @code{alloca} is in @file{stdlib.h}.  This function is
 a BSD extension.
 @pindex stdlib.h
 
-@comment stdlib.h
-@comment GNU, BSD
-@deftypefun {void *} alloca (size_t @var{size});
+@deftypefun {void *} alloca (size_t @var{size})
+@standards{GNU, stdlib.h}
+@standards{BSD, stdlib.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 The return value of @code{alloca} is the address of a block of @var{size}
 bytes of memory, allocated in the stack frame of the calling function.
 @end deftypefun
@@ -2232,7 +2884,7 @@ open-coded by the GNU C compiler.)
 
 @item
 Since @code{alloca} does not have separate pools for different sizes of
-block, space used for any size block can be reused for any other size.
+blocks, space used for any size block can be reused for any other size.
 @code{alloca} does not cause memory fragmentation.
 
 @item
@@ -2286,7 +2938,7 @@ the one you would get from an infinite recursion; probably a
 segmentation violation (@pxref{Program Error Signals}).
 
 @item
-Some non-GNU systems fail to support @code{alloca}, so it is less
+Some @nongnusystems{} fail to support @code{alloca}, so it is less
 portable.  However, a slower emulation of @code{alloca} written in C
 is available for use on systems with this deficiency.
 @end itemize
@@ -2322,7 +2974,7 @@ additional block on each iteration.  This is impossible with
 variable-sized arrays.
 @end itemize
 
-@strong{Note:} If you mix use of @code{alloca} and variable-sized arrays
+@strong{NB:} If you mix use of @code{alloca} and variable-sized arrays
 within one function, exiting a scope in which a variable-sized array was
 declared frees all blocks allocated with @code{alloca} during the
 execution of that scope.
@@ -2335,13 +2987,13 @@ The symbols in this section are declared in @file{unistd.h}.
 
 You will not normally use the functions in this section, because the
 functions described in @ref{Memory Allocation} are easier to use.  Those
-are interfaces to a GNU C Library memory allocator that uses the
+are interfaces to a @glibcadj{} memory allocator that uses the
 functions below itself.  The functions below are simple interfaces to
 system calls.
 
-@comment unistd.h
-@comment BSD
 @deftypefun int brk (void *@var{addr})
+@standards{BSD, unistd.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 
 @code{brk} sets the high end of the calling process' data segment to
 @var{addr}.
@@ -2350,7 +3002,7 @@ The address of the end of a segment is defined to be the address of the
 last byte in the segment plus 1.
 
 The function has no effect if @var{addr} is lower than the low end of
-the data segment.  (This is considered success, by the way).
+the data segment.  (This is considered success, by the way.)
 
 The function fails if it would cause the data segment to overlap another
 segment or exceed the process' data storage limit (@pxref{Limits on
@@ -2375,15 +3027,16 @@ exceed the process' data storage limit.
 @c The Brk system call in Linux (as opposed to the GNU C Library function)
 @c is considerably different.  It always returns the new end of the data
 @c segment, whether it succeeds or fails.  The GNU C library Brk determines
-@c it's a failure if and only if if the system call returns an address less
+@c it's a failure if and only if the system call returns an address less
 @c than the address requested.
 
 @end deftypefun
 
 
-@comment unistd.h
-@comment BSD
-@deftypefun int sbrk (ptrdiff_t @var{delta})
+@deftypefun void *sbrk (ptrdiff_t @var{delta})
+@standards{BSD, unistd.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+
 This function is the same as @code{brk} except that you specify the new
 end of the data segment as an offset @var{delta} from the current end
 and on success the return value is the address of the resulting end of
@@ -2394,7 +3047,360 @@ of the data segment is.
 
 @end deftypefun
 
+@node Memory Protection
+@section Memory Protection
+@cindex memory protection
+@cindex page protection
+@cindex protection flags
+
+When a page is mapped using @code{mmap}, page protection flags can be
+specified using the protection flags argument.  @xref{Memory-mapped
+I/O}.
+
+The following flags are available:
+
+@vtable @code
+@item PROT_WRITE
+@standards{POSIX, sys/mman.h}
+The memory can be written to.
+
+@item PROT_READ
+@standards{POSIX, sys/mman.h}
+The memory can be read.  On some architectures, this flag implies that
+the memory can be executed as well (as if @code{PROT_EXEC} had been
+specified at the same time).
+
+@item PROT_EXEC
+@standards{POSIX, sys/mman.h}
+The memory can be used to store instructions which can then be executed.
+On most architectures, this flag implies that the memory can be read (as
+if @code{PROT_READ} had been specified).
+
+@item PROT_NONE
+@standards{POSIX, sys/mman.h}
+This flag must be specified on its own.
+
+The memory is reserved, but cannot be read, written, or executed.  If
+this flag is specified in a call to @code{mmap}, a virtual memory area
+will be set aside for future use in the process, and @code{mmap} calls
+without the @code{MAP_FIXED} flag will not use it for subsequent
+allocations.  For anonymous mappings, the kernel will not reserve any
+physical memory for the allocation at the time the mapping is created.
+@end vtable
+
+The operating system may keep track of these flags separately even if
+the underlying hardware treats them the same for the purposes of access
+checking (as happens with @code{PROT_READ} and @code{PROT_EXEC} on some
+platforms).  On GNU systems, @code{PROT_EXEC} always implies
+@code{PROT_READ}, so that users can view the machine code which is
+executing on their system.
+
+Inappropriate access will cause a segfault (@pxref{Program Error
+Signals}).
+
+After allocation, protection flags can be changed using the
+@code{mprotect} function.
+
+@deftypefun int mprotect (void *@var{address}, size_t @var{length}, int @var{protection})
+@standards{POSIX, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+
+A successful call to the @code{mprotect} function changes the protection
+flags of at least @var{length} bytes of memory, starting at
+@var{address}.
+
+@var{address} must be aligned to the page size for the mapping.  The
+system page size can be obtained by calling @code{sysconf} with the
+@code{_SC_PAGESIZE} parameter (@pxref{Sysconf Definition}).  The system
+page size is the granularity in which the page protection of anonymous
+memory mappings and most file mappings can be changed.  Memory which is
+mapped from special files or devices may have larger page granularity
+than the system page size and may require larger alignment.
+
+@var{length} is the number of bytes whose protection flags must be
+changed.  It is automatically rounded up to the next multiple of the
+system page size.
+
+@var{protection} is a combination of the @code{PROT_*} flags described
+above.
+
+The @code{mprotect} function returns @math{0} on success and @math{-1}
+on failure.
+
+The following @code{errno} error conditions are defined for this
+function:
+
+@table @code
+@item ENOMEM
+The system was not able to allocate resources to fulfill the request.
+This can happen if there is not enough physical memory in the system for
+the allocation of backing storage.  The error can also occur if the new
+protection flags would cause the memory region to be split from its
+neighbors, and the process limit for the number of such distinct memory
+regions would be exceeded.
+
+@item EINVAL
+@var{address} is not properly aligned to a page boundary for the
+mapping, or @var{length} (after rounding up to the system page size) is
+not a multiple of the applicable page size for the mapping, or the
+combination of flags in @var{protection} is not valid.
+
+@item EACCES
+The file for a file-based mapping was not opened with open flags which
+are compatible with @var{protection}.
+
+@item EPERM
+The system security policy does not allow a mapping with the specified
+flags.  For example, mappings which are both @code{PROT_EXEC} and
+@code{PROT_WRITE} at the same time might not be allowed.
+@end table
+@end deftypefun
+
+If the @code{mprotect} function is used to make a region of memory
+inaccessible by specifying the @code{PROT_NONE} protection flag and
+access is later restored, the memory retains its previous contents.
+
+On some systems, it may not be possible to specify additional flags
+which were not present when the mapping was first created.  For example,
+an attempt to make a region of memory executable could fail if the
+initial protection flags were @samp{PROT_READ | PROT_WRITE}.
+
+In general, the @code{mprotect} function can be used to change any
+process memory, no matter how it was allocated.  However, portable use
+of the function requires that it is only used with memory regions
+returned by @code{mmap} or @code{mmap64}.
+
+@subsection Memory Protection Keys
+
+@cindex memory protection key
+@cindex protection key
+@cindex MPK
+On some systems, further restrictions can be added to specific pages
+using @dfn{memory protection keys}.  These restrictions work as follows:
+
+@itemize @bullet
+@item
+All memory pages are associated with a protection key.  The default
+protection key does not cause any additional protections to be applied
+during memory accesses.  New keys can be allocated with the
+@code{pkey_alloc} function, and applied to pages using
+@code{pkey_mprotect}.
+
+@item
+Each thread has a set of separate access right restriction for each
+protection key.  These access rights can be manipulated using the
+@code{pkey_set} and @code{pkey_get} functions.
+
+@item
+During a memory access, the system obtains the protection key for the
+accessed page and uses that to determine the applicable access rights,
+as configured for the current thread.  If the access is restricted, a
+segmentation fault is the result ((@pxref{Program Error Signals}).
+These checks happen in addition to the @code{PROT_}* protection flags
+set by @code{mprotect} or @code{pkey_mprotect}.
+@end itemize
+
+New threads and subprocesses inherit the access rights of the current
+thread.  If a protection key is allocated subsequently, existing threads
+(except the current) will use an unspecified system default for the
+access rights associated with newly allocated keys.
 
+Upon entering a signal handler, the system resets the access rights of
+the current thread so that pages with the default key can be accessed,
+but the access rights for other protection keys are unspecified.
+
+Applications are expected to allocate a key once using
+@code{pkey_alloc}, and apply the key to memory regions which need
+special protection with @code{pkey_mprotect}:
+
+@smallexample
+  int key = pkey_alloc (0, PKEY_DISABLE_ACCESS);
+  if (key < 0)
+    /* Perform error checking, including fallback for lack of support.  */
+    ...;
+
+  /* Apply the key to a special memory region used to store critical
+     data.  */
+  if (pkey_mprotect (region, region_length,
+                     PROT_READ | PROT_WRITE, key) < 0)
+    ...; /* Perform error checking (generally fatal).  */
+@end smallexample
+
+If the key allocation fails due to lack of support for memory protection
+keys, the @code{pkey_mprotect} call can usually be skipped.  In this
+case, the region will not be protected by default.  It is also possible
+to call @code{pkey_mprotect} with a key value of @math{-1}, in which
+case it will behave in the same way as @code{mprotect}.
+
+After key allocation assignment to memory pages, @code{pkey_set} can be
+used to temporarily acquire access to the memory region and relinquish
+it again:
+
+@smallexample
+  if (key >= 0 && pkey_set (key, 0) < 0)
+    ...; /* Perform error checking (generally fatal).  */
+  /* At this point, the current thread has read-write access to the
+     memory region.  */
+  ...
+  /* Revoke access again.  */
+  if (key >= 0 && pkey_set (key, PKEY_DISABLE_ACCESS) < 0)
+    ...; /* Perform error checking (generally fatal).  */
+@end smallexample
+
+In this example, a negative key value indicates that no key had been
+allocated, which means that the system lacks support for memory
+protection keys and it is not necessary to change the the access rights
+of the current thread (because it always has access).
+
+Compared to using @code{mprotect} to change the page protection flags,
+this approach has two advantages: It is thread-safe in the sense that
+the access rights are only changed for the current thread, so another
+thread which changes its own access rights concurrently to gain access
+to the mapping will not suddenly see its access rights revoked.  And
+@code{pkey_set} typically does not involve a call into the kernel and a
+context switch, so it is more efficient.
+
+@deftypefun int pkey_alloc (unsigned int @var{flags}, unsigned int @var{restrictions})
+@standards{Linux, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}}
+Allocate a new protection key.  The @var{flags} argument is reserved and
+must be zero.  The @var{restrictions} argument specifies access rights
+which are applied to the current thread (as if with @code{pkey_set}
+below).  Access rights of other threads are not changed.
+
+The function returns the new protection key, a non-negative number, or
+@math{-1} on error.
+
+The following @code{errno} error conditions are defined for this
+function:
+
+@table @code
+@item ENOSYS
+The system does not implement memory protection keys.
+
+@item EINVAL
+The @var{flags} argument is not zero.
+
+The @var{restrictions} argument is invalid.
+
+The system does not implement memory protection keys or runs in a mode
+in which memory protection keys are disabled.
+
+@item ENOSPC
+All available protection keys already have been allocated.
+@end table
+@end deftypefun
+
+@deftypefun int pkey_free (int @var{key})
+@standards{Linux, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Deallocate the protection key, so that it can be reused by
+@code{pkey_alloc}.
+
+Calling this function does not change the access rights of the freed
+protection key.  The calling thread and other threads may retain access
+to it, even if it is subsequently allocated again.  For this reason, it
+is not recommended to call the @code{pkey_free} function.
+
+@table @code
+@item ENOSYS
+The system does not implement memory protection keys.
+
+@item EINVAL
+The @var{key} argument is not a valid protection key.
+@end table
+@end deftypefun
+
+@deftypefun int pkey_mprotect (void *@var{address}, size_t @var{length}, int @var{protection}, int @var{key})
+@standards{Linux, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Similar to @code{mprotect}, but also set the memory protection key for
+the memory region to @code{key}.
+
+Some systems use memory protection keys to emulate certain combinations
+of @var{protection} flags.  Under such circumstances, specifying an
+explicit protection key may behave as if additional flags have been
+specified in @var{protection}, even though this does not happen with the
+default protection key.  For example, some systems can support
+@code{PROT_EXEC}-only mappings only with a default protection key, and
+memory with a key which was allocated using @code{pkey_alloc} will still
+be readable if @code{PROT_EXEC} is specified without @code{PROT_READ}.
+
+If @var{key} is @math{-1}, the default protection key is applied to the
+mapping, just as if @code{mprotect} had been called.
+
+The @code{pkey_mprotect} function returns @math{0} on success and
+@math{-1} on failure.  The same @code{errno} error conditions as for
+@code{mprotect} are defined for this function, with the following
+addition:
+
+@table @code
+@item EINVAL
+The @var{key} argument is not @math{-1} or a valid memory protection
+key allocated using @code{pkey_alloc}.
+
+@item ENOSYS
+The system does not implement memory protection keys, and @var{key} is
+not @math{-1}.
+@end table
+@end deftypefun
+
+@deftypefun int pkey_set (int @var{key}, unsigned int @var{rights})
+@standards{Linux, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Change the access rights of the current thread for memory pages with the
+protection key @var{key} to @var{rights}.  If @var{rights} is zero, no
+additional access restrictions on top of the page protection flags are
+applied.  Otherwise, @var{rights} is a combination of the following
+flags:
+
+@vtable @code
+@item PKEY_DISABLE_WRITE
+@standards{Linux, sys/mman.h}
+Subsequent attempts to write to memory with the specified protection
+key will fault.
+
+@item PKEY_DISABLE_ACCESS
+@standards{Linux, sys/mman.h}
+Subsequent attempts to write to or read from memory with the specified
+protection key will fault.
+@end vtable
+
+Operations not specified as flags are not restricted.  In particular,
+this means that the memory region will remain executable if it was
+mapped with the @code{PROT_EXEC} protection flag and
+@code{PKEY_DISABLE_ACCESS} has been specified.
+
+Calling the @code{pkey_set} function with a protection key which was not
+allocated by @code{pkey_alloc} results in undefined behavior.  This
+means that calling this function on systems which do not support memory
+protection keys is undefined.
+
+The @code{pkey_set} function returns @math{0} on success and @math{-1}
+on failure.
+
+The following @code{errno} error conditions are defined for this
+function:
+
+@table @code
+@item EINVAL
+The system does not support the access rights restrictions expressed in
+the @var{rights} argument.
+@end table
+@end deftypefun
+
+@deftypefun int pkey_get (int @var{key})
+@standards{Linux, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+Return the access rights of the current thread for memory pages with
+protection key @var{key}.  The return value is zero or a combination of
+the @code{PKEY_DISABLE_}* flags; see the @code{pkey_set} function.
+
+Calling the @code{pkey_get} function with a protection key which was not
+allocated by @code{pkey_alloc} results in undefined behavior.  This
+means that calling this function on systems which do not support memory
+protection keys is undefined.
+@end deftypefun
 
 @node Locking Pages
 @section Locking Pages
@@ -2403,7 +3409,7 @@ of the data segment is.
 @cindex paging
 
 You can tell the system to associate a particular virtual memory page
-with a real page frame and keep it that way --- i.e. cause the page to
+with a real page frame and keep it that way --- i.e., cause the page to
 be paged in if it isn't already and mark it so it will never be paged
 out and consequently will never cause a page fault.  This is called
 @dfn{locking} a page.
@@ -2445,7 +3451,7 @@ system performance.  In this case, locking pages can help.
 @item
 Privacy.  If you keep secrets in virtual memory and that virtual memory
 gets paged out, that increases the chance that the secrets will get out.
-If a password gets written out to disk swap space, for example, it might
+If a passphrase gets written out to disk swap space, for example, it might
 still be there long after virtual and real memory have been wiped clean.
 
 @end itemize
@@ -2463,7 +3469,7 @@ A memory lock is associated with a virtual page, not a real frame.  The
 paging rule is: If a frame backs at least one locked page, don't page it
 out.
 
-Memory locks do not stack.  I.e. you can't lock a particular page twice
+Memory locks do not stack.  I.e., you can't lock a particular page twice
 so that it has to be unlocked twice before it is truly unlocked.  It is
 either locked or it isn't.
 
@@ -2517,12 +3523,12 @@ define the macro @code{_POSIX_MEMLOCK_RANGE} and the file
 @code{limits.h} define the macro @code{PAGESIZE} to be the size of a
 memory page in bytes.  It requires that when the @code{mlockall} and
 @code{munlockall} functions are available, the @file{unistd.h} file
-define the macro @code{_POSIX_MEMLOCK}.  The GNU C library conforms to
+define the macro @code{_POSIX_MEMLOCK}.  @Theglibc{} conforms to
 this requirement.
 
-@comment sys/mman.h
-@comment POSIX.1b
 @deftypefun int mlock (const void *@var{addr}, size_t @var{len})
+@standards{POSIX.1b, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 
 @code{mlock} locks a range of the calling process' virtual pages.
 
@@ -2562,6 +3568,36 @@ The calling process is not superuser.
 The kernel does not provide @code{mlock} capability.
 
 @end table
+@end deftypefun
+
+@deftypefun int mlock2 (const void *@var{addr}, size_t @var{len}, unsigned int @var{flags})
+@standards{Linux, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+
+This function is similar to @code{mlock}.  If @var{flags} is zero, a
+call to @code{mlock2} behaves exactly as the equivalent call to @code{mlock}.
+
+The @var{flags} argument must be a combination of zero or more of the
+following flags:
+
+@vtable @code
+@item MLOCK_ONFAULT
+@standards{Linux, sys/mman.h}
+Only those pages in the specified address range which are already in
+memory are locked immediately.  Additional pages in the range are
+automatically locked in case of a page fault and allocation of memory.
+@end vtable
+
+Like @code{mlock}, @code{mlock2} returns zero on success and @code{-1}
+on failure, setting @code{errno} accordingly.  Additional @code{errno}
+values defined for @code{mlock2} are:
+
+@table @code
+@item EINVAL
+The specified (non-zero) @var{flags} argument is not supported by this
+system.
+@end table
+@end deftypefun
 
 You can lock @emph{all} a process' memory with @code{mlockall}.  You
 unlock memory with @code{munlock} or @code{munlockall}.
@@ -2571,13 +3607,11 @@ To avoid all page faults in a C program, you have to use
 from the C code, e.g. the stack and automatic variables, and you
 wouldn't know what address to tell @code{mlock}.
 
-@end deftypefun
-
-@comment sys/mman.h
-@comment POSIX.1b
 @deftypefun int munlock (const void *@var{addr}, size_t @var{len})
+@standards{POSIX.1b, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 
-@code{mlock} unlocks a range of the calling process' virtual pages.
+@code{munlock} unlocks a range of the calling process' virtual pages.
 
 @code{munlock} is the inverse of @code{mlock} and functions completely
 analogously to @code{mlock}, except that there is no @code{EPERM}
@@ -2585,9 +3619,9 @@ failure.
 
 @end deftypefun
 
-@comment sys/mman.h
-@comment POSIX.1b
 @deftypefun int mlockall (int @var{flags})
+@standards{POSIX.1b, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 
 @code{mlockall} locks all the pages in a process' virtual memory address
 space, and/or any that are added to it in the future.  This includes the
@@ -2598,7 +3632,7 @@ user space kernel data, shared memory, and memory mapped files.
 macros.  They tell @code{mlockall} which of its functions you want.  All
 other bits must be zero.
 
-@table @code
+@vtable @code
 
 @item MCL_CURRENT
 Lock all pages which currently exist in the calling process' virtual
@@ -2611,7 +3645,7 @@ affect future address spaces owned by the same process so exec, which
 replaces a process' address space, wipes out @code{MCL_FUTURE}.
 @xref{Executing a File}.
 
-@end table
+@end vtable
 
 When the function returns successfully, and you specified
 @code{MCL_CURRENT}, all of the process' pages are backed by (connected
@@ -2661,12 +3695,12 @@ with @code{munlockall} and @code{munlock}.
 @end deftypefun
 
 
-@comment sys/mman.h
-@comment POSIX.1b
 @deftypefun int munlockall (void)
+@standards{POSIX.1b, sys/mman.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
 
 @code{munlockall} unlocks every page in the calling process' virtual
-address space and turn off @code{MCL_FUTURE} future locking mode.
+address space and turns off @code{MCL_FUTURE} future locking mode.
 
 The return value is zero if the function succeeds.  Otherwise, it is
 @code{-1} and @code{errno} is set accordingly.  The only way this