132379Sminshall /* 233685Sbostic * Copyright (c) 1988 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 533685Sbostic * Redistribution and use in source and binary forms are permitted 634898Sbostic * provided that the above copyright notice and this paragraph are 734898Sbostic * duplicated in all such forms and that any documentation, 834898Sbostic * advertising materials, and other materials related to such 934898Sbostic * distribution and use acknowledge that the software was developed 1034898Sbostic * by the University of California, Berkeley. The name of the 1134898Sbostic * University may not be used to endorse or promote products derived 1234898Sbostic * from this software without specific prior written permission. 1334898Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434898Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534898Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633685Sbostic */ 1733685Sbostic 1833685Sbostic #ifndef lint 19*38689Sborman static char sccsid[] = "@(#)ring.c 1.11 (Berkeley) 08/21/89"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2233685Sbostic /* 2332528Sminshall * This defines a structure for a ring buffer. 2432379Sminshall * 2532528Sminshall * The circular buffer has two parts: 2632379Sminshall *((( 2732528Sminshall * full: [consume, supply) 2832528Sminshall * empty: [supply, consume) 2932379Sminshall *]]] 3032379Sminshall * 3132379Sminshall */ 3232379Sminshall 3332379Sminshall #include <stdio.h> 3432379Sminshall #include <errno.h> 3532379Sminshall 3632379Sminshall #ifdef size_t 3732379Sminshall #undef size_t 3832379Sminshall #endif 3932379Sminshall 4032379Sminshall #include <sys/types.h> 4132379Sminshall #include <sys/ioctl.h> 4232379Sminshall #include <sys/socket.h> 4332379Sminshall 4432379Sminshall #include "ring.h" 4532379Sminshall #include "general.h" 4632379Sminshall 4732379Sminshall /* Internal macros */ 4832379Sminshall 4932381Sminshall #if !defined(MIN) 5032381Sminshall #define MIN(a,b) (((a)<(b))? (a):(b)) 5132381Sminshall #endif /* !defined(MIN) */ 5232379Sminshall 53*38689Sborman #define ring_subtract(d,a,b) (((a)-(b) >= 0)? \ 5432381Sminshall (a)-(b): (((a)-(b))+(d)->size)) 5532379Sminshall 5632379Sminshall #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ 5732379Sminshall (a)+(c) : (((a)+(c))-(d)->size)) 5832379Sminshall 5933294Sminshall #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ 6033294Sminshall (a)-(c) : (((a)-(c))-(d)->size)) 6132379Sminshall 6233294Sminshall 6332379Sminshall /* 6432379Sminshall * The following is a clock, used to determine full, empty, etc. 6532379Sminshall * 6632379Sminshall * There is some trickiness here. Since the ring buffers are initialized 6732379Sminshall * to ZERO on allocation, we need to make sure, when interpreting the 6832528Sminshall * clock, that when the times are EQUAL, then the buffer is FULL. 6932379Sminshall */ 7032379Sminshall static u_long ring_clock = 0; 7132379Sminshall 7232379Sminshall 7332528Sminshall #define ring_empty(d) (((d)->consume == (d)->supply) && \ 7432528Sminshall ((d)->consumetime >= (d)->supplytime)) 7532528Sminshall #define ring_full(d) (((d)->supply == (d)->consume) && \ 7632528Sminshall ((d)->supplytime > (d)->consumetime)) 7732379Sminshall 7832379Sminshall 7932379Sminshall 8032379Sminshall 8132379Sminshall 8232379Sminshall /* Buffer state transition routines */ 8332379Sminshall 8432381Sminshall ring_init(ring, buffer, count) 8532381Sminshall Ring *ring; 8632381Sminshall char *buffer; 8732381Sminshall int count; 8832381Sminshall { 8932381Sminshall memset((char *)ring, 0, sizeof *ring); 9032379Sminshall 9132381Sminshall ring->size = count; 9232381Sminshall 9332528Sminshall ring->supply = ring->consume = ring->bottom = buffer; 9432381Sminshall 9532381Sminshall ring->top = ring->bottom+ring->size; 9632381Sminshall 9732381Sminshall return 1; 9832381Sminshall } 9932381Sminshall 10033294Sminshall /* Mark routines */ 10133294Sminshall 10232379Sminshall /* 10333294Sminshall * Mark the most recently supplied byte. 10433294Sminshall */ 10533294Sminshall 10633294Sminshall void 10733294Sminshall ring_mark(ring) 10833294Sminshall Ring *ring; 10933294Sminshall { 11033294Sminshall ring->mark = ring_decrement(ring, ring->supply, 1); 11133294Sminshall } 11233294Sminshall 11333294Sminshall /* 11433294Sminshall * Is the ring pointing to the mark? 11533294Sminshall */ 11633294Sminshall 11733294Sminshall int 11833294Sminshall ring_at_mark(ring) 11933294Sminshall Ring *ring; 12033294Sminshall { 12133294Sminshall if (ring->mark == ring->consume) { 12233294Sminshall return 1; 12333294Sminshall } else { 12433294Sminshall return 0; 12533294Sminshall } 12633294Sminshall } 12733294Sminshall 12833294Sminshall /* 12933294Sminshall * Clear any mark set on the ring. 13033294Sminshall */ 13133294Sminshall 13233294Sminshall void 13333294Sminshall ring_clear_mark(ring) 13433294Sminshall Ring *ring; 13533294Sminshall { 13633294Sminshall ring->mark = 0; 13733294Sminshall } 13833294Sminshall 13933294Sminshall /* 14032379Sminshall * Add characters from current segment to ring buffer. 14132379Sminshall */ 14232379Sminshall void 14332528Sminshall ring_supplied(ring, count) 14432379Sminshall Ring *ring; 14532379Sminshall int count; 14632379Sminshall { 14732528Sminshall ring->supply = ring_increment(ring, ring->supply, count); 14832528Sminshall ring->supplytime = ++ring_clock; 14932379Sminshall } 15032379Sminshall 15132379Sminshall /* 15232528Sminshall * We have just consumed "c" bytes. 15332379Sminshall */ 15432379Sminshall void 15532528Sminshall ring_consumed(ring, count) 15632379Sminshall Ring *ring; 15732379Sminshall int count; 15832379Sminshall { 15932667Sminshall if (count == 0) /* don't update anything */ 16032667Sminshall return; 16132667Sminshall 16233294Sminshall if (ring->mark && 16333294Sminshall (ring_subtract(ring, ring->mark, ring->consume) < count)) { 16433294Sminshall ring->mark = 0; 16533294Sminshall } 16632528Sminshall ring->consume = ring_increment(ring, ring->consume, count); 16732528Sminshall ring->consumetime = ++ring_clock; 16832547Sminshall /* 16932547Sminshall * Try to encourage "ring_empty_consecutive()" to be large. 17032547Sminshall */ 17132547Sminshall if (ring_empty(ring)) { 17232547Sminshall ring->consume = ring->supply = ring->bottom; 17332547Sminshall } 17432379Sminshall } 17532379Sminshall 17632379Sminshall 17732379Sminshall 17832379Sminshall /* Buffer state query routines */ 17932379Sminshall 18032379Sminshall 18132528Sminshall /* Number of bytes that may be supplied */ 18232379Sminshall int 18332379Sminshall ring_empty_count(ring) 18432379Sminshall Ring *ring; 18532379Sminshall { 18632528Sminshall if (ring_empty(ring)) { /* if empty */ 18732379Sminshall return ring->size; 18832379Sminshall } else { 18932528Sminshall return ring_subtract(ring, ring->consume, ring->supply); 19032379Sminshall } 19132379Sminshall } 19232379Sminshall 19332528Sminshall /* number of CONSECUTIVE bytes that may be supplied */ 19432379Sminshall int 19532379Sminshall ring_empty_consecutive(ring) 19632379Sminshall Ring *ring; 19732379Sminshall { 19832528Sminshall if ((ring->consume < ring->supply) || ring_empty(ring)) { 19932528Sminshall /* 20032528Sminshall * if consume is "below" supply, or empty, then 20132528Sminshall * return distance to the top 20232528Sminshall */ 20332528Sminshall return ring_subtract(ring, ring->top, ring->supply); 20432379Sminshall } else { 20532379Sminshall /* 20632379Sminshall * else, return what we may. 20732379Sminshall */ 20832528Sminshall return ring_subtract(ring, ring->consume, ring->supply); 20932379Sminshall } 21032379Sminshall } 21132379Sminshall 21233294Sminshall /* Return the number of bytes that are available for consuming 21333294Sminshall * (but don't give more than enough to get to cross over set mark) 21433294Sminshall */ 21533294Sminshall 21632379Sminshall int 21732528Sminshall ring_full_count(ring) 21832379Sminshall Ring *ring; 21932379Sminshall { 22033294Sminshall if ((ring->mark == 0) || (ring->mark == ring->consume)) { 22133294Sminshall if (ring_full(ring)) { 22233294Sminshall return ring->size; /* nothing consumed, but full */ 22333294Sminshall } else { 22433294Sminshall return ring_subtract(ring, ring->supply, ring->consume); 22533294Sminshall } 22632379Sminshall } else { 22733294Sminshall return ring_subtract(ring, ring->mark, ring->consume); 22832379Sminshall } 22932379Sminshall } 23032379Sminshall 23133294Sminshall /* 23233294Sminshall * Return the number of CONSECUTIVE bytes available for consuming. 23333294Sminshall * However, don't return more than enough to cross over set mark. 23433294Sminshall */ 23532379Sminshall int 23632528Sminshall ring_full_consecutive(ring) 23732379Sminshall Ring *ring; 23832379Sminshall { 23933294Sminshall if ((ring->mark == 0) || (ring->mark == ring->consume)) { 24033294Sminshall if ((ring->supply < ring->consume) || ring_full(ring)) { 24133294Sminshall return ring_subtract(ring, ring->top, ring->consume); 24233294Sminshall } else { 24333294Sminshall return ring_subtract(ring, ring->supply, ring->consume); 24433294Sminshall } 24532379Sminshall } else { 24633294Sminshall if (ring->mark < ring->consume) { 24733294Sminshall return ring_subtract(ring, ring->top, ring->consume); 24833294Sminshall } else { /* Else, distance to mark */ 24933294Sminshall return ring_subtract(ring, ring->mark, ring->consume); 25033294Sminshall } 25132379Sminshall } 25232379Sminshall } 25332379Sminshall 25432379Sminshall /* 25532528Sminshall * Move data into the "supply" portion of of the ring buffer. 25632379Sminshall */ 25732379Sminshall void 25832528Sminshall ring_supply_data(ring, buffer, count) 25932379Sminshall Ring *ring; 26032379Sminshall char *buffer; 26132379Sminshall int count; 26232379Sminshall { 26332379Sminshall int i; 26432379Sminshall 26532379Sminshall while (count) { 26632381Sminshall i = MIN(count, ring_empty_consecutive(ring)); 26732528Sminshall memcpy(ring->supply, buffer, i); 26832528Sminshall ring_supplied(ring, i); 26932379Sminshall count -= i; 27032379Sminshall buffer += i; 27132379Sminshall } 27232379Sminshall } 27332379Sminshall 27432379Sminshall 27532379Sminshall /* 27632528Sminshall * Move data from the "consume" portion of the ring buffer 27732379Sminshall */ 27832379Sminshall void 27932528Sminshall ring_consume_data(ring, buffer, count) 28032379Sminshall Ring *ring; 28132379Sminshall char *buffer; 28232379Sminshall int count; 28332379Sminshall { 28432379Sminshall int i; 28532379Sminshall 28632379Sminshall while (count) { 28732528Sminshall i = MIN(count, ring_full_consecutive(ring)); 28832528Sminshall memcpy(buffer, ring->consume, i); 28932528Sminshall ring_consumed(ring, i); 29032379Sminshall count -= i; 29132379Sminshall buffer += i; 29232379Sminshall } 29332379Sminshall } 294