1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright 2018 Google
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker #include "ring_buffer.h"
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker #include <errno.h>
8*61046927SAndroid Build Coastguard Worker #include <string.h>
9*61046927SAndroid Build Coastguard Worker #ifdef _MSC_VER
10*61046927SAndroid Build Coastguard Worker #include "aemu/base/msvc.h"
11*61046927SAndroid Build Coastguard Worker #else
12*61046927SAndroid Build Coastguard Worker #include <sys/time.h>
13*61046927SAndroid Build Coastguard Worker #endif
14*61046927SAndroid Build Coastguard Worker
15*61046927SAndroid Build Coastguard Worker #ifdef __x86_64__
16*61046927SAndroid Build Coastguard Worker #include <emmintrin.h>
17*61046927SAndroid Build Coastguard Worker #endif
18*61046927SAndroid Build Coastguard Worker
19*61046927SAndroid Build Coastguard Worker #ifdef _WIN32
20*61046927SAndroid Build Coastguard Worker #include <windows.h>
21*61046927SAndroid Build Coastguard Worker #else
22*61046927SAndroid Build Coastguard Worker #include <sched.h>
23*61046927SAndroid Build Coastguard Worker #include <unistd.h>
24*61046927SAndroid Build Coastguard Worker #endif
25*61046927SAndroid Build Coastguard Worker
26*61046927SAndroid Build Coastguard Worker #define RING_BUFFER_MASK (RING_BUFFER_SIZE - 1)
27*61046927SAndroid Build Coastguard Worker
28*61046927SAndroid Build Coastguard Worker #define RING_BUFFER_VERSION 1
29*61046927SAndroid Build Coastguard Worker
ring_buffer_init(struct ring_buffer * r)30*61046927SAndroid Build Coastguard Worker void ring_buffer_init(struct ring_buffer* r) {
31*61046927SAndroid Build Coastguard Worker r->host_version = 1;
32*61046927SAndroid Build Coastguard Worker r->write_pos = 0;
33*61046927SAndroid Build Coastguard Worker r->read_pos = 0;
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker r->read_live_count = 0;
36*61046927SAndroid Build Coastguard Worker r->read_yield_count = 0;
37*61046927SAndroid Build Coastguard Worker r->read_sleep_us_count = 0;
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker r->state = 0;
40*61046927SAndroid Build Coastguard Worker }
41*61046927SAndroid Build Coastguard Worker
get_ring_pos(uint32_t index)42*61046927SAndroid Build Coastguard Worker static uint32_t get_ring_pos(uint32_t index) { return index & RING_BUFFER_MASK; }
43*61046927SAndroid Build Coastguard Worker
ring_buffer_can_write(const struct ring_buffer * r,uint32_t bytes)44*61046927SAndroid Build Coastguard Worker bool ring_buffer_can_write(const struct ring_buffer* r, uint32_t bytes) {
45*61046927SAndroid Build Coastguard Worker uint32_t read_view;
46*61046927SAndroid Build Coastguard Worker __atomic_load(&r->read_pos, &read_view, __ATOMIC_SEQ_CST);
47*61046927SAndroid Build Coastguard Worker return get_ring_pos(read_view - r->write_pos - 1) >= bytes;
48*61046927SAndroid Build Coastguard Worker }
49*61046927SAndroid Build Coastguard Worker
ring_buffer_can_read(const struct ring_buffer * r,uint32_t bytes)50*61046927SAndroid Build Coastguard Worker bool ring_buffer_can_read(const struct ring_buffer* r, uint32_t bytes) {
51*61046927SAndroid Build Coastguard Worker uint32_t write_view;
52*61046927SAndroid Build Coastguard Worker __atomic_load(&r->write_pos, &write_view, __ATOMIC_SEQ_CST);
53*61046927SAndroid Build Coastguard Worker return get_ring_pos(write_view - r->read_pos) >= bytes;
54*61046927SAndroid Build Coastguard Worker }
55*61046927SAndroid Build Coastguard Worker
ring_buffer_write(struct ring_buffer * r,const void * data,uint32_t step_size,uint32_t steps)56*61046927SAndroid Build Coastguard Worker long ring_buffer_write(struct ring_buffer* r, const void* data, uint32_t step_size,
57*61046927SAndroid Build Coastguard Worker uint32_t steps) {
58*61046927SAndroid Build Coastguard Worker const uint8_t* data_bytes = (const uint8_t*)data;
59*61046927SAndroid Build Coastguard Worker uint32_t i;
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker for (i = 0; i < steps; ++i) {
62*61046927SAndroid Build Coastguard Worker if (!ring_buffer_can_write(r, step_size)) {
63*61046927SAndroid Build Coastguard Worker errno = -EAGAIN;
64*61046927SAndroid Build Coastguard Worker return (long)i;
65*61046927SAndroid Build Coastguard Worker }
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker // Needs to be split up into 2 writes for the edge case.
68*61046927SAndroid Build Coastguard Worker uint32_t available_at_end = RING_BUFFER_SIZE - get_ring_pos(r->write_pos);
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker if (step_size > available_at_end) {
71*61046927SAndroid Build Coastguard Worker uint32_t remaining = step_size - available_at_end;
72*61046927SAndroid Build Coastguard Worker memcpy(&r->buf[get_ring_pos(r->write_pos)], data_bytes + i * step_size,
73*61046927SAndroid Build Coastguard Worker available_at_end);
74*61046927SAndroid Build Coastguard Worker memcpy(&r->buf[get_ring_pos(r->write_pos + available_at_end)],
75*61046927SAndroid Build Coastguard Worker data_bytes + i * step_size + available_at_end, remaining);
76*61046927SAndroid Build Coastguard Worker } else {
77*61046927SAndroid Build Coastguard Worker memcpy(&r->buf[get_ring_pos(r->write_pos)], data_bytes + i * step_size, step_size);
78*61046927SAndroid Build Coastguard Worker }
79*61046927SAndroid Build Coastguard Worker
80*61046927SAndroid Build Coastguard Worker __atomic_add_fetch(&r->write_pos, step_size, __ATOMIC_SEQ_CST);
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker errno = 0;
84*61046927SAndroid Build Coastguard Worker return (long)steps;
85*61046927SAndroid Build Coastguard Worker }
86*61046927SAndroid Build Coastguard Worker
ring_buffer_read(struct ring_buffer * r,void * data,uint32_t step_size,uint32_t steps)87*61046927SAndroid Build Coastguard Worker long ring_buffer_read(struct ring_buffer* r, void* data, uint32_t step_size, uint32_t steps) {
88*61046927SAndroid Build Coastguard Worker uint8_t* data_bytes = (uint8_t*)data;
89*61046927SAndroid Build Coastguard Worker uint32_t i;
90*61046927SAndroid Build Coastguard Worker
91*61046927SAndroid Build Coastguard Worker for (i = 0; i < steps; ++i) {
92*61046927SAndroid Build Coastguard Worker if (!ring_buffer_can_read(r, step_size)) {
93*61046927SAndroid Build Coastguard Worker errno = -EAGAIN;
94*61046927SAndroid Build Coastguard Worker return (long)i;
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker // Needs to be split up into 2 reads for the edge case.
98*61046927SAndroid Build Coastguard Worker uint32_t available_at_end = RING_BUFFER_SIZE - get_ring_pos(r->read_pos);
99*61046927SAndroid Build Coastguard Worker
100*61046927SAndroid Build Coastguard Worker if (step_size > available_at_end) {
101*61046927SAndroid Build Coastguard Worker uint32_t remaining = step_size - available_at_end;
102*61046927SAndroid Build Coastguard Worker memcpy(data_bytes + i * step_size, &r->buf[get_ring_pos(r->read_pos)],
103*61046927SAndroid Build Coastguard Worker available_at_end);
104*61046927SAndroid Build Coastguard Worker memcpy(data_bytes + i * step_size + available_at_end,
105*61046927SAndroid Build Coastguard Worker &r->buf[get_ring_pos(r->read_pos + available_at_end)], remaining);
106*61046927SAndroid Build Coastguard Worker } else {
107*61046927SAndroid Build Coastguard Worker memcpy(data_bytes + i * step_size, &r->buf[get_ring_pos(r->read_pos)], step_size);
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker
110*61046927SAndroid Build Coastguard Worker __atomic_add_fetch(&r->read_pos, step_size, __ATOMIC_SEQ_CST);
111*61046927SAndroid Build Coastguard Worker }
112*61046927SAndroid Build Coastguard Worker
113*61046927SAndroid Build Coastguard Worker errno = 0;
114*61046927SAndroid Build Coastguard Worker return (long)steps;
115*61046927SAndroid Build Coastguard Worker }
116*61046927SAndroid Build Coastguard Worker
ring_buffer_advance_write(struct ring_buffer * r,uint32_t step_size,uint32_t steps)117*61046927SAndroid Build Coastguard Worker long ring_buffer_advance_write(struct ring_buffer* r, uint32_t step_size, uint32_t steps) {
118*61046927SAndroid Build Coastguard Worker uint32_t i;
119*61046927SAndroid Build Coastguard Worker
120*61046927SAndroid Build Coastguard Worker for (i = 0; i < steps; ++i) {
121*61046927SAndroid Build Coastguard Worker if (!ring_buffer_can_write(r, step_size)) {
122*61046927SAndroid Build Coastguard Worker errno = -EAGAIN;
123*61046927SAndroid Build Coastguard Worker return (long)i;
124*61046927SAndroid Build Coastguard Worker }
125*61046927SAndroid Build Coastguard Worker
126*61046927SAndroid Build Coastguard Worker __atomic_add_fetch(&r->write_pos, step_size, __ATOMIC_SEQ_CST);
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker errno = 0;
130*61046927SAndroid Build Coastguard Worker return (long)steps;
131*61046927SAndroid Build Coastguard Worker }
132*61046927SAndroid Build Coastguard Worker
ring_buffer_advance_read(struct ring_buffer * r,uint32_t step_size,uint32_t steps)133*61046927SAndroid Build Coastguard Worker long ring_buffer_advance_read(struct ring_buffer* r, uint32_t step_size, uint32_t steps) {
134*61046927SAndroid Build Coastguard Worker uint32_t i;
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker for (i = 0; i < steps; ++i) {
137*61046927SAndroid Build Coastguard Worker if (!ring_buffer_can_read(r, step_size)) {
138*61046927SAndroid Build Coastguard Worker errno = -EAGAIN;
139*61046927SAndroid Build Coastguard Worker return (long)i;
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker __atomic_add_fetch(&r->read_pos, step_size, __ATOMIC_SEQ_CST);
143*61046927SAndroid Build Coastguard Worker }
144*61046927SAndroid Build Coastguard Worker
145*61046927SAndroid Build Coastguard Worker errno = 0;
146*61046927SAndroid Build Coastguard Worker return (long)steps;
147*61046927SAndroid Build Coastguard Worker }
148*61046927SAndroid Build Coastguard Worker
ring_buffer_calc_shift(uint32_t size)149*61046927SAndroid Build Coastguard Worker uint32_t ring_buffer_calc_shift(uint32_t size) {
150*61046927SAndroid Build Coastguard Worker uint32_t shift = 0;
151*61046927SAndroid Build Coastguard Worker while ((1 << shift) < size) {
152*61046927SAndroid Build Coastguard Worker ++shift;
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker // if size is not a power of 2,
156*61046927SAndroid Build Coastguard Worker if ((1 << shift) > size) {
157*61046927SAndroid Build Coastguard Worker --shift;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker return shift;
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker
ring_buffer_view_init(struct ring_buffer * r,struct ring_buffer_view * v,uint8_t * buf,uint32_t size)162*61046927SAndroid Build Coastguard Worker void ring_buffer_view_init(struct ring_buffer* r, struct ring_buffer_view* v, uint8_t* buf,
163*61046927SAndroid Build Coastguard Worker uint32_t size) {
164*61046927SAndroid Build Coastguard Worker uint32_t shift = ring_buffer_calc_shift(size);
165*61046927SAndroid Build Coastguard Worker
166*61046927SAndroid Build Coastguard Worker ring_buffer_init(r);
167*61046927SAndroid Build Coastguard Worker
168*61046927SAndroid Build Coastguard Worker v->buf = buf;
169*61046927SAndroid Build Coastguard Worker v->size = (1 << shift);
170*61046927SAndroid Build Coastguard Worker v->mask = (1 << shift) - 1;
171*61046927SAndroid Build Coastguard Worker }
172*61046927SAndroid Build Coastguard Worker
ring_buffer_init_view_only(struct ring_buffer_view * v,uint8_t * buf,uint32_t size)173*61046927SAndroid Build Coastguard Worker void ring_buffer_init_view_only(struct ring_buffer_view* v, uint8_t* buf, uint32_t size) {
174*61046927SAndroid Build Coastguard Worker uint32_t shift = ring_buffer_calc_shift(size);
175*61046927SAndroid Build Coastguard Worker
176*61046927SAndroid Build Coastguard Worker v->buf = buf;
177*61046927SAndroid Build Coastguard Worker v->size = (1 << shift);
178*61046927SAndroid Build Coastguard Worker v->mask = (1 << shift) - 1;
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker
ring_buffer_view_get_ring_pos(const struct ring_buffer_view * v,uint32_t index)181*61046927SAndroid Build Coastguard Worker uint32_t ring_buffer_view_get_ring_pos(const struct ring_buffer_view* v, uint32_t index) {
182*61046927SAndroid Build Coastguard Worker return index & v->mask;
183*61046927SAndroid Build Coastguard Worker }
184*61046927SAndroid Build Coastguard Worker
ring_buffer_view_can_write(const struct ring_buffer * r,const struct ring_buffer_view * v,uint32_t bytes)185*61046927SAndroid Build Coastguard Worker bool ring_buffer_view_can_write(const struct ring_buffer* r, const struct ring_buffer_view* v,
186*61046927SAndroid Build Coastguard Worker uint32_t bytes) {
187*61046927SAndroid Build Coastguard Worker uint32_t read_view;
188*61046927SAndroid Build Coastguard Worker __atomic_load(&r->read_pos, &read_view, __ATOMIC_SEQ_CST);
189*61046927SAndroid Build Coastguard Worker return ring_buffer_view_get_ring_pos(v, read_view - r->write_pos - 1) >= bytes;
190*61046927SAndroid Build Coastguard Worker }
191*61046927SAndroid Build Coastguard Worker
ring_buffer_view_can_read(const struct ring_buffer * r,const struct ring_buffer_view * v,uint32_t bytes)192*61046927SAndroid Build Coastguard Worker bool ring_buffer_view_can_read(const struct ring_buffer* r, const struct ring_buffer_view* v,
193*61046927SAndroid Build Coastguard Worker uint32_t bytes) {
194*61046927SAndroid Build Coastguard Worker uint32_t write_view;
195*61046927SAndroid Build Coastguard Worker __atomic_load(&r->write_pos, &write_view, __ATOMIC_SEQ_CST);
196*61046927SAndroid Build Coastguard Worker return ring_buffer_view_get_ring_pos(v, write_view - r->read_pos) >= bytes;
197*61046927SAndroid Build Coastguard Worker }
198*61046927SAndroid Build Coastguard Worker
ring_buffer_available_read(const struct ring_buffer * r,const struct ring_buffer_view * v)199*61046927SAndroid Build Coastguard Worker uint32_t ring_buffer_available_read(const struct ring_buffer* r, const struct ring_buffer_view* v) {
200*61046927SAndroid Build Coastguard Worker uint32_t write_view;
201*61046927SAndroid Build Coastguard Worker __atomic_load(&r->write_pos, &write_view, __ATOMIC_SEQ_CST);
202*61046927SAndroid Build Coastguard Worker if (v) {
203*61046927SAndroid Build Coastguard Worker return ring_buffer_view_get_ring_pos(v, write_view - r->read_pos);
204*61046927SAndroid Build Coastguard Worker } else {
205*61046927SAndroid Build Coastguard Worker return get_ring_pos(write_view - r->read_pos);
206*61046927SAndroid Build Coastguard Worker }
207*61046927SAndroid Build Coastguard Worker }
208*61046927SAndroid Build Coastguard Worker
ring_buffer_available_write(const struct ring_buffer * r,const struct ring_buffer_view * v)209*61046927SAndroid Build Coastguard Worker uint32_t ring_buffer_available_write(const struct ring_buffer* r,
210*61046927SAndroid Build Coastguard Worker const struct ring_buffer_view* v) {
211*61046927SAndroid Build Coastguard Worker uint32_t read_view;
212*61046927SAndroid Build Coastguard Worker __atomic_load(&r->read_pos, &read_view, __ATOMIC_SEQ_CST);
213*61046927SAndroid Build Coastguard Worker if (v) {
214*61046927SAndroid Build Coastguard Worker return ring_buffer_view_get_ring_pos(v, read_view - r->write_pos - 1);
215*61046927SAndroid Build Coastguard Worker } else {
216*61046927SAndroid Build Coastguard Worker return get_ring_pos(read_view - r->write_pos - 1);
217*61046927SAndroid Build Coastguard Worker }
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker
ring_buffer_copy_contents(const struct ring_buffer * r,const struct ring_buffer_view * v,uint32_t wanted_bytes,uint8_t * res)220*61046927SAndroid Build Coastguard Worker int ring_buffer_copy_contents(const struct ring_buffer* r, const struct ring_buffer_view* v,
221*61046927SAndroid Build Coastguard Worker uint32_t wanted_bytes, uint8_t* res) {
222*61046927SAndroid Build Coastguard Worker uint32_t total_available = ring_buffer_available_read(r, v);
223*61046927SAndroid Build Coastguard Worker uint32_t available_at_end = 0;
224*61046927SAndroid Build Coastguard Worker
225*61046927SAndroid Build Coastguard Worker if (v) {
226*61046927SAndroid Build Coastguard Worker available_at_end = v->size - ring_buffer_view_get_ring_pos(v, r->read_pos);
227*61046927SAndroid Build Coastguard Worker } else {
228*61046927SAndroid Build Coastguard Worker available_at_end = RING_BUFFER_SIZE - get_ring_pos(r->write_pos);
229*61046927SAndroid Build Coastguard Worker }
230*61046927SAndroid Build Coastguard Worker
231*61046927SAndroid Build Coastguard Worker if (total_available < wanted_bytes) {
232*61046927SAndroid Build Coastguard Worker return -1;
233*61046927SAndroid Build Coastguard Worker }
234*61046927SAndroid Build Coastguard Worker
235*61046927SAndroid Build Coastguard Worker if (v) {
236*61046927SAndroid Build Coastguard Worker if (wanted_bytes > available_at_end) {
237*61046927SAndroid Build Coastguard Worker uint32_t remaining = wanted_bytes - available_at_end;
238*61046927SAndroid Build Coastguard Worker memcpy(res, &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos)], available_at_end);
239*61046927SAndroid Build Coastguard Worker memcpy(res + available_at_end,
240*61046927SAndroid Build Coastguard Worker &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos + available_at_end)],
241*61046927SAndroid Build Coastguard Worker remaining);
242*61046927SAndroid Build Coastguard Worker } else {
243*61046927SAndroid Build Coastguard Worker memcpy(res, &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos)], wanted_bytes);
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker } else {
246*61046927SAndroid Build Coastguard Worker if (wanted_bytes > available_at_end) {
247*61046927SAndroid Build Coastguard Worker uint32_t remaining = wanted_bytes - available_at_end;
248*61046927SAndroid Build Coastguard Worker memcpy(res, &r->buf[get_ring_pos(r->read_pos)], available_at_end);
249*61046927SAndroid Build Coastguard Worker memcpy(res + available_at_end, &r->buf[get_ring_pos(r->read_pos + available_at_end)],
250*61046927SAndroid Build Coastguard Worker remaining);
251*61046927SAndroid Build Coastguard Worker } else {
252*61046927SAndroid Build Coastguard Worker memcpy(res, &r->buf[get_ring_pos(r->read_pos)], wanted_bytes);
253*61046927SAndroid Build Coastguard Worker }
254*61046927SAndroid Build Coastguard Worker }
255*61046927SAndroid Build Coastguard Worker return 0;
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker
ring_buffer_view_write(struct ring_buffer * r,struct ring_buffer_view * v,const void * data,uint32_t step_size,uint32_t steps)258*61046927SAndroid Build Coastguard Worker long ring_buffer_view_write(struct ring_buffer* r, struct ring_buffer_view* v, const void* data,
259*61046927SAndroid Build Coastguard Worker uint32_t step_size, uint32_t steps) {
260*61046927SAndroid Build Coastguard Worker uint8_t* data_bytes = (uint8_t*)data;
261*61046927SAndroid Build Coastguard Worker uint32_t i;
262*61046927SAndroid Build Coastguard Worker
263*61046927SAndroid Build Coastguard Worker for (i = 0; i < steps; ++i) {
264*61046927SAndroid Build Coastguard Worker if (!ring_buffer_view_can_write(r, v, step_size)) {
265*61046927SAndroid Build Coastguard Worker errno = -EAGAIN;
266*61046927SAndroid Build Coastguard Worker return (long)i;
267*61046927SAndroid Build Coastguard Worker }
268*61046927SAndroid Build Coastguard Worker
269*61046927SAndroid Build Coastguard Worker // Needs to be split up into 2 writes for the edge case.
270*61046927SAndroid Build Coastguard Worker uint32_t available_at_end = v->size - ring_buffer_view_get_ring_pos(v, r->write_pos);
271*61046927SAndroid Build Coastguard Worker
272*61046927SAndroid Build Coastguard Worker if (step_size > available_at_end) {
273*61046927SAndroid Build Coastguard Worker uint32_t remaining = step_size - available_at_end;
274*61046927SAndroid Build Coastguard Worker memcpy(&v->buf[ring_buffer_view_get_ring_pos(v, r->write_pos)],
275*61046927SAndroid Build Coastguard Worker data_bytes + i * step_size, available_at_end);
276*61046927SAndroid Build Coastguard Worker memcpy(&v->buf[ring_buffer_view_get_ring_pos(v, r->write_pos + available_at_end)],
277*61046927SAndroid Build Coastguard Worker data_bytes + i * step_size + available_at_end, remaining);
278*61046927SAndroid Build Coastguard Worker } else {
279*61046927SAndroid Build Coastguard Worker memcpy(&v->buf[ring_buffer_view_get_ring_pos(v, r->write_pos)],
280*61046927SAndroid Build Coastguard Worker data_bytes + i * step_size, step_size);
281*61046927SAndroid Build Coastguard Worker }
282*61046927SAndroid Build Coastguard Worker
283*61046927SAndroid Build Coastguard Worker __atomic_add_fetch(&r->write_pos, step_size, __ATOMIC_SEQ_CST);
284*61046927SAndroid Build Coastguard Worker }
285*61046927SAndroid Build Coastguard Worker
286*61046927SAndroid Build Coastguard Worker errno = 0;
287*61046927SAndroid Build Coastguard Worker return (long)steps;
288*61046927SAndroid Build Coastguard Worker }
289*61046927SAndroid Build Coastguard Worker
ring_buffer_view_read(struct ring_buffer * r,struct ring_buffer_view * v,void * data,uint32_t step_size,uint32_t steps)290*61046927SAndroid Build Coastguard Worker long ring_buffer_view_read(struct ring_buffer* r, struct ring_buffer_view* v, void* data,
291*61046927SAndroid Build Coastguard Worker uint32_t step_size, uint32_t steps) {
292*61046927SAndroid Build Coastguard Worker uint8_t* data_bytes = (uint8_t*)data;
293*61046927SAndroid Build Coastguard Worker uint32_t i;
294*61046927SAndroid Build Coastguard Worker
295*61046927SAndroid Build Coastguard Worker for (i = 0; i < steps; ++i) {
296*61046927SAndroid Build Coastguard Worker if (!ring_buffer_view_can_read(r, v, step_size)) {
297*61046927SAndroid Build Coastguard Worker errno = -EAGAIN;
298*61046927SAndroid Build Coastguard Worker return (long)i;
299*61046927SAndroid Build Coastguard Worker }
300*61046927SAndroid Build Coastguard Worker
301*61046927SAndroid Build Coastguard Worker // Needs to be split up into 2 reads for the edge case.
302*61046927SAndroid Build Coastguard Worker uint32_t available_at_end = v->size - ring_buffer_view_get_ring_pos(v, r->read_pos);
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker if (step_size > available_at_end) {
305*61046927SAndroid Build Coastguard Worker uint32_t remaining = step_size - available_at_end;
306*61046927SAndroid Build Coastguard Worker memcpy(data_bytes + i * step_size,
307*61046927SAndroid Build Coastguard Worker &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos)], available_at_end);
308*61046927SAndroid Build Coastguard Worker memcpy(data_bytes + i * step_size + available_at_end,
309*61046927SAndroid Build Coastguard Worker &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos + available_at_end)],
310*61046927SAndroid Build Coastguard Worker remaining);
311*61046927SAndroid Build Coastguard Worker } else {
312*61046927SAndroid Build Coastguard Worker memcpy(data_bytes + i * step_size,
313*61046927SAndroid Build Coastguard Worker &v->buf[ring_buffer_view_get_ring_pos(v, r->read_pos)], step_size);
314*61046927SAndroid Build Coastguard Worker }
315*61046927SAndroid Build Coastguard Worker __atomic_add_fetch(&r->read_pos, step_size, __ATOMIC_SEQ_CST);
316*61046927SAndroid Build Coastguard Worker }
317*61046927SAndroid Build Coastguard Worker
318*61046927SAndroid Build Coastguard Worker errno = 0;
319*61046927SAndroid Build Coastguard Worker return (long)steps;
320*61046927SAndroid Build Coastguard Worker }
321*61046927SAndroid Build Coastguard Worker
ring_buffer_yield()322*61046927SAndroid Build Coastguard Worker void ring_buffer_yield() {
323*61046927SAndroid Build Coastguard Worker #ifdef _WIN32
324*61046927SAndroid Build Coastguard Worker _mm_pause();
325*61046927SAndroid Build Coastguard Worker #else
326*61046927SAndroid Build Coastguard Worker sched_yield();
327*61046927SAndroid Build Coastguard Worker #endif
328*61046927SAndroid Build Coastguard Worker }
329*61046927SAndroid Build Coastguard Worker
ring_buffer_sleep()330*61046927SAndroid Build Coastguard Worker static void ring_buffer_sleep() {
331*61046927SAndroid Build Coastguard Worker #ifdef _WIN32
332*61046927SAndroid Build Coastguard Worker Sleep(2);
333*61046927SAndroid Build Coastguard Worker #else
334*61046927SAndroid Build Coastguard Worker usleep(2000);
335*61046927SAndroid Build Coastguard Worker #endif
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker
ring_buffer_curr_us()338*61046927SAndroid Build Coastguard Worker static uint64_t ring_buffer_curr_us() {
339*61046927SAndroid Build Coastguard Worker uint64_t res;
340*61046927SAndroid Build Coastguard Worker struct timeval tv;
341*61046927SAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
342*61046927SAndroid Build Coastguard Worker res = tv.tv_sec * 1000000ULL + tv.tv_usec;
343*61046927SAndroid Build Coastguard Worker return res;
344*61046927SAndroid Build Coastguard Worker }
345*61046927SAndroid Build Coastguard Worker
346*61046927SAndroid Build Coastguard Worker static const uint32_t yield_backoff_us = 1000;
347*61046927SAndroid Build Coastguard Worker static const uint32_t sleep_backoff_us = 2000;
348*61046927SAndroid Build Coastguard Worker
ring_buffer_wait_write(const struct ring_buffer * r,const struct ring_buffer_view * v,uint32_t bytes,uint64_t timeout_us)349*61046927SAndroid Build Coastguard Worker bool ring_buffer_wait_write(const struct ring_buffer* r, const struct ring_buffer_view* v,
350*61046927SAndroid Build Coastguard Worker uint32_t bytes, uint64_t timeout_us) {
351*61046927SAndroid Build Coastguard Worker uint64_t start_us = ring_buffer_curr_us();
352*61046927SAndroid Build Coastguard Worker uint64_t curr_wait_us;
353*61046927SAndroid Build Coastguard Worker
354*61046927SAndroid Build Coastguard Worker bool can_write = v ? ring_buffer_view_can_write(r, v, bytes) : ring_buffer_can_write(r, bytes);
355*61046927SAndroid Build Coastguard Worker
356*61046927SAndroid Build Coastguard Worker while (!can_write) {
357*61046927SAndroid Build Coastguard Worker #ifdef __x86_64
358*61046927SAndroid Build Coastguard Worker _mm_pause();
359*61046927SAndroid Build Coastguard Worker #endif
360*61046927SAndroid Build Coastguard Worker curr_wait_us = ring_buffer_curr_us() - start_us;
361*61046927SAndroid Build Coastguard Worker
362*61046927SAndroid Build Coastguard Worker if (curr_wait_us > yield_backoff_us) {
363*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
364*61046927SAndroid Build Coastguard Worker }
365*61046927SAndroid Build Coastguard Worker
366*61046927SAndroid Build Coastguard Worker if (curr_wait_us > sleep_backoff_us) {
367*61046927SAndroid Build Coastguard Worker ring_buffer_sleep();
368*61046927SAndroid Build Coastguard Worker }
369*61046927SAndroid Build Coastguard Worker
370*61046927SAndroid Build Coastguard Worker if (curr_wait_us > timeout_us) {
371*61046927SAndroid Build Coastguard Worker return false;
372*61046927SAndroid Build Coastguard Worker }
373*61046927SAndroid Build Coastguard Worker
374*61046927SAndroid Build Coastguard Worker can_write = v ? ring_buffer_view_can_write(r, v, bytes) : ring_buffer_can_write(r, bytes);
375*61046927SAndroid Build Coastguard Worker }
376*61046927SAndroid Build Coastguard Worker
377*61046927SAndroid Build Coastguard Worker return true;
378*61046927SAndroid Build Coastguard Worker }
379*61046927SAndroid Build Coastguard Worker
ring_buffer_wait_read(const struct ring_buffer * r,const struct ring_buffer_view * v,uint32_t bytes,uint64_t timeout_us)380*61046927SAndroid Build Coastguard Worker bool ring_buffer_wait_read(const struct ring_buffer* r, const struct ring_buffer_view* v,
381*61046927SAndroid Build Coastguard Worker uint32_t bytes, uint64_t timeout_us) {
382*61046927SAndroid Build Coastguard Worker uint64_t start_us = ring_buffer_curr_us();
383*61046927SAndroid Build Coastguard Worker uint64_t curr_wait_us;
384*61046927SAndroid Build Coastguard Worker
385*61046927SAndroid Build Coastguard Worker bool can_read = v ? ring_buffer_view_can_read(r, v, bytes) : ring_buffer_can_read(r, bytes);
386*61046927SAndroid Build Coastguard Worker
387*61046927SAndroid Build Coastguard Worker while (!can_read) {
388*61046927SAndroid Build Coastguard Worker // TODO(bohu): find aarch64 equivalent
389*61046927SAndroid Build Coastguard Worker #ifdef __x86_64
390*61046927SAndroid Build Coastguard Worker _mm_pause();
391*61046927SAndroid Build Coastguard Worker #endif
392*61046927SAndroid Build Coastguard Worker curr_wait_us = ring_buffer_curr_us() - start_us;
393*61046927SAndroid Build Coastguard Worker
394*61046927SAndroid Build Coastguard Worker if (curr_wait_us > yield_backoff_us) {
395*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
396*61046927SAndroid Build Coastguard Worker ((struct ring_buffer*)r)->read_yield_count++;
397*61046927SAndroid Build Coastguard Worker }
398*61046927SAndroid Build Coastguard Worker
399*61046927SAndroid Build Coastguard Worker if (curr_wait_us > sleep_backoff_us) {
400*61046927SAndroid Build Coastguard Worker ring_buffer_sleep();
401*61046927SAndroid Build Coastguard Worker ((struct ring_buffer*)r)->read_sleep_us_count += 2000;
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker
404*61046927SAndroid Build Coastguard Worker if (curr_wait_us > timeout_us) {
405*61046927SAndroid Build Coastguard Worker return false;
406*61046927SAndroid Build Coastguard Worker }
407*61046927SAndroid Build Coastguard Worker
408*61046927SAndroid Build Coastguard Worker can_read = v ? ring_buffer_view_can_read(r, v, bytes) : ring_buffer_can_read(r, bytes);
409*61046927SAndroid Build Coastguard Worker }
410*61046927SAndroid Build Coastguard Worker
411*61046927SAndroid Build Coastguard Worker ((struct ring_buffer*)r)->read_live_count++;
412*61046927SAndroid Build Coastguard Worker return true;
413*61046927SAndroid Build Coastguard Worker }
414*61046927SAndroid Build Coastguard Worker
get_step_size(struct ring_buffer * r,struct ring_buffer_view * v,uint32_t bytes)415*61046927SAndroid Build Coastguard Worker static uint32_t get_step_size(struct ring_buffer* r, struct ring_buffer_view* v, uint32_t bytes) {
416*61046927SAndroid Build Coastguard Worker uint32_t available = v ? (v->size >> 1) : (RING_BUFFER_SIZE >> 1);
417*61046927SAndroid Build Coastguard Worker uint32_t res = available < bytes ? available : bytes;
418*61046927SAndroid Build Coastguard Worker
419*61046927SAndroid Build Coastguard Worker return res;
420*61046927SAndroid Build Coastguard Worker }
421*61046927SAndroid Build Coastguard Worker
ring_buffer_write_fully(struct ring_buffer * r,struct ring_buffer_view * v,const void * data,uint32_t bytes)422*61046927SAndroid Build Coastguard Worker void ring_buffer_write_fully(struct ring_buffer* r, struct ring_buffer_view* v, const void* data,
423*61046927SAndroid Build Coastguard Worker uint32_t bytes) {
424*61046927SAndroid Build Coastguard Worker ring_buffer_write_fully_with_abort(r, v, data, bytes, 0, 0);
425*61046927SAndroid Build Coastguard Worker }
426*61046927SAndroid Build Coastguard Worker
ring_buffer_read_fully(struct ring_buffer * r,struct ring_buffer_view * v,void * data,uint32_t bytes)427*61046927SAndroid Build Coastguard Worker void ring_buffer_read_fully(struct ring_buffer* r, struct ring_buffer_view* v, void* data,
428*61046927SAndroid Build Coastguard Worker uint32_t bytes) {
429*61046927SAndroid Build Coastguard Worker ring_buffer_read_fully_with_abort(r, v, data, bytes, 0, 0);
430*61046927SAndroid Build Coastguard Worker }
431*61046927SAndroid Build Coastguard Worker
ring_buffer_write_fully_with_abort(struct ring_buffer * r,struct ring_buffer_view * v,const void * data,uint32_t bytes,uint32_t abort_value,const volatile uint32_t * abort_ptr)432*61046927SAndroid Build Coastguard Worker uint32_t ring_buffer_write_fully_with_abort(struct ring_buffer* r, struct ring_buffer_view* v,
433*61046927SAndroid Build Coastguard Worker const void* data, uint32_t bytes, uint32_t abort_value,
434*61046927SAndroid Build Coastguard Worker const volatile uint32_t* abort_ptr) {
435*61046927SAndroid Build Coastguard Worker uint32_t candidate_step = get_step_size(r, v, bytes);
436*61046927SAndroid Build Coastguard Worker uint32_t processed = 0;
437*61046927SAndroid Build Coastguard Worker
438*61046927SAndroid Build Coastguard Worker uint8_t* dst = (uint8_t*)data;
439*61046927SAndroid Build Coastguard Worker
440*61046927SAndroid Build Coastguard Worker while (processed < bytes) {
441*61046927SAndroid Build Coastguard Worker if (bytes - processed < candidate_step) {
442*61046927SAndroid Build Coastguard Worker candidate_step = bytes - processed;
443*61046927SAndroid Build Coastguard Worker }
444*61046927SAndroid Build Coastguard Worker
445*61046927SAndroid Build Coastguard Worker long processed_here = 0;
446*61046927SAndroid Build Coastguard Worker ring_buffer_wait_write(r, v, candidate_step, (uint64_t)(-1));
447*61046927SAndroid Build Coastguard Worker
448*61046927SAndroid Build Coastguard Worker if (v) {
449*61046927SAndroid Build Coastguard Worker processed_here = ring_buffer_view_write(r, v, dst + processed, candidate_step, 1);
450*61046927SAndroid Build Coastguard Worker } else {
451*61046927SAndroid Build Coastguard Worker processed_here = ring_buffer_write(r, dst + processed, candidate_step, 1);
452*61046927SAndroid Build Coastguard Worker }
453*61046927SAndroid Build Coastguard Worker
454*61046927SAndroid Build Coastguard Worker processed += processed_here ? candidate_step : 0;
455*61046927SAndroid Build Coastguard Worker
456*61046927SAndroid Build Coastguard Worker if (abort_ptr && (abort_value == *abort_ptr)) {
457*61046927SAndroid Build Coastguard Worker return processed;
458*61046927SAndroid Build Coastguard Worker }
459*61046927SAndroid Build Coastguard Worker }
460*61046927SAndroid Build Coastguard Worker
461*61046927SAndroid Build Coastguard Worker return processed;
462*61046927SAndroid Build Coastguard Worker }
463*61046927SAndroid Build Coastguard Worker
ring_buffer_read_fully_with_abort(struct ring_buffer * r,struct ring_buffer_view * v,void * data,uint32_t bytes,uint32_t abort_value,const volatile uint32_t * abort_ptr)464*61046927SAndroid Build Coastguard Worker uint32_t ring_buffer_read_fully_with_abort(struct ring_buffer* r, struct ring_buffer_view* v,
465*61046927SAndroid Build Coastguard Worker void* data, uint32_t bytes, uint32_t abort_value,
466*61046927SAndroid Build Coastguard Worker const volatile uint32_t* abort_ptr) {
467*61046927SAndroid Build Coastguard Worker uint32_t candidate_step = get_step_size(r, v, bytes);
468*61046927SAndroid Build Coastguard Worker uint32_t processed = 0;
469*61046927SAndroid Build Coastguard Worker
470*61046927SAndroid Build Coastguard Worker uint8_t* dst = (uint8_t*)data;
471*61046927SAndroid Build Coastguard Worker
472*61046927SAndroid Build Coastguard Worker while (processed < bytes) {
473*61046927SAndroid Build Coastguard Worker #ifdef __x86_64
474*61046927SAndroid Build Coastguard Worker _mm_pause();
475*61046927SAndroid Build Coastguard Worker #endif
476*61046927SAndroid Build Coastguard Worker if (bytes - processed < candidate_step) {
477*61046927SAndroid Build Coastguard Worker candidate_step = bytes - processed;
478*61046927SAndroid Build Coastguard Worker }
479*61046927SAndroid Build Coastguard Worker
480*61046927SAndroid Build Coastguard Worker long processed_here = 0;
481*61046927SAndroid Build Coastguard Worker ring_buffer_wait_read(r, v, candidate_step, (uint64_t)(-1));
482*61046927SAndroid Build Coastguard Worker
483*61046927SAndroid Build Coastguard Worker if (v) {
484*61046927SAndroid Build Coastguard Worker processed_here = ring_buffer_view_read(r, v, dst + processed, candidate_step, 1);
485*61046927SAndroid Build Coastguard Worker } else {
486*61046927SAndroid Build Coastguard Worker processed_here = ring_buffer_read(r, dst + processed, candidate_step, 1);
487*61046927SAndroid Build Coastguard Worker }
488*61046927SAndroid Build Coastguard Worker
489*61046927SAndroid Build Coastguard Worker processed += processed_here ? candidate_step : 0;
490*61046927SAndroid Build Coastguard Worker
491*61046927SAndroid Build Coastguard Worker if (abort_ptr && (abort_value == *abort_ptr)) {
492*61046927SAndroid Build Coastguard Worker return processed;
493*61046927SAndroid Build Coastguard Worker }
494*61046927SAndroid Build Coastguard Worker }
495*61046927SAndroid Build Coastguard Worker
496*61046927SAndroid Build Coastguard Worker return processed;
497*61046927SAndroid Build Coastguard Worker }
498*61046927SAndroid Build Coastguard Worker
ring_buffer_sync_init(struct ring_buffer * r)499*61046927SAndroid Build Coastguard Worker void ring_buffer_sync_init(struct ring_buffer* r) {
500*61046927SAndroid Build Coastguard Worker __atomic_store_n(&r->state, RING_BUFFER_SYNC_PRODUCER_IDLE, __ATOMIC_SEQ_CST);
501*61046927SAndroid Build Coastguard Worker }
502*61046927SAndroid Build Coastguard Worker
ring_buffer_producer_acquire(struct ring_buffer * r)503*61046927SAndroid Build Coastguard Worker bool ring_buffer_producer_acquire(struct ring_buffer* r) {
504*61046927SAndroid Build Coastguard Worker uint32_t expected_idle = RING_BUFFER_SYNC_PRODUCER_IDLE;
505*61046927SAndroid Build Coastguard Worker bool success =
506*61046927SAndroid Build Coastguard Worker __atomic_compare_exchange_n(&r->state, &expected_idle, RING_BUFFER_SYNC_PRODUCER_ACTIVE,
507*61046927SAndroid Build Coastguard Worker false /* strong */, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
508*61046927SAndroid Build Coastguard Worker return success;
509*61046927SAndroid Build Coastguard Worker }
510*61046927SAndroid Build Coastguard Worker
ring_buffer_producer_acquire_from_hangup(struct ring_buffer * r)511*61046927SAndroid Build Coastguard Worker bool ring_buffer_producer_acquire_from_hangup(struct ring_buffer* r) {
512*61046927SAndroid Build Coastguard Worker uint32_t expected_hangup = RING_BUFFER_SYNC_CONSUMER_HUNG_UP;
513*61046927SAndroid Build Coastguard Worker bool success =
514*61046927SAndroid Build Coastguard Worker __atomic_compare_exchange_n(&r->state, &expected_hangup, RING_BUFFER_SYNC_PRODUCER_ACTIVE,
515*61046927SAndroid Build Coastguard Worker false /* strong */, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
516*61046927SAndroid Build Coastguard Worker return success;
517*61046927SAndroid Build Coastguard Worker }
518*61046927SAndroid Build Coastguard Worker
ring_buffer_producer_wait_hangup(struct ring_buffer * r)519*61046927SAndroid Build Coastguard Worker void ring_buffer_producer_wait_hangup(struct ring_buffer* r) {
520*61046927SAndroid Build Coastguard Worker while (__atomic_load_n(&r->state, __ATOMIC_SEQ_CST) != RING_BUFFER_SYNC_CONSUMER_HUNG_UP) {
521*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
522*61046927SAndroid Build Coastguard Worker }
523*61046927SAndroid Build Coastguard Worker }
524*61046927SAndroid Build Coastguard Worker
ring_buffer_producer_idle(struct ring_buffer * r)525*61046927SAndroid Build Coastguard Worker void ring_buffer_producer_idle(struct ring_buffer* r) {
526*61046927SAndroid Build Coastguard Worker __atomic_store_n(&r->state, RING_BUFFER_SYNC_PRODUCER_IDLE, __ATOMIC_SEQ_CST);
527*61046927SAndroid Build Coastguard Worker }
528*61046927SAndroid Build Coastguard Worker
ring_buffer_consumer_hangup(struct ring_buffer * r)529*61046927SAndroid Build Coastguard Worker bool ring_buffer_consumer_hangup(struct ring_buffer* r) {
530*61046927SAndroid Build Coastguard Worker uint32_t expected_idle = RING_BUFFER_SYNC_PRODUCER_IDLE;
531*61046927SAndroid Build Coastguard Worker bool success =
532*61046927SAndroid Build Coastguard Worker __atomic_compare_exchange_n(&r->state, &expected_idle, RING_BUFFER_SYNC_CONSUMER_HANGING_UP,
533*61046927SAndroid Build Coastguard Worker false /* strong */, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
534*61046927SAndroid Build Coastguard Worker return success;
535*61046927SAndroid Build Coastguard Worker }
536*61046927SAndroid Build Coastguard Worker
ring_buffer_consumer_wait_producer_idle(struct ring_buffer * r)537*61046927SAndroid Build Coastguard Worker void ring_buffer_consumer_wait_producer_idle(struct ring_buffer* r) {
538*61046927SAndroid Build Coastguard Worker while (__atomic_load_n(&r->state, __ATOMIC_SEQ_CST) != RING_BUFFER_SYNC_PRODUCER_IDLE) {
539*61046927SAndroid Build Coastguard Worker ring_buffer_yield();
540*61046927SAndroid Build Coastguard Worker }
541*61046927SAndroid Build Coastguard Worker }
542*61046927SAndroid Build Coastguard Worker
ring_buffer_consumer_hung_up(struct ring_buffer * r)543*61046927SAndroid Build Coastguard Worker void ring_buffer_consumer_hung_up(struct ring_buffer* r) {
544*61046927SAndroid Build Coastguard Worker __atomic_store_n(&r->state, RING_BUFFER_SYNC_CONSUMER_HUNG_UP, __ATOMIC_SEQ_CST);
545*61046927SAndroid Build Coastguard Worker }
546