Kernel: STREAMS
The IRIX STREAMS framework provides a modular, message-passing I/O subsystem for character devices, terminals, network protocols, and pseudo-devices. It uses queues (read/write pairs per module/driver), message blocks (mblk_t/dblk_t), and buffers for data transfer. The implementation is highly optimized for performance with:
Per-CPU free lists (NUMA-aware) for message blocks, data blocks, and buffers of various sizes. Cache coloring and alignment support. Zone-based allocation for small structures. Page-based buffering with coalescing and reclaim. Global limits and dynamic reclamation via strgiveback. MP-safe design using spinlocks per CPU.
The core data structures are managed through list vectors (lf_listvec) per CPU, with separate pools for different buffer sizes (64B to full page).
Key Functions
Initialization
str_init_master: Initializes global structures for master CPU. str_init_slave: Sets up per-CPU structures for slave CPUs. str_init_memsize: Configures page limits based on physical memory. str_init_alloc_bufs: Preallocates initial buffers per CPU. strinit_giveback: Starts periodic page reclamation timer.
Message Block Allocation
allocb: Allocates mblk_t + dblk_t + buffer (various sizes). allocb_nobuffer: Allocates only mblk_t/dblk_t (no data buffer). esballoc: Attaches external buffer (zero-copy). bufcall / esbbcall: Schedule callback when memory available.
Queue Operations
putq / putbq / insq: Insert message into queue (priority-ordered). getq: Remove next message from queue. rmvq: Remove specific message. flushq / flushband: Discard messages (all or by band). qenable: Schedule queue service routine. canput / bcanput: Flow control checks.
Buffer Management
lf_get / lf_free: Node allocation/deallocation from per-CPU lists. lf_addpage / lf_getpage_tiled: Page tiling and addition to free lists. lf_freepage: Return full page to kernel VM. str_preallocate: Initial buffer preallocation.
Special Cases
msgpullup: Coalesce message into single contiguous buffer. copyb / copymsg / dupb / dupmsg: Copy or reference-count messages. linkb / unlinkb: Chain management. adjmsg: Trim bytes from head/tail.
Undocumented or IRIX-Specific Interfaces and Behaviors
Structures
mblk_t: Message descriptor (pointers, type, flags, band). dblk_t: Data block (buffer pointers, refcount, type, size, free routine). queue_t: Read/write queue pair with flow control parameters. qband_t: Per-priority-band flow control (for non-zero bands). lf_listvec / listvec: Per-CPU free list vectors with multiple size classes. strstat: Per-CPU statistics.
Buffer Pools
Fixed sizes: 64, 256, 512, 2048 bytes + full page. Combined mblk_t/dblk_t pool. Separate message header pool. Page reclamation: strgiveback returns excess pages to kernel.
NUMA Awareness
Per-node, per-CPU list vectors. Allocation prefers local node.
Flow Control
High/low water marks per queue and band. QFULL / QB_FULL flags. Back-enable nearest upstream service routine.
Extended Free Routine
esballoc supports external buffers with custom free function.
Similarities to illumos and BSD Kernel Implementations
illumos (Solaris-derived) Strong similarity:
Message block (mblk_t/dblk_t) and queue model nearly identical. allocb, esballoc, putq, getq, canput, qenable. Per-CPU caches and buffer pools. Flow control with high/low water.
Differences: illumos uses kmem_cache extensively; more modular. BSD (FreeBSD, etc.) Less similar:
No native STREAMS (removed long ago). Character I/O via cdevsw or tty. Some ports emulate via compatibility layers.
Overall, IRIX STREAMS is classic SVR4 with NUMA/per-CPU optimizations. illumos provides closest modern equivalent; BSD lacks native support. For replication: preserve per-CPU lists, buffer size classes, and queue scheduling semantics. Page reclamation and tiling logic are IRIX-specific.