Home | History | Annotate | Line # | Download | only in telnet
ring.c revision 1.8
      1 /*	$NetBSD: ring.c,v 1.8 1998/02/27 10:44:13 christos 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 #include <sys/cdefs.h>
     37 #ifndef lint
     38 #if 0
     39 static char sccsid[] = "@(#)ring.c	8.2 (Berkeley) 5/30/95";
     40 #else
     41 __RCSID("$NetBSD: ring.c,v 1.8 1998/02/27 10:44:13 christos Exp $");
     42 #endif
     43 #endif /* not lint */
     44 
     45 /*
     46  * This defines a structure for a ring buffer.
     47  *
     48  * The circular buffer has two parts:
     49  *(((
     50  *	full:	[consume, supply)
     51  *	empty:	[supply, consume)
     52  *]]]
     53  *
     54  */
     55 
     56 #include	<stdio.h>
     57 #ifndef NO_STRING_H
     58 #include	<string.h>
     59 #endif
     60 #include	<strings.h>
     61 #include	<errno.h>
     62 
     63 #ifdef	size_t
     64 #undef	size_t
     65 #endif
     66 
     67 #include	<sys/types.h>
     68 #ifndef	FILIO_H
     69 #include	<sys/ioctl.h>
     70 #endif
     71 #include	<sys/socket.h>
     72 
     73 #include	"ring.h"
     74 #include	"general.h"
     75 
     76 /* Internal macros */
     77 
     78 #if	!defined(MIN)
     79 #define	MIN(a,b)	(((a)<(b))? (a):(b))
     80 #endif	/* !defined(MIN) */
     81 
     82 #define	ring_subtract(d,a,b)	(((a)-(b) >= 0)? \
     83 					(a)-(b): (((a)-(b))+(d)->size))
     84 
     85 #define	ring_increment(d,a,c)	(((a)+(c) < (d)->top)? \
     86 					(a)+(c) : (((a)+(c))-(d)->size))
     87 
     88 #define	ring_decrement(d,a,c)	(((a)-(c) >= (d)->bottom)? \
     89 					(a)-(c) : (((a)-(c))-(d)->size))
     90 
     91 
     92 /*
     93  * The following is a clock, used to determine full, empty, etc.
     94  *
     95  * There is some trickiness here.  Since the ring buffers are initialized
     96  * to ZERO on allocation, we need to make sure, when interpreting the
     97  * clock, that when the times are EQUAL, then the buffer is FULL.
     98  */
     99 static u_long ring_clock = 0;
    100 
    101 
    102 #define	ring_empty(d) (((d)->consume == (d)->supply) && \
    103 				((d)->consumetime >= (d)->supplytime))
    104 #define	ring_full(d) (((d)->supply == (d)->consume) && \
    105 				((d)->supplytime > (d)->consumetime))
    106 
    107 
    108 
    109 
    110 
    111 /* Buffer state transition routines */
    112 
    113     int
    114 ring_init(ring, buffer, count)
    115 Ring *ring;
    116     unsigned char *buffer;
    117     int count;
    118 {
    119     memset((char *)ring, 0, sizeof *ring);
    120 
    121     ring->size = count;
    122 
    123     ring->supply = ring->consume = ring->bottom = buffer;
    124 
    125     ring->top = ring->bottom+ring->size;
    126 
    127 
    128     return 1;
    129 }
    130 
    131 /* Mark routines */
    132 
    133 /*
    134  * Mark the most recently supplied byte.
    135  */
    136 
    137     void
    138 ring_mark(ring)
    139     Ring *ring;
    140 {
    141     ring->mark = ring_decrement(ring, ring->supply, 1);
    142 }
    143 
    144 /*
    145  * Is the ring pointing to the mark?
    146  */
    147 
    148     int
    149 ring_at_mark(ring)
    150     Ring *ring;
    151 {
    152     if (ring->mark == ring->consume) {
    153 	return 1;
    154     } else {
    155 	return 0;
    156     }
    157 }
    158 
    159 /*
    160  * Clear any mark set on the ring.
    161  */
    162 
    163     void
    164 ring_clear_mark(ring)
    165     Ring *ring;
    166 {
    167     ring->mark = 0;
    168 }
    169 
    170 /*
    171  * Add characters from current segment to ring buffer.
    172  */
    173     void
    174 ring_supplied(ring, count)
    175     Ring *ring;
    176     int count;
    177 {
    178     ring->supply = ring_increment(ring, ring->supply, count);
    179     ring->supplytime = ++ring_clock;
    180 }
    181 
    182 /*
    183  * We have just consumed "c" bytes.
    184  */
    185     void
    186 ring_consumed(ring, count)
    187     Ring *ring;
    188     int count;
    189 {
    190     if (count == 0)	/* don't update anything */
    191 	return;
    192 
    193     if (ring->mark &&
    194 		(ring_subtract(ring, ring->mark, ring->consume) < count)) {
    195 	ring->mark = 0;
    196     }
    197     ring->consume = ring_increment(ring, ring->consume, count);
    198     ring->consumetime = ++ring_clock;
    199     /*
    200      * Try to encourage "ring_empty_consecutive()" to be large.
    201      */
    202     if (ring_empty(ring)) {
    203 	ring->consume = ring->supply = ring->bottom;
    204     }
    205 }
    206 
    207 
    208 
    209 /* Buffer state query routines */
    210 
    211 
    212 /* Number of bytes that may be supplied */
    213     int
    214 ring_empty_count(ring)
    215     Ring *ring;
    216 {
    217     if (ring_empty(ring)) {	/* if empty */
    218 	    return ring->size;
    219     } else {
    220 	return ring_subtract(ring, ring->consume, ring->supply);
    221     }
    222 }
    223 
    224 /* number of CONSECUTIVE bytes that may be supplied */
    225     int
    226 ring_empty_consecutive(ring)
    227     Ring *ring;
    228 {
    229     if ((ring->consume < ring->supply) || ring_empty(ring)) {
    230 			    /*
    231 			     * if consume is "below" supply, or empty, then
    232 			     * return distance to the top
    233 			     */
    234 	return ring_subtract(ring, ring->top, ring->supply);
    235     } else {
    236 				    /*
    237 				     * else, return what we may.
    238 				     */
    239 	return ring_subtract(ring, ring->consume, ring->supply);
    240     }
    241 }
    242 
    243 /* Return the number of bytes that are available for consuming
    244  * (but don't give more than enough to get to cross over set mark)
    245  */
    246 
    247     int
    248 ring_full_count(ring)
    249     Ring *ring;
    250 {
    251     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
    252 	if (ring_full(ring)) {
    253 	    return ring->size;	/* nothing consumed, but full */
    254 	} else {
    255 	    return ring_subtract(ring, ring->supply, ring->consume);
    256 	}
    257     } else {
    258 	return ring_subtract(ring, ring->mark, ring->consume);
    259     }
    260 }
    261 
    262 /*
    263  * Return the number of CONSECUTIVE bytes available for consuming.
    264  * However, don't return more than enough to cross over set mark.
    265  */
    266     int
    267 ring_full_consecutive(ring)
    268     Ring *ring;
    269 {
    270     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
    271 	if ((ring->supply < ring->consume) || ring_full(ring)) {
    272 	    return ring_subtract(ring, ring->top, ring->consume);
    273 	} else {
    274 	    return ring_subtract(ring, ring->supply, ring->consume);
    275 	}
    276     } else {
    277 	if (ring->mark < ring->consume) {
    278 	    return ring_subtract(ring, ring->top, ring->consume);
    279 	} else {	/* Else, distance to mark */
    280 	    return ring_subtract(ring, ring->mark, ring->consume);
    281 	}
    282     }
    283 }
    284 
    285 /*
    286  * Move data into the "supply" portion of of the ring buffer.
    287  */
    288     void
    289 ring_supply_data(ring, buffer, count)
    290     Ring *ring;
    291     unsigned char *buffer;
    292     int count;
    293 {
    294     int i;
    295 
    296     while (count) {
    297 	i = MIN(count, ring_empty_consecutive(ring));
    298 	memmove(ring->supply, buffer, i);
    299 	ring_supplied(ring, i);
    300 	count -= i;
    301 	buffer += i;
    302     }
    303 }
    304 
    305 #ifdef notdef
    306 
    307 /*
    308  * Move data from the "consume" portion of the ring buffer
    309  */
    310     void
    311 ring_consume_data(ring, buffer, count)
    312     Ring *ring;
    313     unsigned char *buffer;
    314     int count;
    315 {
    316     int i;
    317 
    318     while (count) {
    319 	i = MIN(count, ring_full_consecutive(ring));
    320 	memmove(buffer, ring->consume, i);
    321 	ring_consumed(ring, i);
    322 	count -= i;
    323 	buffer += i;
    324     }
    325 }
    326 #endif
    327 
    328