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