1*074ba9b2SJens Wiklander 2*074ba9b2SJens Wiklander BGET -- Memory Allocator 3*074ba9b2SJens Wiklander ========================== 4*074ba9b2SJens Wiklander 5*074ba9b2SJens Wiklander by John Walker 6*074ba9b2SJens Wiklander http://www.fourmilab.ch/ 7*074ba9b2SJens Wiklander 8*074ba9b2SJens WiklanderBGET is a comprehensive memory allocation package which is easily 9*074ba9b2SJens Wiklanderconfigured to the needs of an application. BGET is efficient in both 10*074ba9b2SJens Wiklanderthe time needed to allocate and release buffers and in the memory 11*074ba9b2SJens Wiklanderoverhead required for buffer pool management. It automatically 12*074ba9b2SJens Wiklanderconsolidates contiguous space to minimise fragmentation. BGET is 13*074ba9b2SJens Wiklanderconfigured by compile-time definitions, Major options include: 14*074ba9b2SJens Wiklander 15*074ba9b2SJens Wiklander * A built-in test program to exercise BGET and 16*074ba9b2SJens Wiklander demonstrate how the various functions are used. 17*074ba9b2SJens Wiklander 18*074ba9b2SJens Wiklander * Allocation by either the "first fit" or "best fit" 19*074ba9b2SJens Wiklander method. 20*074ba9b2SJens Wiklander 21*074ba9b2SJens Wiklander * Wiping buffers at release time to catch code which 22*074ba9b2SJens Wiklander references previously released storage. 23*074ba9b2SJens Wiklander 24*074ba9b2SJens Wiklander * Built-in routines to dump individual buffers or the 25*074ba9b2SJens Wiklander entire buffer pool. 26*074ba9b2SJens Wiklander 27*074ba9b2SJens Wiklander * Retrieval of allocation and pool size statistics. 28*074ba9b2SJens Wiklander 29*074ba9b2SJens Wiklander * Quantisation of buffer sizes to a power of two to 30*074ba9b2SJens Wiklander satisfy hardware alignment constraints. 31*074ba9b2SJens Wiklander 32*074ba9b2SJens Wiklander * Automatic pool compaction, growth, and shrinkage by 33*074ba9b2SJens Wiklander means of call-backs to user defined functions. 34*074ba9b2SJens Wiklander 35*074ba9b2SJens WiklanderApplications of BGET can range from storage management in ROM-based 36*074ba9b2SJens Wiklanderembedded programs to providing the framework upon which a multitasking 37*074ba9b2SJens Wiklandersystem incorporating garbage collection is constructed. BGET 38*074ba9b2SJens Wiklanderincorporates extensive internal consistency checking using the 39*074ba9b2SJens Wiklander<assert.h> mechanism; all these checks can be turned off by compiling 40*074ba9b2SJens Wiklanderwith NDEBUG defined, yielding a version of BGET with minimal size and 41*074ba9b2SJens Wiklandermaximum speed. 42*074ba9b2SJens Wiklander 43*074ba9b2SJens WiklanderThe basic algorithm underlying BGET has withstood the test of time; more 44*074ba9b2SJens Wiklanderthan 25 years have passed since the first implementation of this code. 45*074ba9b2SJens WiklanderAnd yet, it is substantially more efficient than the native allocation 46*074ba9b2SJens Wiklanderschemes of many operating systems: the Macintosh and Microsoft Windows 47*074ba9b2SJens Wiklanderto name two, on which programs have obtained substantial speed-ups by 48*074ba9b2SJens Wiklanderlayering BGET as an application level memory manager atop the underlying 49*074ba9b2SJens Wiklandersystem's. 50*074ba9b2SJens Wiklander 51*074ba9b2SJens WiklanderBGET has been implemented on the largest mainframes and the lowest of 52*074ba9b2SJens Wiklandermicroprocessors. It has served as the core for multitasking operating 53*074ba9b2SJens Wiklandersystems, multi-thread applications, embedded software in data network 54*074ba9b2SJens Wiklanderswitching processors, and a host of C programs. And while it has 55*074ba9b2SJens Wiklanderaccreted flexibility and additional options over the years, it remains 56*074ba9b2SJens Wiklanderfast, memory efficient, portable, and easy to integrate into your 57*074ba9b2SJens Wiklanderprogram. 58*074ba9b2SJens Wiklander 59*074ba9b2SJens Wiklander 60*074ba9b2SJens WiklanderBGET IMPLEMENTATION ASSUMPTIONS 61*074ba9b2SJens Wiklander=============================== 62*074ba9b2SJens Wiklander 63*074ba9b2SJens WiklanderBGET is written in as portable a dialect of C as possible. The only 64*074ba9b2SJens Wiklanderfundamental assumption about the underlying hardware architecture is 65*074ba9b2SJens Wiklanderthat memory is allocated is a linear array which can be addressed as a 66*074ba9b2SJens Wiklandervector of C "char" objects. On segmented address space architectures, 67*074ba9b2SJens Wiklanderthis generally means that BGET should be used to allocate storage within 68*074ba9b2SJens Wiklandera single segment (although some compilers simulate linear address spaces 69*074ba9b2SJens Wiklanderon segmented architectures). On segmented architectures, then, BGET 70*074ba9b2SJens Wiklanderbuffer pools may not be larger than a segment, but since BGET allows any 71*074ba9b2SJens Wiklandernumber of separate buffer pools, there is no limit on the total storage 72*074ba9b2SJens Wiklanderwhich can be managed, only on the largest individual object which can be 73*074ba9b2SJens Wiklanderallocated. Machines with a linear address architecture, such as the 74*074ba9b2SJens WiklanderVAX, 680x0, Sparc, MIPS, or the Intel 80386 and above in native mode, 75*074ba9b2SJens Wiklandermay use BGET without restriction. 76*074ba9b2SJens Wiklander 77*074ba9b2SJens Wiklander 78*074ba9b2SJens WiklanderGETTING STARTED WITH BGET 79*074ba9b2SJens Wiklander========================= 80*074ba9b2SJens Wiklander 81*074ba9b2SJens WiklanderAlthough BGET can be configured in a multitude of fashions, there are 82*074ba9b2SJens Wiklanderthree basic ways of working with BGET. The functions mentioned below 83*074ba9b2SJens Wiklanderare documented in the following section. Please excuse the forward 84*074ba9b2SJens Wiklanderreferences which are made in the interest of providing a roadmap to 85*074ba9b2SJens Wiklanderguide you to the BGET functions you're likely to need. 86*074ba9b2SJens Wiklander 87*074ba9b2SJens WiklanderEmbedded Applications 88*074ba9b2SJens Wiklander--------------------- 89*074ba9b2SJens Wiklander 90*074ba9b2SJens WiklanderEmbedded applications typically have a fixed area of memory dedicated to 91*074ba9b2SJens Wiklanderbuffer allocation (often in a separate RAM address space distinct from 92*074ba9b2SJens Wiklanderthe ROM that contains the executable code). To use BGET in such an 93*074ba9b2SJens Wiklanderenvironment, simply call bpool() with the start address and length of 94*074ba9b2SJens Wiklanderthe buffer pool area in RAM, then allocate buffers with bget() and 95*074ba9b2SJens Wiklanderrelease them with brel(). Embedded applications with very limited RAM 96*074ba9b2SJens Wiklanderbut abundant CPU speed may benefit by configuring BGET for BestFit 97*074ba9b2SJens Wiklanderallocation (which is usually not worth it in other environments). 98*074ba9b2SJens Wiklander 99*074ba9b2SJens WiklanderMalloc() Emulation 100*074ba9b2SJens Wiklander------------------ 101*074ba9b2SJens Wiklander 102*074ba9b2SJens WiklanderIf the C library malloc() function is too slow, not present in your 103*074ba9b2SJens Wiklanderdevelopment environment (for example, an a native Windows or Macintosh 104*074ba9b2SJens Wiklanderprogram), or otherwise unsuitable, you can replace it with BGET. 105*074ba9b2SJens WiklanderInitially define a buffer pool of an appropriate size with 106*074ba9b2SJens Wiklanderbpool()--usually obtained by making a call to the operating system's 107*074ba9b2SJens Wiklanderlow-level memory allocator. Then allocate buffers with bget(), bgetz(), 108*074ba9b2SJens Wiklanderand bgetr() (the last two permit the allocation of buffers initialised 109*074ba9b2SJens Wiklanderto zero and [inefficient] re-allocation of existing buffers for 110*074ba9b2SJens Wiklandercompatibility with C library functions). Release buffers by calling 111*074ba9b2SJens Wiklanderbrel(). If a buffer allocation request fails, obtain more storage from 112*074ba9b2SJens Wiklanderthe underlying operating system, add it to the buffer pool by another 113*074ba9b2SJens Wiklandercall to bpool(), and continue execution. 114*074ba9b2SJens Wiklander 115*074ba9b2SJens WiklanderAutomatic Storage Management 116*074ba9b2SJens Wiklander---------------------------- 117*074ba9b2SJens Wiklander 118*074ba9b2SJens WiklanderYou can use BGET as your application's native memory manager and 119*074ba9b2SJens Wiklanderimplement automatic storage pool expansion, contraction, and optionally 120*074ba9b2SJens Wiklanderapplication-specific memory compaction by compiling BGET with the BECtl 121*074ba9b2SJens Wiklandervariable defined, then calling bectl() and supplying functions for 122*074ba9b2SJens Wiklanderstorage compaction, acquisition, and release, as well as a standard pool 123*074ba9b2SJens Wiklanderexpansion increment. All of these functions are optional (although it 124*074ba9b2SJens Wiklanderdoesn't make much sense to provide a release function without an 125*074ba9b2SJens Wiklanderacquisition function, does it?). Once the call-back functions have been 126*074ba9b2SJens Wiklanderdefined with bectl(), you simply use bget() and brel() to allocate and 127*074ba9b2SJens Wiklanderrelease storage as before. You can supply an initial buffer pool with 128*074ba9b2SJens Wiklanderbpool() or rely on automatic allocation to acquire the entire pool. 129*074ba9b2SJens WiklanderWhen a call on bget() cannot be satisfied, BGET first checks if a 130*074ba9b2SJens Wiklandercompaction function has been supplied. If so, it is called (with the 131*074ba9b2SJens Wiklanderspace required to satisfy the allocation request and a sequence number 132*074ba9b2SJens Wiklanderto allow the compaction routine to be called successively without 133*074ba9b2SJens Wiklanderlooping). If the compaction function is able to free any storage (it 134*074ba9b2SJens Wiklanderneedn't know whether the storage it freed was adequate) it should return 135*074ba9b2SJens Wiklandera nonzero value, whereupon BGET will retry the allocation request and, 136*074ba9b2SJens Wiklanderif it fails again, call the compaction function again with the 137*074ba9b2SJens Wiklandernext-higher sequence number. 138*074ba9b2SJens Wiklander 139*074ba9b2SJens WiklanderIf the compaction function returns zero, indicating failure to free 140*074ba9b2SJens Wiklanderspace, or no compaction function is defined, BGET next tests whether a 141*074ba9b2SJens Wiklandernon-NULL allocation function was supplied to bectl(). If so, that 142*074ba9b2SJens Wiklanderfunction is called with an argument indicating how many bytes of 143*074ba9b2SJens Wiklanderadditional space are required. This will be the standard pool expansion 144*074ba9b2SJens Wiklanderincrement supplied in the call to bectl() unless the original bget() 145*074ba9b2SJens Wiklandercall requested a buffer larger than this; buffers larger than the 146*074ba9b2SJens Wiklanderstandard pool block can be managed "off the books" by BGET in this mode. 147*074ba9b2SJens WiklanderIf the allocation function succeeds in obtaining the storage, it returns 148*074ba9b2SJens Wiklandera pointer to the new block and BGET expands the buffer pool; if it 149*074ba9b2SJens Wiklanderfails, the allocation request fails and returns NULL to the caller. If 150*074ba9b2SJens Wiklandera non-NULL release function is supplied, expansion blocks which become 151*074ba9b2SJens Wiklandertotally empty are released to the global free pool by passing their 152*074ba9b2SJens Wiklanderaddresses to the release function. 153*074ba9b2SJens Wiklander 154*074ba9b2SJens WiklanderEquipped with appropriate allocation, release, and compaction functions, 155*074ba9b2SJens WiklanderBGET can be used as part of very sophisticated memory management 156*074ba9b2SJens Wiklanderstrategies, including garbage collection. (Note, however, that BGET is 157*074ba9b2SJens Wiklander*not* a garbage collector by itself, and that developing such a system 158*074ba9b2SJens Wiklanderrequires much additional logic and careful design of the application's 159*074ba9b2SJens Wiklandermemory allocation strategy.) 160*074ba9b2SJens Wiklander 161*074ba9b2SJens Wiklander 162*074ba9b2SJens WiklanderBGET FUNCTION DESCRIPTIONS 163*074ba9b2SJens Wiklander========================== 164*074ba9b2SJens Wiklander 165*074ba9b2SJens WiklanderFunctions implemented by BGET (some are enabled by certain of the 166*074ba9b2SJens Wiklanderoptional settings below): 167*074ba9b2SJens Wiklander 168*074ba9b2SJens Wiklander void bpool(void *buffer, bufsize len); 169*074ba9b2SJens Wiklander 170*074ba9b2SJens WiklanderCreate a buffer pool of <len> bytes, using the storage starting at 171*074ba9b2SJens Wiklander<buffer>. You can call bpool() subsequently to contribute additional 172*074ba9b2SJens Wiklanderstorage to the overall buffer pool. 173*074ba9b2SJens Wiklander 174*074ba9b2SJens Wiklander void *bget(bufsize size); 175*074ba9b2SJens Wiklander 176*074ba9b2SJens WiklanderAllocate a buffer of <size> bytes. The address of the buffer is 177*074ba9b2SJens Wiklanderreturned, or NULL if insufficient memory was available to allocate the 178*074ba9b2SJens Wiklanderbuffer. 179*074ba9b2SJens Wiklander 180*074ba9b2SJens Wiklander void *bgetz(bufsize size); 181*074ba9b2SJens Wiklander 182*074ba9b2SJens WiklanderAllocate a buffer of <size> bytes and clear it to all zeroes. The 183*074ba9b2SJens Wiklanderaddress of the buffer is returned, or NULL if insufficient memory was 184*074ba9b2SJens Wiklanderavailable to allocate the buffer. 185*074ba9b2SJens Wiklander 186*074ba9b2SJens Wiklander void *bgetr(void *buffer, bufsize newsize); 187*074ba9b2SJens Wiklander 188*074ba9b2SJens WiklanderReallocate a buffer previously allocated by bget(), changing its size to 189*074ba9b2SJens Wiklander<newsize> and preserving all existing data. NULL is returned if 190*074ba9b2SJens Wiklanderinsufficient memory is available to reallocate the buffer, in which case 191*074ba9b2SJens Wiklanderthe original buffer remains intact. 192*074ba9b2SJens Wiklander 193*074ba9b2SJens Wiklander void brel(void *buf); 194*074ba9b2SJens Wiklander 195*074ba9b2SJens WiklanderReturn the buffer <buf>, previously allocated by bget(), to the free 196*074ba9b2SJens Wiklanderspace pool. 197*074ba9b2SJens Wiklander 198*074ba9b2SJens Wiklander void bectl(int (*compact)(bufsize sizereq, int sequence), 199*074ba9b2SJens Wiklander void *(*acquire)(bufsize size), 200*074ba9b2SJens Wiklander void (*release)(void *buf), 201*074ba9b2SJens Wiklander bufsize pool_incr); 202*074ba9b2SJens Wiklander 203*074ba9b2SJens WiklanderExpansion control: specify functions through which the package may 204*074ba9b2SJens Wiklandercompact storage (or take other appropriate action) when an allocation 205*074ba9b2SJens Wiklanderrequest fails, and optionally automatically acquire storage for 206*074ba9b2SJens Wiklanderexpansion blocks when necessary, and release such blocks when they 207*074ba9b2SJens Wiklanderbecome empty. If <compact> is non-NULL, whenever a buffer allocation 208*074ba9b2SJens Wiklanderrequest fails, the <compact> function will be called with arguments 209*074ba9b2SJens Wiklanderspecifying the number of bytes (total buffer size, including header 210*074ba9b2SJens Wiklanderoverhead) required to satisfy the allocation request, and a sequence 211*074ba9b2SJens Wiklandernumber indicating the number of consecutive calls on <compact> 212*074ba9b2SJens Wiklanderattempting to satisfy this allocation request. The sequence number is 1 213*074ba9b2SJens Wiklanderfor the first call on <compact> for a given allocation request, and 214*074ba9b2SJens Wiklanderincrements on subsequent calls, permitting the <compact> function to 215*074ba9b2SJens Wiklandertake increasingly dire measures in an attempt to free up storage. If 216*074ba9b2SJens Wiklanderthe <compact> function returns a nonzero value, the allocation attempt 217*074ba9b2SJens Wiklanderis re-tried. If <compact> returns 0 (as it must if it isn't able to 218*074ba9b2SJens Wiklanderrelease any space or add storage to the buffer pool), the allocation 219*074ba9b2SJens Wiklanderrequest fails, which can trigger automatic pool expansion if the 220*074ba9b2SJens Wiklander<acquire> argument is non-NULL. At the time the <compact> function is 221*074ba9b2SJens Wiklandercalled, the state of the buffer allocator is identical to that at the 222*074ba9b2SJens Wiklandermoment the allocation request was made; consequently, the <compact> 223*074ba9b2SJens Wiklanderfunction may call brel(), bpool(), bstats(), and/or directly manipulate 224*074ba9b2SJens Wiklanderthe buffer pool in any manner which would be valid were the application 225*074ba9b2SJens Wiklanderin control. This does not, however, relieve the <compact> function of 226*074ba9b2SJens Wiklanderthe need to ensure that whatever actions it takes do not change things 227*074ba9b2SJens Wiklanderunderneath the application that made the allocation request. For 228*074ba9b2SJens Wiklanderexample, a <compact> function that released a buffer in the process of 229*074ba9b2SJens Wiklanderbeing reallocated with bgetr() would lead to disaster. Implementing a 230*074ba9b2SJens Wiklandersafe and effective <compact> mechanism requires careful design of an 231*074ba9b2SJens Wiklanderapplication's memory architecture, and cannot generally be easily 232*074ba9b2SJens Wiklanderretrofitted into existing code. 233*074ba9b2SJens Wiklander 234*074ba9b2SJens WiklanderIf <acquire> is non-NULL, that function will be called whenever an 235*074ba9b2SJens Wiklanderallocation request fails. If the <acquire> function succeeds in 236*074ba9b2SJens Wiklanderallocating the requested space and returns a pointer to the new area, 237*074ba9b2SJens Wiklanderallocation will proceed using the expanded buffer pool. If <acquire> 238*074ba9b2SJens Wiklandercannot obtain the requested space, it should return NULL and the entire 239*074ba9b2SJens Wiklanderallocation process will fail. <pool_incr> specifies the normal 240*074ba9b2SJens Wiklanderexpansion block size. Providing an <acquire> function will cause 241*074ba9b2SJens Wiklandersubsequent bget() requests for buffers too large to be managed in the 242*074ba9b2SJens Wiklanderlinked-block scheme (in other words, larger than <pool_incr> minus the 243*074ba9b2SJens Wiklanderbuffer overhead) to be satisfied directly by calls to the <acquire> 244*074ba9b2SJens Wiklanderfunction. Automatic release of empty pool blocks will occur only if all 245*074ba9b2SJens Wiklanderpool blocks in the system are the size given by <pool_incr>. 246*074ba9b2SJens Wiklander 247*074ba9b2SJens Wiklander void bstats(bufsize *curalloc, bufsize *totfree, 248*074ba9b2SJens Wiklander bufsize *maxfree, long *nget, long *nrel); 249*074ba9b2SJens Wiklander 250*074ba9b2SJens WiklanderThe amount of space currently allocated is stored into the variable 251*074ba9b2SJens Wiklanderpointed to by <curalloc>. The total free space (sum of all free blocks 252*074ba9b2SJens Wiklanderin the pool) is stored into the variable pointed to by <totfree>, and 253*074ba9b2SJens Wiklanderthe size of the largest single block in the free space pool is stored 254*074ba9b2SJens Wiklanderinto the variable pointed to by <maxfree>. The variables pointed to by 255*074ba9b2SJens Wiklander<nget> and <nrel> are filled, respectively, with the number of 256*074ba9b2SJens Wiklandersuccessful (non-NULL return) bget() calls and the number of brel() 257*074ba9b2SJens Wiklandercalls. 258*074ba9b2SJens Wiklander 259*074ba9b2SJens Wiklander void bstatse(bufsize *pool_incr, long *npool, 260*074ba9b2SJens Wiklander long *npget, long *nprel, 261*074ba9b2SJens Wiklander long *ndget, long *ndrel); 262*074ba9b2SJens Wiklander 263*074ba9b2SJens WiklanderExtended statistics: The expansion block size will be stored into the 264*074ba9b2SJens Wiklandervariable pointed to by <pool_incr>, or the negative thereof if automatic 265*074ba9b2SJens Wiklanderexpansion block releases are disabled. The number of currently active 266*074ba9b2SJens Wiklanderpool blocks will be stored into the variable pointed to by <npool>. The 267*074ba9b2SJens Wiklandervariables pointed to by <npget> and <nprel> will be filled with, 268*074ba9b2SJens Wiklanderrespectively, the number of expansion block acquisitions and releases 269*074ba9b2SJens Wiklanderwhich have occurred. The variables pointed to by <ndget> and <ndrel> 270*074ba9b2SJens Wiklanderwill be filled with the number of bget() and brel() calls, respectively, 271*074ba9b2SJens Wiklandermanaged through blocks directly allocated by the acquisition and release 272*074ba9b2SJens Wiklanderfunctions. 273*074ba9b2SJens Wiklander 274*074ba9b2SJens Wiklander void bufdump(void *buf); 275*074ba9b2SJens Wiklander 276*074ba9b2SJens WiklanderThe buffer pointed to by <buf> is dumped on standard output. 277*074ba9b2SJens Wiklander 278*074ba9b2SJens Wiklander void bpoold(void *pool, int dumpalloc, int dumpfree); 279*074ba9b2SJens Wiklander 280*074ba9b2SJens WiklanderAll buffers in the buffer pool <pool>, previously initialised by a call 281*074ba9b2SJens Wiklanderon bpool(), are listed in ascending memory address order. If 282*074ba9b2SJens Wiklander<dumpalloc> is nonzero, the contents of allocated buffers are dumped; if 283*074ba9b2SJens Wiklander<dumpfree> is nonzero, the contents of free blocks are dumped. 284*074ba9b2SJens Wiklander 285*074ba9b2SJens Wiklander int bpoolv(void *pool); 286*074ba9b2SJens Wiklander 287*074ba9b2SJens WiklanderThe named buffer pool, previously initialised by a call on bpool(), is 288*074ba9b2SJens Wiklandervalidated for bad pointers, overwritten data, etc. If compiled with 289*074ba9b2SJens WiklanderNDEBUG not defined, any error generates an assertion failure. Otherwise 1 290*074ba9b2SJens Wiklanderis returned if the pool is valid, 0 if an error is found. 291*074ba9b2SJens Wiklander 292*074ba9b2SJens WiklanderBGET CONFIGURATION 293*074ba9b2SJens Wiklander================== 294*074ba9b2SJens Wiklander 295*074ba9b2SJens Wiklander#define TestProg 20000 /* Generate built-in test program 296*074ba9b2SJens Wiklander if defined. The value specifies 297*074ba9b2SJens Wiklander how many buffer allocation attempts 298*074ba9b2SJens Wiklander the test program should make. */ 299*074ba9b2SJens Wiklander 300*074ba9b2SJens Wiklander#define SizeQuant 4 /* Buffer allocation size quantum: 301*074ba9b2SJens Wiklander all buffers allocated are a 302*074ba9b2SJens Wiklander multiple of this size. This 303*074ba9b2SJens Wiklander MUST be a power of two. */ 304*074ba9b2SJens Wiklander 305*074ba9b2SJens Wiklander#define BufDump 1 /* Define this symbol to enable the 306*074ba9b2SJens Wiklander bpoold() function which dumps the 307*074ba9b2SJens Wiklander buffers in a buffer pool. */ 308*074ba9b2SJens Wiklander 309*074ba9b2SJens Wiklander#define BufValid 1 /* Define this symbol to enable the 310*074ba9b2SJens Wiklander bpoolv() function for validating 311*074ba9b2SJens Wiklander a buffer pool. */ 312*074ba9b2SJens Wiklander 313*074ba9b2SJens Wiklander#define DumpData 1 /* Define this symbol to enable the 314*074ba9b2SJens Wiklander bufdump() function which allows 315*074ba9b2SJens Wiklander dumping the contents of an allocated 316*074ba9b2SJens Wiklander or free buffer. */ 317*074ba9b2SJens Wiklander 318*074ba9b2SJens Wiklander#define BufStats 1 /* Define this symbol to enable the 319*074ba9b2SJens Wiklander bstats() function which calculates 320*074ba9b2SJens Wiklander the total free space in the buffer 321*074ba9b2SJens Wiklander pool, the largest available 322*074ba9b2SJens Wiklander buffer, and the total space 323*074ba9b2SJens Wiklander currently allocated. */ 324*074ba9b2SJens Wiklander 325*074ba9b2SJens Wiklander#define FreeWipe 1 /* Wipe free buffers to a guaranteed 326*074ba9b2SJens Wiklander pattern of garbage to trip up 327*074ba9b2SJens Wiklander miscreants who attempt to use 328*074ba9b2SJens Wiklander pointers into released buffers. */ 329*074ba9b2SJens Wiklander 330*074ba9b2SJens Wiklander#define BestFit 1 /* Use a best fit algorithm when 331*074ba9b2SJens Wiklander searching for space for an 332*074ba9b2SJens Wiklander allocation request. This uses 333*074ba9b2SJens Wiklander memory more efficiently, but 334*074ba9b2SJens Wiklander allocation will be much slower. */ 335*074ba9b2SJens Wiklander 336*074ba9b2SJens Wiklander#define BECtl 1 /* Define this symbol to enable the 337*074ba9b2SJens Wiklander bectl() function for automatic 338*074ba9b2SJens Wiklander pool space control. */ 339