132379Sminshall /* 232528Sminshall * This defines a structure for a ring buffer. 332379Sminshall * 432528Sminshall * The circular buffer has two parts: 532379Sminshall *((( 632528Sminshall * full: [consume, supply) 732528Sminshall * empty: [supply, consume) 832379Sminshall *]]] 932379Sminshall * 1032379Sminshall */ 1132379Sminshall 1232379Sminshall #include <stdio.h> 1332379Sminshall #include <errno.h> 1432379Sminshall 1532379Sminshall #ifdef size_t 1632379Sminshall #undef size_t 1732379Sminshall #endif 1832379Sminshall 1932379Sminshall #include <sys/types.h> 2032379Sminshall #include <sys/ioctl.h> 2132379Sminshall #include <sys/socket.h> 2232379Sminshall 2332379Sminshall #include "ring.h" 2432379Sminshall #include "general.h" 2532379Sminshall 2632379Sminshall /* Internal macros */ 2732379Sminshall 2832381Sminshall #if !defined(MIN) 2932381Sminshall #define MIN(a,b) (((a)<(b))? (a):(b)) 3032381Sminshall #endif /* !defined(MIN) */ 3132379Sminshall 3232381Sminshall #define ring_subtract(d,a,b) ((((int)(a))-((int)(b)) >= 0)? \ 3332381Sminshall (a)-(b): (((a)-(b))+(d)->size)) 3432379Sminshall 3532379Sminshall #define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ 3632379Sminshall (a)+(c) : (((a)+(c))-(d)->size)) 3732379Sminshall 38*33294Sminshall #define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ 39*33294Sminshall (a)-(c) : (((a)-(c))-(d)->size)) 4032379Sminshall 41*33294Sminshall 4232379Sminshall /* 4332379Sminshall * The following is a clock, used to determine full, empty, etc. 4432379Sminshall * 4532379Sminshall * There is some trickiness here. Since the ring buffers are initialized 4632379Sminshall * to ZERO on allocation, we need to make sure, when interpreting the 4732528Sminshall * clock, that when the times are EQUAL, then the buffer is FULL. 4832379Sminshall */ 4932379Sminshall static u_long ring_clock = 0; 5032379Sminshall 5132379Sminshall 5232528Sminshall #define ring_empty(d) (((d)->consume == (d)->supply) && \ 5332528Sminshall ((d)->consumetime >= (d)->supplytime)) 5432528Sminshall #define ring_full(d) (((d)->supply == (d)->consume) && \ 5532528Sminshall ((d)->supplytime > (d)->consumetime)) 5632379Sminshall 5732379Sminshall 5832379Sminshall 5932379Sminshall 6032379Sminshall 6132379Sminshall /* Buffer state transition routines */ 6232379Sminshall 6332381Sminshall ring_init(ring, buffer, count) 6432381Sminshall Ring *ring; 6532381Sminshall char *buffer; 6632381Sminshall int count; 6732381Sminshall { 6832381Sminshall memset((char *)ring, 0, sizeof *ring); 6932379Sminshall 7032381Sminshall ring->size = count; 7132381Sminshall 7232528Sminshall ring->supply = ring->consume = ring->bottom = buffer; 7332381Sminshall 7432381Sminshall ring->top = ring->bottom+ring->size; 7532381Sminshall 7632381Sminshall return 1; 7732381Sminshall } 7832381Sminshall 79*33294Sminshall /* Mark routines */ 80*33294Sminshall 8132379Sminshall /* 82*33294Sminshall * Mark the most recently supplied byte. 83*33294Sminshall */ 84*33294Sminshall 85*33294Sminshall void 86*33294Sminshall ring_mark(ring) 87*33294Sminshall Ring *ring; 88*33294Sminshall { 89*33294Sminshall ring->mark = ring_decrement(ring, ring->supply, 1); 90*33294Sminshall } 91*33294Sminshall 92*33294Sminshall /* 93*33294Sminshall * Is the ring pointing to the mark? 94*33294Sminshall */ 95*33294Sminshall 96*33294Sminshall int 97*33294Sminshall ring_at_mark(ring) 98*33294Sminshall Ring *ring; 99*33294Sminshall { 100*33294Sminshall if (ring->mark == ring->consume) { 101*33294Sminshall return 1; 102*33294Sminshall } else { 103*33294Sminshall return 0; 104*33294Sminshall } 105*33294Sminshall } 106*33294Sminshall 107*33294Sminshall /* 108*33294Sminshall * Clear any mark set on the ring. 109*33294Sminshall */ 110*33294Sminshall 111*33294Sminshall void 112*33294Sminshall ring_clear_mark(ring) 113*33294Sminshall Ring *ring; 114*33294Sminshall { 115*33294Sminshall ring->mark = 0; 116*33294Sminshall } 117*33294Sminshall 118*33294Sminshall /* 11932379Sminshall * Add characters from current segment to ring buffer. 12032379Sminshall */ 12132379Sminshall void 12232528Sminshall ring_supplied(ring, count) 12332379Sminshall Ring *ring; 12432379Sminshall int count; 12532379Sminshall { 12632528Sminshall ring->supply = ring_increment(ring, ring->supply, count); 12732528Sminshall ring->supplytime = ++ring_clock; 12832379Sminshall } 12932379Sminshall 13032379Sminshall /* 13132528Sminshall * We have just consumed "c" bytes. 13232379Sminshall */ 13332379Sminshall void 13432528Sminshall ring_consumed(ring, count) 13532379Sminshall Ring *ring; 13632379Sminshall int count; 13732379Sminshall { 13832667Sminshall if (count == 0) /* don't update anything */ 13932667Sminshall return; 14032667Sminshall 141*33294Sminshall if (ring->mark && 142*33294Sminshall (ring_subtract(ring, ring->mark, ring->consume) < count)) { 143*33294Sminshall ring->mark = 0; 144*33294Sminshall } 14532528Sminshall ring->consume = ring_increment(ring, ring->consume, count); 14632528Sminshall ring->consumetime = ++ring_clock; 14732547Sminshall /* 14832547Sminshall * Try to encourage "ring_empty_consecutive()" to be large. 14932547Sminshall */ 15032547Sminshall if (ring_empty(ring)) { 15132547Sminshall ring->consume = ring->supply = ring->bottom; 15232547Sminshall } 15332379Sminshall } 15432379Sminshall 15532379Sminshall 15632379Sminshall 15732379Sminshall /* Buffer state query routines */ 15832379Sminshall 15932379Sminshall 16032528Sminshall /* Number of bytes that may be supplied */ 16132379Sminshall int 16232379Sminshall ring_empty_count(ring) 16332379Sminshall Ring *ring; 16432379Sminshall { 16532528Sminshall if (ring_empty(ring)) { /* if empty */ 16632379Sminshall return ring->size; 16732379Sminshall } else { 16832528Sminshall return ring_subtract(ring, ring->consume, ring->supply); 16932379Sminshall } 17032379Sminshall } 17132379Sminshall 17232528Sminshall /* number of CONSECUTIVE bytes that may be supplied */ 17332379Sminshall int 17432379Sminshall ring_empty_consecutive(ring) 17532379Sminshall Ring *ring; 17632379Sminshall { 17732528Sminshall if ((ring->consume < ring->supply) || ring_empty(ring)) { 17832528Sminshall /* 17932528Sminshall * if consume is "below" supply, or empty, then 18032528Sminshall * return distance to the top 18132528Sminshall */ 18232528Sminshall return ring_subtract(ring, ring->top, ring->supply); 18332379Sminshall } else { 18432379Sminshall /* 18532379Sminshall * else, return what we may. 18632379Sminshall */ 18732528Sminshall return ring_subtract(ring, ring->consume, ring->supply); 18832379Sminshall } 18932379Sminshall } 19032379Sminshall 191*33294Sminshall /* Return the number of bytes that are available for consuming 192*33294Sminshall * (but don't give more than enough to get to cross over set mark) 193*33294Sminshall */ 194*33294Sminshall 19532379Sminshall int 19632528Sminshall ring_full_count(ring) 19732379Sminshall Ring *ring; 19832379Sminshall { 199*33294Sminshall if ((ring->mark == 0) || (ring->mark == ring->consume)) { 200*33294Sminshall if (ring_full(ring)) { 201*33294Sminshall return ring->size; /* nothing consumed, but full */ 202*33294Sminshall } else { 203*33294Sminshall return ring_subtract(ring, ring->supply, ring->consume); 204*33294Sminshall } 20532379Sminshall } else { 206*33294Sminshall return ring_subtract(ring, ring->mark, ring->consume); 20732379Sminshall } 20832379Sminshall } 20932379Sminshall 210*33294Sminshall /* 211*33294Sminshall * Return the number of CONSECUTIVE bytes available for consuming. 212*33294Sminshall * However, don't return more than enough to cross over set mark. 213*33294Sminshall */ 21432379Sminshall int 21532528Sminshall ring_full_consecutive(ring) 21632379Sminshall Ring *ring; 21732379Sminshall { 218*33294Sminshall if ((ring->mark == 0) || (ring->mark == ring->consume)) { 219*33294Sminshall if ((ring->supply < ring->consume) || ring_full(ring)) { 220*33294Sminshall return ring_subtract(ring, ring->top, ring->consume); 221*33294Sminshall } else { 222*33294Sminshall return ring_subtract(ring, ring->supply, ring->consume); 223*33294Sminshall } 22432379Sminshall } else { 225*33294Sminshall if (ring->mark < ring->consume) { 226*33294Sminshall return ring_subtract(ring, ring->top, ring->consume); 227*33294Sminshall } else { /* Else, distance to mark */ 228*33294Sminshall return ring_subtract(ring, ring->mark, ring->consume); 229*33294Sminshall } 23032379Sminshall } 23132379Sminshall } 23232379Sminshall 23332379Sminshall /* 23432528Sminshall * Move data into the "supply" portion of of the ring buffer. 23532379Sminshall */ 23632379Sminshall void 23732528Sminshall ring_supply_data(ring, buffer, count) 23832379Sminshall Ring *ring; 23932379Sminshall char *buffer; 24032379Sminshall int count; 24132379Sminshall { 24232379Sminshall int i; 24332379Sminshall 24432379Sminshall while (count) { 24532381Sminshall i = MIN(count, ring_empty_consecutive(ring)); 24632528Sminshall memcpy(ring->supply, buffer, i); 24732528Sminshall ring_supplied(ring, i); 24832379Sminshall count -= i; 24932379Sminshall buffer += i; 25032379Sminshall } 25132379Sminshall } 25232379Sminshall 25332379Sminshall 25432379Sminshall /* 25532528Sminshall * Move data from the "consume" portion of the ring buffer 25632379Sminshall */ 25732379Sminshall void 25832528Sminshall ring_consume_data(ring, buffer, count) 25932379Sminshall Ring *ring; 26032379Sminshall char *buffer; 26132379Sminshall int count; 26232379Sminshall { 26332379Sminshall int i; 26432379Sminshall 26532379Sminshall while (count) { 26632528Sminshall i = MIN(count, ring_full_consecutive(ring)); 26732528Sminshall memcpy(buffer, ring->consume, i); 26832528Sminshall ring_consumed(ring, i); 26932379Sminshall count -= i; 27032379Sminshall buffer += i; 27132379Sminshall } 27232379Sminshall } 273