ALLOCB(10.2) ALLOCB(10.2)
NAME
allocb, iallocb, freeb, freeblist, BLEN, blocklen, concatblock, copy‐
block, trimblock, packblock, padblock, pullblock, pullupblock, adjust‐
block, checkb - data block management
SYNOPSIS
Block* allocb(int size)
Block* iallocb(int size)
void freeb(Block *b)
void freeblist(Block *b)
long BLEN(Block *b)
int blocklen(Block *b)
Block* concatblock(Block *b)
Block* copyblock(Block *b, int n)
Block* trimblock(Block *b, int offset, int n)
Block* packblock(Block *b)
Block* padblock(Block *b, int n)
int pullblock(Block **bph, int n)
Block* pullupblock(Block *b, int n)
Block* adjustblock(Block *b, int n)
void checkb(Block *b, char *msg)
DESCRIPTION
A Block provides a receptacle for data:
typedef
struct Block
{
Block* next;
Block* list;
uchar* rp; /* first unconsumed byte */
uchar* wp; /* first empty byte */
uchar* lim; /* 1 past the end of the buffer */
uchar* base; /* start of the buffer */
void (*free)(Block*);
ulong flag;
} Block;
Each Block has an associated buffer, located at base, and accessed via
wp when filling the buffer, or rp when fetching data from it. Each
pointer should be incremented to reflect the amount of data written or
read. A Block is empty when rp reaches wp. The pointer lim bounds the
allocated space. Some operations described below accept lists of
Blocks, which are chained via their next pointers, with a null pointer
ending the list. Blocks are usually intended for a Queue (see
qio(10.2)), but can be used independently.
A Block and its buffer are normally allocated by one call to mal‐
loc(10.2) and aligned on an 8 byte (BY2V) boundary. Some devices with
particular allocation constraints (eg, requiring certain addresses for
DMA) might allocate their own Block and buffer; free must then point to
a function that can deallocate the specially allocated Block.
Many Block operations cannot be used in interrupt handlers because they
either sleep(10.2) or raise an error(10.2). Of operations that allo‐
cate blocks, only iallocb is usable.
Allocb allocates a Block of at least size bytes. The block is ini‐
tially empty: rp and wp point to the start of the data. If it cannot
allocate memory, allocb raises an error(10.2); it cannot be used by an
interrupt handler.
Iallocb is similar to allocb but is intended for use by interrupt han‐
dlers, and returns a null pointer if no memory is available. It also
limits its allocation to a quota allocated at system initialisation to
interrupt-time buffering.
Freeb frees a single Block (and its buffer).
Freeblist frees the whole list of blocks headed by b.
BLEN returns the number of unread bytes in a single block b; it is
implemented as a macro.
Blocklen returns the number of bytes of unread data in the whole list
of blocks headed by b.
Concatblock returns b if it is not a list, and otherwise returns a sin‐
gle Block containing all the data in the list of blocks b, which it
frees.
Copyblock by contrast returns a single Block containing a copy of the
first n bytes of data in the block list b, padding with zeroes if the
list contained less than n bytes. The list b is unchanged.
Padblock can pad a single Block at either end, to reserve space for
protocol headers or trailers. If n≥0, it inserts n bytes at the start
of the block, setting the read pointer rp to point to the new space.
If n<0, it adds n bytes at the end of the block, leaving the write
pointer wp pointing at the new space. In both cases, it allocates a
new Block if necessary, freeing the old, and it always returns a
pointer to the resulting Block.
Trimblock trims the list b to contain no more than n bytes starting at
offset bytes into the data of the original list. It returns a new
list, freeing unneeded parts of the old. If no data remains, it
returns a null pointer.
Packblock examines each Block in the list b, reallocating any block in
the list that has four times more available space than actual data. It
returns a pointer to the revised list.
Pullblock discards up to n bytes from the start of the list headed by
*bph. Unneeded blocks are freed. Pullblock sets *bph to point to the
new list head and returns the number of bytes discarded (which might be
less than n). It is used by transport protocols to discard ack'd data
at the head of a retransmission queue.
Pullupblock rearranges the data in the list of blocks b to ensure that
there are at least n bytes of contiguous data in the first block, and
returns a pointer to the new list head. It frees any blocks that it
empties. It returns a null pointer if there is not enough data in the
list.
Adjustblock ensures that the block b has at least n bytes of data,
reallocating or padding with zero if necessary. It returns a pointer
to the new Block. (If n is negative, it frees the block and returns a
null pointer.)
Checkb does some consistency checking of the state of b; a panic(10.2)
results if things look grim. It is intended for internal use by the
queue I/O routines (see qio(10.2)) but could be used elsewhere.
The only functions that can be called at interrupt level are iallocb,
freeb, freeblist, BLEN, blocklen, trimblock and pullupblock. The oth‐
ers allocate memory and can potentially block.
DIAGNOSTICS
Many functions directly or indirectly can raise an error(10.2), and
callers must therefore provide for proper error recovery as described
therein to prevent memory leaks and other bugs. Except for iallocb,
any functions that allocate new blocks or lists are unsuitable for use
by interrupt handlers. Iallocb returns a null pointer when it runs out
of memory.
SOURCE
/os/port/qio.c
/emu/port/qio.c
SEE ALSO
qio(10.2)
ALLOCB(10.2)