ref: e391b7ec8c0dc746a70725f3fc598def0419d1e6
dir: /sys/man/2/pool/
.TH POOL 2 .SH NAME poolalloc, poolallocalign, poolfree, poolmsize, poolisoverlap, poolrealloc, poolcompact, poolcheck, poolblockcheck, pooldump \- general memory management routines .SH SYNOPSIS .B #include <u.h> .br .B #include <libc.h> .br .B #include <pool.h> .PP .B void* poolalloc(Pool* pool, ulong size) .PP .B void* poolallocalign(Pool *pool, ulong size, .br .B ulong align, long offset, ulong span) .PP .B void poolfree(Pool* pool, void* ptr) .PP .B ulong poolmsize(Pool* pool, void* ptr) .PP .B int poolisoverlap(Pool* pool, void* ptr, ulong len) .PP .B void poolreset(Pool* pool) .PP .B void* poolrealloc(Pool* pool, void* ptr, ulong size) .PP .B int 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. .PP .I Poolallocalign attempts to allocate a block of size .B size with the given alignment constraints. If .I align is non-zero, the returned pointer is aligned to be equal to .I offset modulo .IR align . If .I span is non-zero, the .I n byte block allocated will not span a .IR span -byte boundary. .PP .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 .I Poolisoverlap checks if the byte span .BR [ptr , ptr + len) overlaps the arenas of the specified .BR pool , returning non-zero when there is overlap or zero if none. .PP .I Poolreset clears the pool counters and frees all arenas. The arenas are filled with a pattern before freeing them when the .B POOL_ANTAGONISM flag is set. When the .B free function of the pool is non-nil, it is called for each arena, passing its pointer and 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; 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 (*free)(void*, ulong); 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 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 , freed arenas after .I poolreset .BR 0xFF000000 . 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.