glenda.party
term% ls -F
term% pwd
$home/manuals/9front/2/pool
term% cat index.txt
POOL(2)                       System Calls Manual                      POOL(2)

NAME
       poolalloc,  poolallocalign,  poolfree, poolmsize, poolrealloc, poolcom‐
       pact, poolcheck, poolblockcheck, pooldump - general  memory  management
       routines

SYNOPSIS
       #include <u.h>
       #include <libc.h>
       #include <pool.h>

       void*     poolalloc(Pool* pool, ulong size)

       void*     poolallocalign(Pool *pool, ulong size,
                       ulong align, long offset, ulong span)

       void poolfree(Pool* pool, void* ptr)

       ulong     poolmsize(Pool* pool, void* ptr)

       void*     poolrealloc(Pool* pool, void* ptr, ulong size)

       void poolcompact(Pool* pool)

       void poolcheck(Pool *pool)

       void poolblockcheck(Pool *pool, void *ptr)

       void pooldump(Pool *pool);

DESCRIPTION
       These routines provide a general memory management facility.  Memory is
       retrieved  from a coarser allocator (e.g.  sbrk or the kernel's xalloc)
       and then allocated to callers.  The routines are locked  and  thus  may
       safely be used in multiprocess programs.

       Poolalloc  attempts  to  allocate  a  block  of size size; it returns a
       pointer to the block when  successful  and  nil  otherwise.   The  call
       poolalloc(0)  returns a non-nil pointer.  Poolfree returns an allocated
       block to the pool.  It is an error to free a block more than once or to
       free a pointer not returned by poolalloc.  The  call  poolfree(nil)  is
       legal and is a no-op.

       Poolallocalign attempts to allocate a block of size size with the given
       alignment  constraints.   If align is non-zero, the returned pointer is
       aligned to be equal to offset modulo align.  If span is non-zero, the n
       byte block allocated will not span a span-byte boundary.

       Poolrealloc attempts to resize to nsize bytes the block associated with
       ptr, which must have been previously returned by poolalloc or poolreal‐
       loc.  If the block's size  can  be  adjusted,  a  (possibly  different)
       pointer to the new block is returned.  The contents up to the lesser of
       the  old and new sizes are unchanged.  After a successful call to pool‐
       realloc, the return value should be used rather than ptr to access  the
       block.   If  the  request cannot be satisfied, poolrealloc returns nil,
       and the old pointer remains valid.

       When blocks are allocated, there is often some extra space left at  the
       end  that would usually go unused.  Poolmsize grows the block to encom‐
       pass this extra space and returns the new size.

       The poolblockcheck and poolcheck routines validate a  single  allocated
       block or the entire pool, respectively.  They call panic (see below) if
       corruption is detected.  Pooldump prints a summary line for every block
       in the pool, using the print function (see below).

       The Pool structure itself provides much of the setup interface.

              typedef struct Pool Pool;
              struct Pool {
                  char* name;
                  uintptr             maxsize;/* of entire Pool */
                  uintptr             cursize;/* of Pool */
                  uintptr             curfree;/* total free bytes in Pool */
                  uintptr             curalloc;/* total allocated bytes in Pool */
                  ulong minarena;     /* smallest size of new arena */
                  ulong quantum;      /* allocated blocks should be multiple of */
                  ulong minblock;     /* smallest newly allocated block */
                  int   flags;
                  int   nfree;        /* number of calls to free */
                  int   lastcompact;  /* nfree at time of last poolcompact */
                  void* (*alloc)(ulong);
                  int   (*merge)(void*, void*);
                  void  (*move)(void* from, void* to);
                  void  (*lock)(Pool*);
                  void  (*unlock)(Pool*);
                  void  (*print)(Pool*, char*, ...);
                  void  (*panic)(Pool*, char*, ...);
                  void  (*logstack)(Pool*);
                  void* private;
              };
              enum {  /* flags */
                  POOL_ANTAGONISM = 1<<0,
                  POOL_PARANOIA   = 1<<1,
                  POOL_VERBOSITY  = 1<<2,
                  POOL_DEBUGGING  = 1<<3,
                  POOL_LOGGING    = 1<<4,
                  POOL_TOLERANCE  = 1<<5,
                  POOL_NOREUSE    = 1<<6,
              };

       The  pool obtains arenas of memory to manage by calling the given alloc
       routine.  The total number of requested bytes will not exceed  maxsize.
       Each allocation request will be for at least minarena bytes.

       When  a  new arena is allocated, the pool routines try to merge it with
       the surrounding arenas, in an  attempt  to  combat  fragmentation.   If
       merge  is  non-nil,  it is called with the addresses of two blocks from
       alloc that the pool routines suspect might be adjacent.   If  they  are
       not  mergeable,  merge  must return zero.  If they are mergeable, merge
       should merge them into one block in its own bookkeeping and return non-
       zero.

       To ease fragmentation and make block reuse easier, the sizes  requested
       of the pool routines are rounded up to a multiple of quantum before the
       carrying  out  requests.   If,  after rounding, the block size is still
       less than minblock bytes, minblock will be used as the block size.

       Poolcompact defragments the pool, moving blocks in order  to  aggregate
       the  free space.  Each time it moves a block, it notifies the move rou‐
       tine that the contents have moved.  At the time that  move  is  called,
       the  contents have already moved, so from should never be dereferenced.
       If no move routine is supplied (i.e. it is nil), then calling  poolcom‐
       pact is a no-op.

       When  the pool routines need to allocate a new arena but cannot, either
       because alloc has returned nil or because doing so would use more  than
       maxsize  bytes, poolcompact is called once to defragment the memory and
       the request is retried.

       Pools are protected by the pool routines calling  lock  (when  non-nil)
       before modifying the pool, and calling unlock when finished.

       When  internal  corruption is detected, panic is called with a print(2)
       style argument that specifies what happened.  It is assumed that  panic
       never  returns.  When the pool routines wish to convey a message to the
       caller (usually because logging is turned  on;  see  below),  print  is
       called, also with a print(2) style argument.

       Flags  is a bit vector that tweaks the behavior of the pool routines in
       various ways.  Most are useful for debugging in  one  way  or  another.
       When  POOL_ANTAGONISM  is  set,  poolalloc  fills  blocks with non-zero
       garbage before releasing them to  the  user,  and  poolfree  fills  the
       blocks  on receipt.  This tickles both user programs and the innards of
       the allocator.  Specifically, each 32-bit word of the memory is  marked
       with  a  pointer  value  exclusive-or'ed  with a constant.  The pointer
       value is the pointer to the beginning of the allocated  block  and  the
       constant  varies  in  order  to  distinguish different markings.  Freed
       blocks use the constant 0xF7000000, newly allocated blocks  0xF9000000,
       and  newly  created  unallocated  blocks  0xF1000000.   For example, if
       POOL_ANTAGONISM is set  and  poolalloc  returns  a  block  starting  at
       0x00012345,  each word of the block will contain the value 0xF90012345.
       Recognizing these numbers in memory-related crashes can  help  diagnose
       things like double-frees or dangling pointers.

       Setting  POOL_PARANOIA  causes  the  allocator  to walk the entire pool
       whenever locking or unlocking itself,  looking  for  corruption.   This
       slows runtime by a few orders of magnitude when many blocks are in use.
       If  POOL_VERBOSITY  is  set,  the entire pool structure is printed (via
       print) each time the pool is locked or  unlocked.   POOL_DEBUGGING  en‐
       ables  internal  debugging  output,  whose  format  is  unspecified and
       volatile.  It should not be used by most programs.   When  POOL_LOGGING
       is  set, a single line is printed via print at the beginning and end of
       each pool call.  If logstack is not nil, it will  be  called  as  well.
       This  provides  a  mechanism for external programs to search for leaks.
       (See leak(1) for one such program.)

       The pool routines are strict about the amount of space callers use.  If
       even a single byte is written past the end of the allotted space  of  a
       block, they will notice when that block is next used in a call to pool‐
       realloc  or  free  (or  at  the  next  entry  into  the allocator, when
       POOL_PARANOIA is set), and panic will be called.  Since  forgetting  to
       allocate  space for the terminating NUL on strings is such a common er‐
       ror, if POOL_TOLERANCE is set and a single NUL is  found  written  past
       the end of a block, print will be called with a notification, but panic
       will not be.

       When  POOL_NOREUSE is set, poolfree fills the passed block with garbage
       rather than return it to the free pool.

SOURCE
       /sys/src/libc/port/pool.c

SEE ALSO
       malloc(2), brk(2)

       /sys/src/libc/port/malloc.c is a complete example.

                                                                       POOL(2)