diff options
Diffstat (limited to 'man/man3/pool.3')
-rw-r--r-- | man/man3/pool.3 | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/man/man3/pool.3 b/man/man3/pool.3 new file mode 100644 index 00000000..0c9a8d49 --- /dev/null +++ b/man/man3/pool.3 @@ -0,0 +1,329 @@ +.TH POOL 3 +.SH NAME +poolalloc, poolfree, poolmsize, poolrealloc, poolcompact, poolcheck, poolblockcheck, +pooldump \- general memory management routines +.SH SYNOPSIS +.B #include <u.h> +.PP +.B #include <libc.h> +.PP +.B #include <pool.h> +.PP +.B +void* poolalloc(Pool* pool, ulong size) +.PP +.B +void poolfree(Pool* pool, void* ptr) +.PP +.B +ulong poolmsize(Pool* pool, void* ptr) +.PP +.B +void* poolrealloc(Pool* pool, void* ptr, ulong size) +.PP +.B +void poolcompact(Pool* pool) +.PP +.B +void poolcheck(Pool *pool) +.PP +.B +void poolblockcheck(Pool *pool, void *ptr) +.PP +.B +void pooldump(Pool *pool); +.SH DESCRIPTION +These routines provide a general memory management facility. +Memory is retrieved from a coarser allocator (e.g. +.I sbrk +or the kernel's +.IR xalloc ) +and then allocated to callers. +The routines are locked and thus may safely be used in +multiprocess programs. +.PP +.I Poolalloc +attempts to allocate a block of size +.BR size ; +it returns a pointer to the block when successful and nil otherwise. +The call +.B "poolalloc(0) +returns a non-nil pointer. +.I 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 +.IR poolalloc . +The call +.B "poolfree(nil) +is legal and is a no-op. +.I Poolrealloc +attempts to resize to +.B nsize +bytes the block associated with +.BR ptr , +which must have been previously returned by +.I poolalloc +or +.IR poolrealloc . +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 +.IR poolrealloc , +the return value should be used rather than +.B ptr +to access the block. +If the request cannot be satisfied, +.I poolrealloc +returns nil, and the old pointer remains valid. +.PP +When blocks are allocated, there is often some extra space left at the end +that would usually go unused. +.IR Poolmsize +grows the block to encompass this extra space and returns the new size. +.PP +The +.I poolblockcheck +and +.I poolcheck +routines validate a single allocated block or the entire pool, respectively. +They call +.B panic +(see below) +if corruption is detected. +.I Pooldump +prints a summary line for every block in the +pool, using the +.B print +function (see below). +.PP +The +.B Pool +structure itself provides much of the setup interface. +.IP +.EX +.ta \w'\fL 'u +\w'\fLulong 'u +\w'\fLlastcompact; 'u +typedef struct Pool Pool; +struct Pool { + char* name; + ulong maxsize; /* of entire Pool */ + ulong cursize; /* of Pool */ + ulong curfree; /* total free bytes in Pool */ + ulong 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; +}; +.ta \w'\fL 'u +\w'POOL_ANTAGONISM 'u +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, +}; +.EE +.PP +The pool obtains arenas of memory to manage by calling the the given +.B alloc +routine. +The total number of requested bytes will not exceed +.BR maxsize . +Each allocation request will be for at least +.B minarena +bytes. +.PP +When a new arena is allocated, the pool routines try to +merge it with the surrounding arenas, in an attempt to combat fragmentation. +If +.B merge +is non-nil, it is called with the addresses of two blocks from +.B alloc +that the pool routines suspect might be adjacent. +If they are not mergeable, +.B merge +must return zero. +If they are mergeable, +.B merge +should merge them into one block in its own bookkeeping +and return non-zero. +.PP +To ease fragmentation and make +block reuse easier, the sizes requested of the pool routines are rounded up to a multiple of +.B quantum +before +the carrying out requests. +If, after rounding, the block size is still less than +.B minblock +bytes, +.B minblock +will be used as the block size. +.PP +.I Poolcompact +defragments the pool, moving blocks in order to aggregate +the free space. +Each time it moves a block, it notifies the +.B move +routine that the contents have moved. +At the time that +.B move +is called, the contents have already moved, +so +.B from +should never be dereferenced. +If no +.B move +routine is supplied (i.e. it is nil), then calling +.I poolcompact +is a no-op. +.PP +When the pool routines need to allocate a new arena but cannot, +either because +.B alloc +has returned nil or because doing so would use more than +.B maxsize +bytes, +.I poolcompact +is called once to defragment the memory +and the request is retried. +.PP +.I Pools +are protected by the pool routines calling +.B lock +(when non-nil) +before modifying the pool, and +calling +.B unlock +when finished. +.PP +When internal corruption is detected, +.B panic +is called with a +.IR print (2) +style argument that specifies what happened. +It is assumed that +.B panic +never returns. +When the pool routines wish to convey a message +to the caller (usually because logging is turned on; see below), +.B print +is called, also with a +.IR print (2) +style argument. +.PP +.B 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 +.B POOL_ANTAGONISM +is set, +.I poolalloc +fills blocks with non-zero garbage before releasing them to the user, +and +.I 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 +.BR 0xF7000000 , +newly allocated blocks +.BR 0xF9000000 , +and newly created unallocated blocks +.BR 0xF1000000 . +For example, if +.B POOL_ANTAGONISM +is set and +.I poolalloc +returns a block starting at +.BR 0x00012345 , +each word of the block will contain the value +.BR 0xF90012345 . +Recognizing these numbers in memory-related crashes can +help diagnose things like double-frees or dangling pointers. +.PP +Setting +.B 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 +.B POOL_VERBOSITY +is set, +the entire pool structure is printed +(via +.BR print ) +each time the pool is locked or unlocked. +.B POOL_DEBUGGING +enables internal +debugging output, +whose format is unspecified and volatile. +It should not be used by most programs. +When +.B POOL_LOGGING +is set, a single line is printed via +.B print +at the beginning and end of each pool call. +If +.B logstack +is not nil, +it will be called as well. +This provides a mechanism for external programs to search for leaks. +(See +.IR leak (1) +for one such program.) +.PP +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 +.I poolrealloc +or +.I free +(or at the next entry into the allocator, when +.B POOL_PARANOIA +is set), +and +.B panic +will be called. +Since forgetting to allocate space for the +terminating NUL on strings is such a common error, +if +.B POOL_TOLERANCE +is set and a single NUL is found written past the end of a block, +.B print +will be called with a notification, but +.B panic +will not be. +.PP +When +.B POOL_NOREUSE +is set, +.B poolfree +fills the passed block with garbage rather than +return it to the free pool. +.SH SOURCE +.B /sys/src/libc/port/pool.c +.SH SEE ALSO +.IR malloc (2), +.IR brk (2) +.PP +.B /sys/src/libc/port/malloc.c +is a complete example. |