xref: /aosp_15_r20/external/libwebsockets/lib/misc/lws-ring.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker struct lws_ring *
lws_ring_create(size_t element_len,size_t count,void (* destroy_element)(void *))28*1c60b9acSAndroid Build Coastguard Worker lws_ring_create(size_t element_len, size_t count,
29*1c60b9acSAndroid Build Coastguard Worker 		void (*destroy_element)(void *))
30*1c60b9acSAndroid Build Coastguard Worker {
31*1c60b9acSAndroid Build Coastguard Worker 	struct lws_ring *ring = lws_malloc(sizeof(*ring), "ring create");
32*1c60b9acSAndroid Build Coastguard Worker 
33*1c60b9acSAndroid Build Coastguard Worker 	if (!ring)
34*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
35*1c60b9acSAndroid Build Coastguard Worker 
36*1c60b9acSAndroid Build Coastguard Worker 	ring->buflen = (uint32_t)(count * element_len);
37*1c60b9acSAndroid Build Coastguard Worker 	ring->element_len = (uint32_t)element_len;
38*1c60b9acSAndroid Build Coastguard Worker 	ring->head = 0;
39*1c60b9acSAndroid Build Coastguard Worker 	ring->oldest_tail = 0;
40*1c60b9acSAndroid Build Coastguard Worker 	ring->destroy_element = destroy_element;
41*1c60b9acSAndroid Build Coastguard Worker 
42*1c60b9acSAndroid Build Coastguard Worker 	ring->buf = lws_malloc(ring->buflen, "ring buf");
43*1c60b9acSAndroid Build Coastguard Worker 	if (!ring->buf) {
44*1c60b9acSAndroid Build Coastguard Worker 		lws_free(ring);
45*1c60b9acSAndroid Build Coastguard Worker 
46*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
47*1c60b9acSAndroid Build Coastguard Worker 	}
48*1c60b9acSAndroid Build Coastguard Worker 
49*1c60b9acSAndroid Build Coastguard Worker 	return ring;
50*1c60b9acSAndroid Build Coastguard Worker }
51*1c60b9acSAndroid Build Coastguard Worker 
52*1c60b9acSAndroid Build Coastguard Worker void
lws_ring_destroy(struct lws_ring * ring)53*1c60b9acSAndroid Build Coastguard Worker lws_ring_destroy(struct lws_ring *ring)
54*1c60b9acSAndroid Build Coastguard Worker {
55*1c60b9acSAndroid Build Coastguard Worker 	if (ring->destroy_element)
56*1c60b9acSAndroid Build Coastguard Worker 		while (ring->oldest_tail != ring->head) {
57*1c60b9acSAndroid Build Coastguard Worker 			ring->destroy_element((uint8_t *)ring->buf +
58*1c60b9acSAndroid Build Coastguard Worker 					      ring->oldest_tail);
59*1c60b9acSAndroid Build Coastguard Worker 			ring->oldest_tail =
60*1c60b9acSAndroid Build Coastguard Worker 				(ring->oldest_tail + ring->element_len) %
61*1c60b9acSAndroid Build Coastguard Worker 				ring->buflen;
62*1c60b9acSAndroid Build Coastguard Worker 		}
63*1c60b9acSAndroid Build Coastguard Worker 	if (ring->buf)
64*1c60b9acSAndroid Build Coastguard Worker 		lws_free_set_NULL(ring->buf);
65*1c60b9acSAndroid Build Coastguard Worker 
66*1c60b9acSAndroid Build Coastguard Worker 	lws_free(ring);
67*1c60b9acSAndroid Build Coastguard Worker }
68*1c60b9acSAndroid Build Coastguard Worker 
69*1c60b9acSAndroid Build Coastguard Worker size_t
lws_ring_get_count_free_elements(struct lws_ring * ring)70*1c60b9acSAndroid Build Coastguard Worker lws_ring_get_count_free_elements(struct lws_ring *ring)
71*1c60b9acSAndroid Build Coastguard Worker {
72*1c60b9acSAndroid Build Coastguard Worker 	int f;
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker 	/*
75*1c60b9acSAndroid Build Coastguard Worker 	 * possible ringbuf patterns
76*1c60b9acSAndroid Build Coastguard Worker 	 *
77*1c60b9acSAndroid Build Coastguard Worker 	 * h == t
78*1c60b9acSAndroid Build Coastguard Worker 	 * |--------t***h---|
79*1c60b9acSAndroid Build Coastguard Worker 	 * |**h-----------t*|
80*1c60b9acSAndroid Build Coastguard Worker 	 * |t**************h|
81*1c60b9acSAndroid Build Coastguard Worker 	 * |*****ht*********|
82*1c60b9acSAndroid Build Coastguard Worker 	 */
83*1c60b9acSAndroid Build Coastguard Worker 	if (ring->head == ring->oldest_tail)
84*1c60b9acSAndroid Build Coastguard Worker 		f = (int)(ring->buflen - ring->element_len);
85*1c60b9acSAndroid Build Coastguard Worker 	else
86*1c60b9acSAndroid Build Coastguard Worker 		if (ring->head < ring->oldest_tail)
87*1c60b9acSAndroid Build Coastguard Worker 			f = (int)((ring->oldest_tail - ring->head) -
88*1c60b9acSAndroid Build Coastguard Worker 			    ring->element_len);
89*1c60b9acSAndroid Build Coastguard Worker 		else
90*1c60b9acSAndroid Build Coastguard Worker 			f = (int)((ring->buflen - ring->head) + ring->oldest_tail -
91*1c60b9acSAndroid Build Coastguard Worker 			    ring->element_len);
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	if (f < 2)
94*1c60b9acSAndroid Build Coastguard Worker 		return 0;
95*1c60b9acSAndroid Build Coastguard Worker 
96*1c60b9acSAndroid Build Coastguard Worker 	return (unsigned int)f / ring->element_len;
97*1c60b9acSAndroid Build Coastguard Worker }
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker size_t
lws_ring_get_count_waiting_elements(struct lws_ring * ring,uint32_t * tail)100*1c60b9acSAndroid Build Coastguard Worker lws_ring_get_count_waiting_elements(struct lws_ring *ring, uint32_t *tail)
101*1c60b9acSAndroid Build Coastguard Worker {	int f;
102*1c60b9acSAndroid Build Coastguard Worker 
103*1c60b9acSAndroid Build Coastguard Worker 	if (!tail)
104*1c60b9acSAndroid Build Coastguard Worker 		tail = &ring->oldest_tail;
105*1c60b9acSAndroid Build Coastguard Worker 	/*
106*1c60b9acSAndroid Build Coastguard Worker 	 * possible ringbuf patterns
107*1c60b9acSAndroid Build Coastguard Worker 	 *
108*1c60b9acSAndroid Build Coastguard Worker 	 * h == t
109*1c60b9acSAndroid Build Coastguard Worker 	 * |--------t***h---|
110*1c60b9acSAndroid Build Coastguard Worker 	 * |**h-----------t*|
111*1c60b9acSAndroid Build Coastguard Worker 	 * |t**************h|
112*1c60b9acSAndroid Build Coastguard Worker 	 * |*****ht*********|
113*1c60b9acSAndroid Build Coastguard Worker 	 */
114*1c60b9acSAndroid Build Coastguard Worker 	if (ring->head == *tail)
115*1c60b9acSAndroid Build Coastguard Worker 		f = 0;
116*1c60b9acSAndroid Build Coastguard Worker 	else
117*1c60b9acSAndroid Build Coastguard Worker 		if (ring->head > *tail)
118*1c60b9acSAndroid Build Coastguard Worker 			f = (int)(ring->head - *tail);
119*1c60b9acSAndroid Build Coastguard Worker 		else
120*1c60b9acSAndroid Build Coastguard Worker 			f = (int)((ring->buflen - *tail) + ring->head);
121*1c60b9acSAndroid Build Coastguard Worker 
122*1c60b9acSAndroid Build Coastguard Worker 	return (unsigned int)f / ring->element_len;
123*1c60b9acSAndroid Build Coastguard Worker }
124*1c60b9acSAndroid Build Coastguard Worker 
125*1c60b9acSAndroid Build Coastguard Worker int
lws_ring_next_linear_insert_range(struct lws_ring * ring,void ** start,size_t * bytes)126*1c60b9acSAndroid Build Coastguard Worker lws_ring_next_linear_insert_range(struct lws_ring *ring, void **start,
127*1c60b9acSAndroid Build Coastguard Worker 				  size_t *bytes)
128*1c60b9acSAndroid Build Coastguard Worker {
129*1c60b9acSAndroid Build Coastguard Worker 	int n;
130*1c60b9acSAndroid Build Coastguard Worker 
131*1c60b9acSAndroid Build Coastguard Worker 	/* n is how many bytes the whole fifo can take */
132*1c60b9acSAndroid Build Coastguard Worker 	n = (int)(lws_ring_get_count_free_elements(ring) * ring->element_len);
133*1c60b9acSAndroid Build Coastguard Worker 
134*1c60b9acSAndroid Build Coastguard Worker 	if (!n)
135*1c60b9acSAndroid Build Coastguard Worker 		return 1;
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker 	if (ring->head + (unsigned int)n > ring->buflen) {
138*1c60b9acSAndroid Build Coastguard Worker 		*start = (void *)(((uint8_t *)ring->buf) + ring->head);
139*1c60b9acSAndroid Build Coastguard Worker 		*bytes = ring->buflen - ring->head;
140*1c60b9acSAndroid Build Coastguard Worker 
141*1c60b9acSAndroid Build Coastguard Worker 		return 0;
142*1c60b9acSAndroid Build Coastguard Worker 	}
143*1c60b9acSAndroid Build Coastguard Worker 
144*1c60b9acSAndroid Build Coastguard Worker 	*start = (void *)(((uint8_t *)ring->buf) + ring->head);
145*1c60b9acSAndroid Build Coastguard Worker 	*bytes = (unsigned int)n;
146*1c60b9acSAndroid Build Coastguard Worker 
147*1c60b9acSAndroid Build Coastguard Worker 	return 0;
148*1c60b9acSAndroid Build Coastguard Worker }
149*1c60b9acSAndroid Build Coastguard Worker 
150*1c60b9acSAndroid Build Coastguard Worker void
lws_ring_bump_head(struct lws_ring * ring,size_t bytes)151*1c60b9acSAndroid Build Coastguard Worker lws_ring_bump_head(struct lws_ring *ring, size_t bytes)
152*1c60b9acSAndroid Build Coastguard Worker {
153*1c60b9acSAndroid Build Coastguard Worker 	ring->head = (ring->head + (uint32_t)bytes) % ring->buflen;
154*1c60b9acSAndroid Build Coastguard Worker }
155*1c60b9acSAndroid Build Coastguard Worker 
156*1c60b9acSAndroid Build Coastguard Worker size_t
lws_ring_insert(struct lws_ring * ring,const void * src,size_t max_count)157*1c60b9acSAndroid Build Coastguard Worker lws_ring_insert(struct lws_ring *ring, const void *src, size_t max_count)
158*1c60b9acSAndroid Build Coastguard Worker {
159*1c60b9acSAndroid Build Coastguard Worker 	const uint8_t *osrc = src;
160*1c60b9acSAndroid Build Coastguard Worker 	size_t m;
161*1c60b9acSAndroid Build Coastguard Worker 	int n;
162*1c60b9acSAndroid Build Coastguard Worker 
163*1c60b9acSAndroid Build Coastguard Worker 	/* n is how many bytes the whole fifo can take */
164*1c60b9acSAndroid Build Coastguard Worker 	n = (int)(lws_ring_get_count_free_elements(ring) * ring->element_len);
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker 	/* restrict n to how much we want to insert */
167*1c60b9acSAndroid Build Coastguard Worker 	if ((uint32_t)n > max_count * ring->element_len)
168*1c60b9acSAndroid Build Coastguard Worker 		n = (int)(max_count * ring->element_len);
169*1c60b9acSAndroid Build Coastguard Worker 
170*1c60b9acSAndroid Build Coastguard Worker 	/*
171*1c60b9acSAndroid Build Coastguard Worker 	 * n is legal to insert, but as an optimization we can cut the
172*1c60b9acSAndroid Build Coastguard Worker 	 * insert into one or two memcpys, depending on if it wraps
173*1c60b9acSAndroid Build Coastguard Worker 	 */
174*1c60b9acSAndroid Build Coastguard Worker 	if (ring->head + (unsigned int)n > ring->buflen) {
175*1c60b9acSAndroid Build Coastguard Worker 
176*1c60b9acSAndroid Build Coastguard Worker 		/*
177*1c60b9acSAndroid Build Coastguard Worker 		 * He does wrap.  The first memcpy should take us up to
178*1c60b9acSAndroid Build Coastguard Worker 		 * the end of the buffer
179*1c60b9acSAndroid Build Coastguard Worker 		 */
180*1c60b9acSAndroid Build Coastguard Worker 
181*1c60b9acSAndroid Build Coastguard Worker 		m = ring->buflen - ring->head;
182*1c60b9acSAndroid Build Coastguard Worker 		memcpy(((uint8_t *)ring->buf) + ring->head, src, m);
183*1c60b9acSAndroid Build Coastguard Worker 		/* we know it will wrap exactly back to zero */
184*1c60b9acSAndroid Build Coastguard Worker 		ring->head = 0;
185*1c60b9acSAndroid Build Coastguard Worker 
186*1c60b9acSAndroid Build Coastguard Worker 		/* adapt the second memcpy for what we already did */
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 		src = ((uint8_t *)src) + m;
189*1c60b9acSAndroid Build Coastguard Worker 		n = n - (int)m;
190*1c60b9acSAndroid Build Coastguard Worker 	}
191*1c60b9acSAndroid Build Coastguard Worker 
192*1c60b9acSAndroid Build Coastguard Worker 	memcpy(((uint8_t *)ring->buf) + ring->head, src, (size_t)n);
193*1c60b9acSAndroid Build Coastguard Worker 	ring->head = (ring->head + (unsigned int)n) % ring->buflen;
194*1c60b9acSAndroid Build Coastguard Worker 
195*1c60b9acSAndroid Build Coastguard Worker 	return (unsigned long)(((uint8_t *)src + (unsigned int)n) - osrc) / ring->element_len;
196*1c60b9acSAndroid Build Coastguard Worker }
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker size_t
lws_ring_consume(struct lws_ring * ring,uint32_t * tail,void * dest,size_t max_count)199*1c60b9acSAndroid Build Coastguard Worker lws_ring_consume(struct lws_ring *ring, uint32_t *tail, void *dest,
200*1c60b9acSAndroid Build Coastguard Worker 		 size_t max_count)
201*1c60b9acSAndroid Build Coastguard Worker {
202*1c60b9acSAndroid Build Coastguard Worker 	uint8_t *odest = dest;
203*1c60b9acSAndroid Build Coastguard Worker 	void *orig_tail = tail;
204*1c60b9acSAndroid Build Coastguard Worker 	uint32_t fake_tail;
205*1c60b9acSAndroid Build Coastguard Worker 	int m, n;
206*1c60b9acSAndroid Build Coastguard Worker 
207*1c60b9acSAndroid Build Coastguard Worker 	if (!tail) {
208*1c60b9acSAndroid Build Coastguard Worker 		fake_tail = ring->oldest_tail;
209*1c60b9acSAndroid Build Coastguard Worker 		tail = &fake_tail;
210*1c60b9acSAndroid Build Coastguard Worker 	}
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker 	/* n is how many bytes the whole fifo has for us */
213*1c60b9acSAndroid Build Coastguard Worker 	n = (int)(lws_ring_get_count_waiting_elements(ring, tail) *
214*1c60b9acSAndroid Build Coastguard Worker 							ring->element_len);
215*1c60b9acSAndroid Build Coastguard Worker 
216*1c60b9acSAndroid Build Coastguard Worker 	/* restrict n to how much we want to insert */
217*1c60b9acSAndroid Build Coastguard Worker 	if ((size_t)n > max_count * ring->element_len)
218*1c60b9acSAndroid Build Coastguard Worker 		n = (int)(max_count * ring->element_len);
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 	if (!dest) {
221*1c60b9acSAndroid Build Coastguard Worker 		*tail = ((*tail) + (unsigned int)n) % ring->buflen;
222*1c60b9acSAndroid Build Coastguard Worker 		if (!orig_tail) /* single tail */
223*1c60b9acSAndroid Build Coastguard Worker 			lws_ring_update_oldest_tail(ring, *tail);
224*1c60b9acSAndroid Build Coastguard Worker 
225*1c60b9acSAndroid Build Coastguard Worker 		return (unsigned int)n / ring->element_len;
226*1c60b9acSAndroid Build Coastguard Worker 	}
227*1c60b9acSAndroid Build Coastguard Worker 	if (*tail + (unsigned int)n > ring->buflen) {
228*1c60b9acSAndroid Build Coastguard Worker 
229*1c60b9acSAndroid Build Coastguard Worker 		/*
230*1c60b9acSAndroid Build Coastguard Worker 		 * He does wrap.  The first memcpy should take us up to
231*1c60b9acSAndroid Build Coastguard Worker 		 * the end of the buffer
232*1c60b9acSAndroid Build Coastguard Worker 		 */
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 		m = (int32_t)(ring->buflen - *tail);
235*1c60b9acSAndroid Build Coastguard Worker 		memcpy(dest, ((uint8_t *)ring->buf) + *tail, (size_t)m);
236*1c60b9acSAndroid Build Coastguard Worker 		/* we know it will wrap exactly back to zero */
237*1c60b9acSAndroid Build Coastguard Worker 		*tail = 0;
238*1c60b9acSAndroid Build Coastguard Worker 
239*1c60b9acSAndroid Build Coastguard Worker 		/* adapt the second memcpy for what we already did */
240*1c60b9acSAndroid Build Coastguard Worker 
241*1c60b9acSAndroid Build Coastguard Worker 		dest = ((uint8_t *)dest) + m;
242*1c60b9acSAndroid Build Coastguard Worker 		n -= m;
243*1c60b9acSAndroid Build Coastguard Worker 	}
244*1c60b9acSAndroid Build Coastguard Worker 
245*1c60b9acSAndroid Build Coastguard Worker 	memcpy(dest, ((uint8_t *)ring->buf) + *tail, (size_t)n);
246*1c60b9acSAndroid Build Coastguard Worker 
247*1c60b9acSAndroid Build Coastguard Worker 	*tail = ((*tail) + (unsigned int)n) % ring->buflen;
248*1c60b9acSAndroid Build Coastguard Worker 	if (!orig_tail) /* single tail */
249*1c60b9acSAndroid Build Coastguard Worker 		lws_ring_update_oldest_tail(ring, *tail);
250*1c60b9acSAndroid Build Coastguard Worker 
251*1c60b9acSAndroid Build Coastguard Worker 	return (unsigned int)(((uint8_t *)dest + n) - odest) / (unsigned int)ring->element_len;
252*1c60b9acSAndroid Build Coastguard Worker }
253*1c60b9acSAndroid Build Coastguard Worker 
254*1c60b9acSAndroid Build Coastguard Worker const void *
lws_ring_get_element(struct lws_ring * ring,uint32_t * tail)255*1c60b9acSAndroid Build Coastguard Worker lws_ring_get_element(struct lws_ring *ring, uint32_t *tail)
256*1c60b9acSAndroid Build Coastguard Worker {
257*1c60b9acSAndroid Build Coastguard Worker 	if (!tail)
258*1c60b9acSAndroid Build Coastguard Worker 		tail = &ring->oldest_tail;
259*1c60b9acSAndroid Build Coastguard Worker 
260*1c60b9acSAndroid Build Coastguard Worker 	if (*tail == ring->head)
261*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker 	return ((uint8_t *)ring->buf) + *tail;
264*1c60b9acSAndroid Build Coastguard Worker }
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker void
lws_ring_update_oldest_tail(struct lws_ring * ring,uint32_t tail)267*1c60b9acSAndroid Build Coastguard Worker lws_ring_update_oldest_tail(struct lws_ring *ring, uint32_t tail)
268*1c60b9acSAndroid Build Coastguard Worker {
269*1c60b9acSAndroid Build Coastguard Worker 	if (!ring->destroy_element) {
270*1c60b9acSAndroid Build Coastguard Worker 		ring->oldest_tail = tail;
271*1c60b9acSAndroid Build Coastguard Worker 		return;
272*1c60b9acSAndroid Build Coastguard Worker 	}
273*1c60b9acSAndroid Build Coastguard Worker 
274*1c60b9acSAndroid Build Coastguard Worker 	while (ring->oldest_tail != tail) {
275*1c60b9acSAndroid Build Coastguard Worker 		ring->destroy_element((uint8_t *)ring->buf + ring->oldest_tail);
276*1c60b9acSAndroid Build Coastguard Worker 		ring->oldest_tail = (ring->oldest_tail + ring->element_len) %
277*1c60b9acSAndroid Build Coastguard Worker 				    ring->buflen;
278*1c60b9acSAndroid Build Coastguard Worker 	}
279*1c60b9acSAndroid Build Coastguard Worker }
280*1c60b9acSAndroid Build Coastguard Worker 
281*1c60b9acSAndroid Build Coastguard Worker uint32_t
lws_ring_get_oldest_tail(struct lws_ring * ring)282*1c60b9acSAndroid Build Coastguard Worker lws_ring_get_oldest_tail(struct lws_ring *ring)
283*1c60b9acSAndroid Build Coastguard Worker {
284*1c60b9acSAndroid Build Coastguard Worker 	return ring->oldest_tail;
285*1c60b9acSAndroid Build Coastguard Worker }
286*1c60b9acSAndroid Build Coastguard Worker 
287*1c60b9acSAndroid Build Coastguard Worker void
lws_ring_dump(struct lws_ring * ring,uint32_t * tail)288*1c60b9acSAndroid Build Coastguard Worker lws_ring_dump(struct lws_ring *ring, uint32_t *tail)
289*1c60b9acSAndroid Build Coastguard Worker {
290*1c60b9acSAndroid Build Coastguard Worker 	if (tail == NULL)
291*1c60b9acSAndroid Build Coastguard Worker 		tail = &ring->oldest_tail;
292*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("ring %p: buflen %u, elem_len %u, head %u, oldest_tail %u\n"
293*1c60b9acSAndroid Build Coastguard Worker 		    "     free_elems: %u; for tail %u, waiting elements: %u\n",
294*1c60b9acSAndroid Build Coastguard Worker 		    ring, (int)ring->buflen, (int)ring->element_len,
295*1c60b9acSAndroid Build Coastguard Worker 		    (int)ring->head, (int)ring->oldest_tail,
296*1c60b9acSAndroid Build Coastguard Worker 		    (int)lws_ring_get_count_free_elements(ring), (int)*tail,
297*1c60b9acSAndroid Build Coastguard Worker 		    (int)lws_ring_get_count_waiting_elements(ring, tail));
298*1c60b9acSAndroid Build Coastguard Worker }
299