This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [MTASCsft PATCH 18/??] MT-, AS- and AC-Safety docs: manual/memory.texi


On 01/27/2014 09:28 PM, Alexandre Oliva wrote:
> 
> for ChangeLog
> 
> 	[BZ #12751]
> 	* manual/memory.texi: Document MTASC-safety properties.

OK to checkin.

Great work on the detailed review of the memory-related functions.

> ---
>  NEWS               |    2 
>  manual/memory.texi |  533 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 534 insertions(+), 1 deletion(-)
> 
> diff --git a/NEWS b/NEWS
> index 52ae5fd..222d4df 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -10,7 +10,7 @@ Version 2.19
>  * The following bugs are resolved with this release:
>  
>    156, 387, 431, 762, 832, 926, 2801, 4772, 6786, 6787, 6807, 6810, 7003,
> -  9721, 9954, 10253, 10278, 11087, 11157, 11214, 12100, 12486, 12986,
> +  9721, 9954, 10253, 10278, 11087, 11157, 11214, 12100, 12486, 12751, 12986,
>    13028, 13982, 13985, 14029, 14032, 14120, 14143, 14155, 14286, 14547,
>    14699, 14752, 14782, 14876, 14910, 15004, 15048, 15073, 15089, 15128,
>    15218, 15268, 15277, 15308, 15362, 15374, 15400, 15425, 15427, 15483,
> diff --git a/manual/memory.texi b/manual/memory.texi
> index 55a6a50..4beb322 100644
> --- a/manual/memory.texi
> +++ b/manual/memory.texi
> @@ -302,6 +302,245 @@ this function is in @file{stdlib.h}.
>  @comment malloc.h stdlib.h
>  @comment ISO
>  @deftypefun {void *} malloc (size_t @var{size})
> +@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_lookup ok
> +@c   tsd_getspecific ok, TLS
> +@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     tsd_setspecific ok, TLS
> +@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      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
> @@ -407,6 +646,21 @@ The prototype for this function is in @file{stdlib.h}.
>  @comment malloc.h stdlib.h
>  @comment ISO
>  @deftypefun void free (void *@var{ptr})
> +@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
> @@ -414,6 +668,8 @@ by @var{ptr}.
>  @comment stdlib.h
>  @comment Sun
>  @deftypefun void cfree (void *@var{ptr})
> +@safety{@prelim{}@mtsafe{}@asunsafe{@asulock{}}@acunsafe{@aculock{} @acsfd{} @acsmem{}}}
> +@c alias to free
>  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
> @@ -471,6 +727,48 @@ is declared in @file{stdlib.h}.
>  @comment malloc.h stdlib.h
>  @comment ISO
>  @deftypefun {void *} realloc (void *@var{ptr}, size_t @var{newsize})
> +@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}.
>  
> @@ -530,6 +828,25 @@ is declared in @file{stdlib.h}.
>  @comment malloc.h stdlib.h
>  @comment ISO
>  @deftypefun {void *} calloc (size_t @var{count}, size_t @var{eltsize})
> +@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_lookup dup ok
> +@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.
> @@ -622,6 +939,8 @@ power of two than that, use @code{aligned_alloc} or @code{posix_memalign}.
>  
>  @comment stdlib.h
>  @deftypefun {void *} aligned_alloc (size_t @var{alignment}, size_t @var{size})
> +@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}.
> @@ -645,6 +964,29 @@ portability to modern non-POSIX systems than @code{posix_memalign}.
>  @comment malloc.h
>  @comment BSD
>  @deftypefun {void *} memalign (size_t @var{boundary}, size_t @var{size})
> +@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
> @@ -670,6 +1012,10 @@ The @code{memalign} function is obsolete and @code{aligned_alloc} or
>  @comment stdlib.h
>  @comment POSIX
>  @deftypefun int posix_memalign (void **@var{memptr}, size_t @var{alignment}, size_t @var{size})
> +@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
> @@ -698,6 +1044,39 @@ systems that do not support @w{ISO C11}.
>  @comment malloc.h stdlib.h
>  @comment BSD
>  @deftypefun {void *} valloc (size_t @var{size})
> +@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   thread_atfork @asulock @aculock @acsfd @acsmem
> +@c    __register_atfork @asulock @aculock @acsfd @acsmem
> +@c     lll_lock (__fork_lock) @asulock @aculock
> +@c     fork_handler_alloc @asulock @aculock @acsfd @acsmem
> +@c      calloc dup @asulock @aculock @acsfd @acsmem
> +@c     __linkin_atfork ok
> +@c      catomic_compare_and_exchange_bool_acq ok
> +@c     lll_unlock (__fork_lock) @aculock
> +@c   *_environ @mtsenv
> +@c   next_env_entry ok
> +@c   strcspn dup ok
> +@c   __libc_mallopt dup @mtasuconst:mallopt [setting mp_]
> +@c   __malloc_check_init @mtasuconst:malloc_hooks [setting hooks]
> +@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:
>  
> @@ -725,6 +1104,14 @@ 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:
> @@ -781,6 +1168,17 @@ declared in @file{mcheck.h}.
>  @comment mcheck.h
>  @comment GNU
>  @deftypefun int mcheck (void (*@var{abortfn}) (enum mcheck_status @var{status}))
> +@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}.
> @@ -823,6 +1221,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
> @@ -1137,6 +1547,24 @@ space's data segment).
>  @comment malloc.h
>  @comment SVID
>  @deftypefun {struct mallinfo} mallinfo (void)
> +@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
> @@ -1235,6 +1663,20 @@ penalties for the program if the debugging mode is not enabled.
>  @comment mcheck.h
>  @comment GNU
>  @deftypefun void mtrace (void)
> +@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
> @@ -1258,6 +1700,11 @@ systems.  The prototype can be found in @file{mcheck.h}.
>  @comment mcheck.h
>  @comment GNU
>  @deftypefun void muntrace (void)
> +@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.
> @@ -1569,6 +2016,20 @@ as an obstack, it must initialize the obstack by calling
>  @comment obstack.h
>  @comment GNU
>  @deftypefun int obstack_init (struct obstack *@var{obstack-ptr})
> +@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
> @@ -1624,6 +2085,10 @@ The most direct way to allocate an object in an obstack is with
>  @comment obstack.h
>  @comment GNU
>  @deftypefun {void *} obstack_alloc (struct obstack *@var{obstack-ptr}, int @var{size})
> +@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}
> @@ -1658,6 +2123,10 @@ To allocate a block with specified contents, use the function
>  @comment obstack.h
>  @comment GNU
>  @deftypefun {void *} obstack_copy (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
> +@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
> @@ -1667,6 +2136,10 @@ bytes of data starting at @var{address}.  It calls
>  @comment obstack.h
>  @comment GNU
>  @deftypefun {void *} obstack_copy0 (struct obstack *@var{obstack-ptr}, void *@var{address}, int @var{size})
> +@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
> @@ -1699,6 +2172,10 @@ in the same obstack.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_free (struct obstack *@var{obstack-ptr}, void *@var{object})
> +@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
> @@ -1803,6 +2280,13 @@ 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})
> +@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
> @@ -1810,6 +2294,10 @@ The most basic function for adding to a growing object is
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_grow (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
> +@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
> @@ -1819,6 +2307,12 @@ bytes of data to the growing object, copying the contents from
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_grow0 (struct obstack *@var{obstack-ptr}, void *@var{data}, int @var{size})
> +@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.
> @@ -1827,6 +2321,10 @@ character.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_1grow (struct obstack *@var{obstack-ptr}, char @var{c})
> +@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
> @@ -1834,6 +2332,10 @@ It adds a single byte containing @var{c} to the growing object.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_ptr_grow (struct obstack *@var{obstack-ptr}, void *@var{data})
> +@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}.
> @@ -1842,6 +2344,10 @@ containing the value of @var{data}.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_int_grow (struct obstack *@var{obstack-ptr}, int @var{data})
> +@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}.
> @@ -1850,6 +2356,8 @@ the growing object and initializes them with the value of @var{data}.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun {void *} obstack_finish (struct obstack *@var{obstack-ptr})
> +@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.
>  
> @@ -1869,6 +2377,7 @@ declared as follows:
>  @comment obstack.h
>  @comment GNU
>  @deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
> +@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.
> @@ -1912,6 +2421,7 @@ in the current chunk.  It is declared as follows:
>  @comment obstack.h
>  @comment GNU
>  @deftypefun int obstack_room (struct obstack *@var{obstack-ptr})
> +@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.
> @@ -1923,6 +2433,9 @@ 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})
> +@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
> @@ -1930,6 +2443,8 @@ character @var{c} to the growing object in obstack @var{obstack-ptr}.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_ptr_grow_fast (struct obstack *@var{obstack-ptr}, void *@var{data})
> +@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}.
> @@ -1938,6 +2453,8 @@ obstack @var{obstack-ptr}.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_int_grow_fast (struct obstack *@var{obstack-ptr}, int @var{data})
> +@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}.
> @@ -1946,6 +2463,8 @@ containing the value of @var{data} to the growing object in obstack
>  @comment obstack.h
>  @comment GNU
>  @deftypefun void obstack_blank_fast (struct obstack *@var{obstack-ptr}, int @var{size})
> +@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
> @@ -2004,6 +2523,7 @@ still growing it.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun {void *} obstack_base (struct obstack *@var{obstack-ptr})
> +@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
> @@ -2017,6 +2537,7 @@ chunk).
>  @comment obstack.h
>  @comment GNU
>  @deftypefun {void *} obstack_next_free (struct obstack *@var{obstack-ptr})
> +@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}
> @@ -2026,6 +2547,8 @@ returns the same value as @code{obstack_base}.
>  @comment obstack.h
>  @comment GNU
>  @deftypefun int obstack_object_size (struct obstack *@var{obstack-ptr})
> +@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
>  
> @@ -2050,6 +2573,7 @@ this:
>  @comment obstack.h
>  @comment GNU
>  @deftypefn Macro int obstack_alignment_mask (struct obstack *@var{obstack-ptr})
> +@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
> @@ -2117,6 +2641,7 @@ 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})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>  This returns the chunk size of the given obstack.
>  @end deftypefn
>  
> @@ -2236,6 +2761,7 @@ a BSD extension.
>  @comment stdlib.h
>  @comment GNU, BSD
>  @deftypefun {void *} alloca (size_t @var{size})
> +@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
> @@ -2418,6 +2944,7 @@ system calls.
>  @comment unistd.h
>  @comment BSD
>  @deftypefun int brk (void *@var{addr})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>  
>  @code{brk} sets the high end of the calling process' data segment to
>  @var{addr}.
> @@ -2460,6 +2987,8 @@ exceed the process' data storage limit.
>  @comment unistd.h
>  @comment BSD
>  @deftypefun void *sbrk (ptrdiff_t @var{delta})
> +@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
> @@ -2599,6 +3128,7 @@ this requirement.
>  @comment sys/mman.h
>  @comment POSIX.1b
>  @deftypefun int mlock (const void *@var{addr}, size_t @var{len})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>  
>  @code{mlock} locks a range of the calling process' virtual pages.
>  
> @@ -2652,6 +3182,7 @@ wouldn't know what address to tell @code{mlock}.
>  @comment sys/mman.h
>  @comment POSIX.1b
>  @deftypefun int munlock (const void *@var{addr}, size_t @var{len})
> +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
>  
>  @code{munlock} unlocks a range of the calling process' virtual pages.
>  
> @@ -2664,6 +3195,7 @@ failure.
>  @comment sys/mman.h
>  @comment POSIX.1b
>  @deftypefun int mlockall (int @var{flags})
> +@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
> @@ -2740,6 +3272,7 @@ with @code{munlockall} and @code{munlock}.
>  @comment sys/mman.h
>  @comment POSIX.1b
>  @deftypefun int munlockall (void)
> +@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.
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]