xref: /csrg-svn/usr.bin/telnet/ring.c (revision 38689)
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