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