| .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 (3) |
| 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 (3) |
| 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 /usr/local/plan9/src/libc/port/pool.c |
| .SH SEE ALSO |
| .IR malloc (3), |
| .IR brk (3) |
| .PP |
| .B /usr/local/plan9/src/libc/port/malloc.c |
| is a complete example. |