The purpose of BFACQ$/BFRLS$ is to provide a simple, yet controlled means of managing user storage. Each element is a small (120 wds/70 wds), reentrant assembly language routine, using only registers X11, A0, and A1. For more extensive storage management, refer to STACK$ (which uses BFACQ$).
BFACQ$ handles the allocation of new buffers and, if necessary, the expansion of user memory. BFRLS$ processes the releasing of buffers back to the storage pool and storage back to the system. (The two elements are separate because a simple program might conceivably need only to acquire storage during its existence and thus not need BFRLS$.)
To acquire a buffer:
LA,U A0,packet-address Or: LA A0,(bdi,packet-address) . buffer BDI on initial call LA,U A1,buffer-length-desired . [maximum = 131070] LMJ X11,BFACQ$ (error return) (normal return)
On a normal return, A1 will contain the address of the user's buffer. On an error return, A0 will contain one of the following status codes:
1 - Storage overflow
2 - Zero or invalid length requested
3 - Corrupted link encountered (address in upper half of A1. Tentative user buffer address in lower half)
07X - TCS error when releasing packet. When this occurs, 070 is added to what would have been the status code; so X is either 0, if the return would otherwise have been normal, or one of the other error codes.
To release a buffer:
LA,U A0,packet-address LA,U A1,buffer-address . (Must have been previously acquired through BFACQ$ and the same control packet) LMJ X11,BFRLS$ (error return) (normal return)
4 - Release address out of bounds
5 - Corrupted link encountered (same as BFACQ$ error 3)
07X - TCS error when releasing packet (same as for BFACQ$).
After releasing a buffer, BFRLS$ will check the links before and after it and, if possible, combine it with the preceding or following buffer. Whenever BFACQ$ cannot satisfy a request from the highest available buffer, it will search back through any released buffers before trying to acquire more storage.
A third element and entry point, BFACQ$BIG, are provided to allow for requests of buffers larger than 131070. The call is the same as for BFACQ$, except that there is no option for zeroing the buffer. Furthermore, once acquired, this size buffer cannot be released using BFRLS$; it must exist for the life of the program. The call to BFACQ$BIG is not reentrant, as it saves and restores registers in its own dbank packet.
The two-word packet whose address is supplied in A0 initially has the following format, although it is later updated by the routines:
|-----------------------------------------------------| -1 | [Optional T$CELL word] | |-----------------------------------------------------| 0 | (TS) | SPBITS | BFPMIN | BFPLTH/A2MOD | |-----------------------------------------------------| 1 | (BFCURR) | BFSTRT | |-----------------------------------------------------|
0,,S1 - TS cell. If set to 040, making word negative, BFACQ$ will not use standard TS locking, but will instead expect a T$CELL word to be defined before word 0 of the packet, for use in test-and-set queuing (TS/C$TS). TSQRG$ registration, if needed, must be done by the caller.
SPBITS - Special flag bits:
Bit 0 - If set, round up all buffer request lengths to one less than the next power of 2.
BFPMIN - The minimum number of 64-word blocks to remain in reserve in the highest available buffer after satisfying a request through MCORE$. If 0, BFACQ$ will assume it only has a fixed amount of storage to work with, will do no MCORE$'s, and could get a storage overflow error if it exhausts the original storage pool.
BFPLTH - The initial length of the storage pool being managed (may be 0). Maximum = 131070. This cell is later used to save A2's modifier.
BFCURR - Must initially be 0. Will always hold the address of the current highest available buffer.
BFSTRT - Address of the storage pool to be managed by this control packet. If BFPMIN is non-zero, BFSTRT must be at the high end of the bank in which it resides; and may be expanded up to 262K. If the user program is banked, BFSTRT's bank must already be based when calling BFACQ$/BFRLS$. If the program's structure is other than a simple IBANK/DBANK, you may need to include the storage pool's BDI in H1 of A0. It is only needed for the initial call to BFACQ$.
The links and pointer words maintained by BFACQ$/BFRLS$ look like this, given a storage pool starting at address A and having its current highest buffer (BFCURR) at address D:
|-------------------------------| A. | 0 | Length+1 of A | |-------------------------------| | ( Buffer ) | |-------------------------------| B. | A | Length+1 of B | |-------------------------------| | ( Buffer ) | |-------------------------------| C. | B | Length+1 of C | |-------------------------------| | ( Buffer ) | |-------------------------------| D. | C | BFPMIN*64+? | [BFCURR] |-------------------------------| | ( Buffer ) | |-------------------------------|