ALLOCB(9)                                               ALLOCB(9)

     NAME
          allocb, iallocb, freeb, freeblist, BLEN, BALLOC, blocklen,
          blockalloclen, readblist, concatblock, copyblock, trimblock,
          packblock, padblock, pullblock, pullupblock, adjustblock,
          checkb - data block management

     SYNOPSIS
          Block* allocb(int size)

          Block* iallocb(int size)

          void   freeb(Block *b)

          void   freeblist(Block *b)

          int    blocklen(Block *b)

          int    blockalloclen(Block *b)

          long   readblist(Block *b, uchar *p, long n, ulong offset)

          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)

          #define BLEN(s)((s)->wp - (s)->rp)

          #define BALLOC(s) ((s)->lim - (s)->base)

     DESCRIPTION
          A Block provides a receptacle for data:

               typedef
               struct Block
               {
                    Block*    next;

     ALLOCB(9)                                               ALLOCB(9)

                    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*);
                    ushort    flag;
                    ushort    checksum; /* IP checksum of complete packet */
               } 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(9)), but can be used independently.

          A Block and its buffer are normally allocated by one call to
          malloc(9) and aligned on an 8 byte (BY2V) boundary.  Some
          devices with particular allocation constraints (eg, requir-
          ing 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(9) or raise an error(9). Of opera-
          tions that allocate blocks, only iallocb is usable.

          Allocb allocates a Block of at least size bytes.  The block
          is initially empty: rp and wp point to the start of the
          data.  If it cannot allocate memory, allocb raises an
          error(9); it cannot be used by an interrupt handler.

          Iallocb is similar to allocb but is intended for use by
          interrupt handlers, 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 buffer-
          ing.

          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.

          BALLOC returns the number of allocated bytes in a single
          block.

          Blocklen returns the number of bytes of unread data in the

     ALLOCB(9)                                               ALLOCB(9)

          whole list of blocks headed by b.

          Blockalloclen returns the number of total bytes allocated in
          the whole list of blocks headed by b.

          Readblist copies n bytes of data at offset offset from the
          list of blocks headed by b into p, then returns the amount
          of bytes copied. It leaves the block list intact.

          Concatblock returns b if it is not a list, and otherwise
          returns a single 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, pad-
          ding 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

     ALLOCB(9)                                               ALLOCB(9)

          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(9) results if things look grim.  It is intended for
          internal use by the queue I/O routines (see qio(9)) but
          could be used elsewhere.

          The only functions that can be called at interrupt level are
          iallocb, freeb, freeblist, BLEN, BALLOC, blocklen,
          blockalloclen, readblist and trimblock. The others allocate
          memory and can potentially block.

     SOURCE
          /sys/src/9/port/allocb.c
          /sys/src/9/port/qio.c

     DIAGNOSTICS
          Many functions directly or indirectly can raise an error(9),
          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.

     SEE ALSO
          qio(9)