Home | History | Annotate | Line # | Download | only in telnet
ring.c revision 1.7
      1 /*	$NetBSD: ring.c,v 1.7 1996/02/28 21:04:07 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1988, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  */
     35 
     36 #ifndef lint
     37 #if 0
     38 static char sccsid[] = "@(#)ring.c	8.2 (Berkeley) 5/30/95";
     39 #else
     40 static char rcsid[] = "$NetBSD: ring.c,v 1.7 1996/02/28 21:04:07 thorpej Exp $";
     41 #endif
     42 #endif /* not lint */
     43 
     44 /*
     45  * This defines a structure for a ring buffer.
     46  *
     47  * The circular buffer has two parts:
     48  *(((
     49  *	full:	[consume, supply)
     50  *	empty:	[supply, consume)
     51  *]]]
     52  *
     53  */
     54 
     55 #include	<stdio.h>
     56 #ifndef NO_STRING_H
     57 #include	<string.h>
     58 #endif
     59 #include	<strings.h>
     60 #include	<errno.h>
     61 
     62 #ifdef	size_t
     63 #undef	size_t
     64 #endif
     65 
     66 #include	<sys/types.h>
     67 #ifndef	FILIO_H
     68 #include	<sys/ioctl.h>
     69 #endif
     70 #include	<sys/socket.h>
     71 
     72 #include	"ring.h"
     73 #include	"general.h"
     74 
     75 /* Internal macros */
     76 
     77 #if	!defined(MIN)
     78 #define	MIN(a,b)	(((a)<(b))? (a):(b))
     79 #endif	/* !defined(MIN) */
     80 
     81 #define	ring_subtract(d,a,b)	(((a)-(b) >= 0)? \
     82 					(a)-(b): (((a)-(b))+(d)->size))
     83 
     84 #define	ring_increment(d,a,c)	(((a)+(c) < (d)->top)? \
     85 					(a)+(c) : (((a)+(c))-(d)->size))
     86 
     87 #define	ring_decrement(d,a,c)	(((a)-(c) >= (d)->bottom)? \
     88 					(a)-(c) : (((a)-(c))-(d)->size))
     89 
     90 
     91 /*
     92  * The following is a clock, used to determine full, empty, etc.
     93  *
     94  * There is some trickiness here.  Since the ring buffers are initialized
     95  * to ZERO on allocation, we need to make sure, when interpreting the
     96  * clock, that when the times are EQUAL, then the buffer is FULL.
     97  */
     98 static u_long ring_clock = 0;
     99 
    100 
    101 #define	ring_empty(d) (((d)->consume == (d)->supply) && \
    102 				((d)->consumetime >= (d)->supplytime))
    103 #define	ring_full(d) (((d)->supply == (d)->consume) && \
    104 				((d)->supplytime > (d)->consumetime))
    105 
    106 
    107 
    108 
    109 
    110 /* Buffer state transition routines */
    111 
    112     ring_init(ring, buffer, count)
    113 Ring *ring;
    114     unsigned char *buffer;
    115     int count;
    116 {
    117     memset((char *)ring, 0, sizeof *ring);
    118 
    119     ring->size = count;
    120 
    121     ring->supply = ring->consume = ring->bottom = buffer;
    122 
    123     ring->top = ring->bottom+ring->size;
    124 
    125 
    126     return 1;
    127 }
    128 
    129 /* Mark routines */
    130 
    131 /*
    132  * Mark the most recently supplied byte.
    133  */
    134 
    135     void
    136 ring_mark(ring)
    137     Ring *ring;
    138 {
    139     ring->mark = ring_decrement(ring, ring->supply, 1);
    140 }
    141 
    142 /*
    143  * Is the ring pointing to the mark?
    144  */
    145 
    146     int
    147 ring_at_mark(ring)
    148     Ring *ring;
    149 {
    150     if (ring->mark == ring->consume) {
    151 	return 1;
    152     } else {
    153 	return 0;
    154     }
    155 }
    156 
    157 /*
    158  * Clear any mark set on the ring.
    159  */
    160 
    161     void
    162 ring_clear_mark(ring)
    163     Ring *ring;
    164 {
    165     ring->mark = 0;
    166 }
    167 
    168 /*
    169  * Add characters from current segment to ring buffer.
    170  */
    171     void
    172 ring_supplied(ring, count)
    173     Ring *ring;
    174     int count;
    175 {
    176     ring->supply = ring_increment(ring, ring->supply, count);
    177     ring->supplytime = ++ring_clock;
    178 }
    179 
    180 /*
    181  * We have just consumed "c" bytes.
    182  */
    183     void
    184 ring_consumed(ring, count)
    185     Ring *ring;
    186     int count;
    187 {
    188     if (count == 0)	/* don't update anything */
    189 	return;
    190 
    191     if (ring->mark &&
    192 		(ring_subtract(ring, ring->mark, ring->consume) < count)) {
    193 	ring->mark = 0;
    194     }
    195     ring->consume = ring_increment(ring, ring->consume, count);
    196     ring->consumetime = ++ring_clock;
    197     /*
    198      * Try to encourage "ring_empty_consecutive()" to be large.
    199      */
    200     if (ring_empty(ring)) {
    201 	ring->consume = ring->supply = ring->bottom;
    202     }
    203 }
    204 
    205 
    206 
    207 /* Buffer state query routines */
    208 
    209 
    210 /* Number of bytes that may be supplied */
    211     int
    212 ring_empty_count(ring)
    213     Ring *ring;
    214 {
    215     if (ring_empty(ring)) {	/* if empty */
    216 	    return ring->size;
    217     } else {
    218 	return ring_subtract(ring, ring->consume, ring->supply);
    219     }
    220 }
    221 
    222 /* number of CONSECUTIVE bytes that may be supplied */
    223     int
    224 ring_empty_consecutive(ring)
    225     Ring *ring;
    226 {
    227     if ((ring->consume < ring->supply) || ring_empty(ring)) {
    228 			    /*
    229 			     * if consume is "below" supply, or empty, then
    230 			     * return distance to the top
    231 			     */
    232 	return ring_subtract(ring, ring->top, ring->supply);
    233     } else {
    234 				    /*
    235 				     * else, return what we may.
    236 				     */
    237 	return ring_subtract(ring, ring->consume, ring->supply);
    238     }
    239 }
    240 
    241 /* Return the number of bytes that are available for consuming
    242  * (but don't give more than enough to get to cross over set mark)
    243  */
    244 
    245     int
    246 ring_full_count(ring)
    247     Ring *ring;
    248 {
    249     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
    250 	if (ring_full(ring)) {
    251 	    return ring->size;	/* nothing consumed, but full */
    252 	} else {
    253 	    return ring_subtract(ring, ring->supply, ring->consume);
    254 	}
    255     } else {
    256 	return ring_subtract(ring, ring->mark, ring->consume);
    257     }
    258 }
    259 
    260 /*
    261  * Return the number of CONSECUTIVE bytes available for consuming.
    262  * However, don't return more than enough to cross over set mark.
    263  */
    264     int
    265 ring_full_consecutive(ring)
    266     Ring *ring;
    267 {
    268     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
    269 	if ((ring->supply < ring->consume) || ring_full(ring)) {
    270 	    return ring_subtract(ring, ring->top, ring->consume);
    271 	} else {
    272 	    return ring_subtract(ring, ring->supply, ring->consume);
    273 	}
    274     } else {
    275 	if (ring->mark < ring->consume) {
    276 	    return ring_subtract(ring, ring->top, ring->consume);
    277 	} else {	/* Else, distance to mark */
    278 	    return ring_subtract(ring, ring->mark, ring->consume);
    279 	}
    280     }
    281 }
    282 
    283 /*
    284  * Move data into the "supply" portion of of the ring buffer.
    285  */
    286     void
    287 ring_supply_data(ring, buffer, count)
    288     Ring *ring;
    289     unsigned char *buffer;
    290     int count;
    291 {
    292     int i;
    293 
    294     while (count) {
    295 	i = MIN(count, ring_empty_consecutive(ring));
    296 	memmove(ring->supply, buffer, i);
    297 	ring_supplied(ring, i);
    298 	count -= i;
    299 	buffer += i;
    300     }
    301 }
    302 
    303 #ifdef notdef
    304 
    305 /*
    306  * Move data from the "consume" portion of the ring buffer
    307  */
    308     void
    309 ring_consume_data(ring, buffer, count)
    310     Ring *ring;
    311     unsigned char *buffer;
    312     int count;
    313 {
    314     int i;
    315 
    316     while (count) {
    317 	i = MIN(count, ring_full_consecutive(ring));
    318 	memmove(buffer, ring->consume, i);
    319 	ring_consumed(ring, i);
    320 	count -= i;
    321 	buffer += i;
    322     }
    323 }
    324 #endif
    325 
    326