Fix ringbuffer thread safety on ARM. Fix #715 #388 (#886)
[jack2.git] / common / ringbuffer.c
bloba44fc7870f88b24fc65bc8276ccf486cafacffed
1 /*
2 Copyright (C) 2000 Paul Davis
3 Copyright (C) 2003 Rohan Drape
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 ISO/POSIX C version of Paul Davis's lock free ringbuffer C++ code.
20 This is safe for the case of one read thread and one write thread.
23 #include <stdlib.h>
24 #include <string.h>
25 #ifdef USE_MLOCK
26 #include <sys/mman.h>
27 #endif /* USE_MLOCK */
28 #include "JackCompilerDeps.h"
30 /* Portable definitions for acquire and release fences */
31 #if defined(_MSC_VER)
32 #if defined(_M_AMD64) || defined(_M_IX86) || defined(_M_X64)
33 /* Only compiler fences are needed on x86. In fact, GCC
34 * will generate no instructions for acq/rel fences on
35 * x86 */
36 #include <intrin.h>
37 #define JACK_ACQ_FENCE() _ReadBarrier()
38 #define JACK_REL_FENCE() _WriteBarrier()
39 #else
40 /* Use full memory fence for non-x86 systems with msvc */
41 #include <windows.h>
42 #define JACK_ACQ_FENCE() MemoryBarrier()
43 #define JACK_REL_FENCE() MemoryBarrier()
44 #endif
45 #elif defined(__GNUC__)
46 #ifdef __ATOMIC_ACQUIRE
47 #define JACK_ACQ_FENCE() __atomic_thread_fence(__ATOMIC_ACQUIRE)
48 #define JACK_REL_FENCE() __atomic_thread_fence(__ATOMIC_RELEASE)
49 #else
50 /* Fallback to the legacy __sync builtin (full memory fence) */
51 #define JACK_ACQ_FENCE() __sync_synchronize()
52 #define JACK_REL_FENCE() __sync_synchronize()
53 #endif
54 #else
55 #define JACK_ACQ_FENCE()
56 #define JACK_REL_FENCE()
57 #endif
59 typedef struct {
60 char *buf;
61 size_t len;
63 jack_ringbuffer_data_t ;
65 typedef struct {
66 char *buf;
67 size_t write_ptr;
68 size_t read_ptr;
69 size_t size;
70 size_t size_mask;
71 int mlocked;
73 jack_ringbuffer_t ;
75 LIB_EXPORT jack_ringbuffer_t *jack_ringbuffer_create(size_t sz);
76 LIB_EXPORT void jack_ringbuffer_free(jack_ringbuffer_t *rb);
77 LIB_EXPORT void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb,
78 jack_ringbuffer_data_t *vec);
79 LIB_EXPORT void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb,
80 jack_ringbuffer_data_t *vec);
81 LIB_EXPORT size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt);
82 LIB_EXPORT size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt);
83 LIB_EXPORT void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt);
84 LIB_EXPORT size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb);
85 LIB_EXPORT int jack_ringbuffer_mlock(jack_ringbuffer_t *rb);
86 LIB_EXPORT void jack_ringbuffer_reset(jack_ringbuffer_t *rb);
87 LIB_EXPORT void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz);
88 LIB_EXPORT size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src,
89 size_t cnt);
90 void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt);
91 size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);
93 /* Create a new ringbuffer to hold at least `sz' bytes of data. The
94 actual buffer size is rounded up to the next power of two. */
96 LIB_EXPORT jack_ringbuffer_t *
97 jack_ringbuffer_create (size_t sz)
99 int power_of_two;
100 jack_ringbuffer_t *rb;
102 if ((rb = (jack_ringbuffer_t *) malloc (sizeof (jack_ringbuffer_t))) == NULL) {
103 return NULL;
106 for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++);
108 rb->size = 1 << power_of_two;
109 rb->size_mask = rb->size;
110 rb->size_mask -= 1;
111 rb->write_ptr = 0;
112 rb->read_ptr = 0;
113 if ((rb->buf = (char *) malloc (rb->size)) == NULL) {
114 free (rb);
115 return NULL;
117 rb->mlocked = 0;
119 return rb;
122 /* Free all data associated with the ringbuffer `rb'. */
124 LIB_EXPORT void
125 jack_ringbuffer_free (jack_ringbuffer_t * rb)
127 #ifdef USE_MLOCK
128 if (rb->mlocked) {
129 munlock (rb->buf, rb->size);
131 #endif /* USE_MLOCK */
132 free (rb->buf);
133 free (rb);
136 /* Lock the data block of `rb' using the system call 'mlock'. */
138 LIB_EXPORT int
139 jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
141 #ifdef USE_MLOCK
142 if (mlock (rb->buf, rb->size)) {
143 return -1;
145 #endif /* USE_MLOCK */
146 rb->mlocked = 1;
147 return 0;
150 /* Reset the read and write pointers to zero. This is not thread
151 safe. */
153 LIB_EXPORT void
154 jack_ringbuffer_reset (jack_ringbuffer_t * rb)
156 rb->read_ptr = 0;
157 rb->write_ptr = 0;
158 memset(rb->buf, 0, rb->size);
161 /* Reset the read and write pointers to zero. This is not thread
162 safe. */
164 LIB_EXPORT void
165 jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz)
167 rb->size = sz;
168 rb->size_mask = rb->size;
169 rb->size_mask -= 1;
170 rb->read_ptr = 0;
171 rb->write_ptr = 0;
174 /* Return the number of bytes available for reading. This is the
175 number of bytes in front of the read pointer and behind the write
176 pointer. */
178 LIB_EXPORT size_t
179 jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)
181 size_t w, r;
183 w = rb->write_ptr;
184 JACK_ACQ_FENCE();
185 r = rb->read_ptr;
187 return (w - r) & rb->size_mask;
190 /* Return the number of bytes available for writing. This is the
191 number of bytes in front of the write pointer and behind the read
192 pointer. */
194 LIB_EXPORT size_t
195 jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
197 size_t w, r;
199 w = rb->write_ptr;
200 r = rb->read_ptr;
201 JACK_ACQ_FENCE();
203 return (r - w - 1) & rb->size_mask;
206 /* The copying data reader. Copy at most `cnt' bytes from `rb' to
207 `dest'. Returns the actual number of bytes copied. */
209 LIB_EXPORT size_t
210 jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)
212 size_t free_cnt;
213 size_t cnt2;
214 size_t to_read;
215 size_t n1, n2;
217 if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
218 return 0;
221 to_read = cnt > free_cnt ? free_cnt : cnt;
223 /* note: relaxed load here, rb->read_ptr cannot be
224 * modified from writing thread */
225 cnt2 = rb->read_ptr + to_read;
227 if (cnt2 > rb->size) {
228 n1 = rb->size - rb->read_ptr;
229 n2 = cnt2 & rb->size_mask;
230 } else {
231 n1 = to_read;
232 n2 = 0;
235 memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
236 JACK_REL_FENCE(); /* ensure pointer increment happens after copy */
237 rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
239 if (n2) {
240 memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
241 JACK_REL_FENCE(); /* ensure pointer increment happens after copy */
242 rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
245 return to_read;
248 /* The copying data reader w/o read pointer advance. Copy at most
249 `cnt' bytes from `rb' to `dest'. Returns the actual number of bytes
250 copied. */
252 LIB_EXPORT size_t
253 jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
255 size_t free_cnt;
256 size_t cnt2;
257 size_t to_read;
258 size_t n1, n2;
259 size_t tmp_read_ptr;
261 tmp_read_ptr = rb->read_ptr;
263 if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
264 return 0;
267 to_read = cnt > free_cnt ? free_cnt : cnt;
269 cnt2 = tmp_read_ptr + to_read;
271 if (cnt2 > rb->size) {
272 n1 = rb->size - tmp_read_ptr;
273 n2 = cnt2 & rb->size_mask;
274 } else {
275 n1 = to_read;
276 n2 = 0;
279 memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
280 tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
282 if (n2) {
283 memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
286 return to_read;
289 /* The copying data writer. Copy at most `cnt' bytes to `rb' from
290 `src'. Returns the actual number of bytes copied. */
292 LIB_EXPORT size_t
293 jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
295 size_t free_cnt;
296 size_t cnt2;
297 size_t to_write;
298 size_t n1, n2;
300 if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
301 return 0;
304 to_write = cnt > free_cnt ? free_cnt : cnt;
306 /* note: relaxed load here, rb->write_ptr cannot be
307 * modified from reading thread */
308 cnt2 = rb->write_ptr + to_write;
310 if (cnt2 > rb->size) {
311 n1 = rb->size - rb->write_ptr;
312 n2 = cnt2 & rb->size_mask;
313 } else {
314 n1 = to_write;
315 n2 = 0;
318 memcpy (&(rb->buf[rb->write_ptr]), src, n1);
319 JACK_REL_FENCE(); /* ensure pointer increment happens after copy */
320 rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
322 if (n2) {
323 memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
324 JACK_REL_FENCE(); /* ensure pointer increment happens after copy */
325 rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
328 return to_write;
331 /* Advance the read pointer `cnt' places. */
333 LIB_EXPORT void
334 jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
336 size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
337 JACK_REL_FENCE(); /* ensure pointer increment happens after copy (by user) */
338 rb->read_ptr = tmp;
341 /* Advance the write pointer `cnt' places. */
343 LIB_EXPORT void
344 jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
346 size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
347 JACK_REL_FENCE(); /* ensure pointer increment happens after copy (by user) */
348 rb->write_ptr = tmp;
351 /* The non-copying data reader. `vec' is an array of two places. Set
352 the values at `vec' to hold the current readable data at `rb'. If
353 the readable data is in one segment the second segment has zero
354 length. */
356 LIB_EXPORT void
357 jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,
358 jack_ringbuffer_data_t * vec)
360 size_t free_cnt;
361 size_t cnt2;
362 size_t r;
364 r = rb->read_ptr;
365 free_cnt = jack_ringbuffer_read_space(rb);
366 cnt2 = r + free_cnt;
368 if (cnt2 > rb->size) {
370 /* Two part vector: the rest of the buffer after the current write
371 ptr, plus some from the start of the buffer. */
373 vec[0].buf = &(rb->buf[r]);
374 vec[0].len = rb->size - r;
375 vec[1].buf = rb->buf;
376 vec[1].len = cnt2 & rb->size_mask;
378 } else {
380 /* Single part vector: just the rest of the buffer */
382 vec[0].buf = &(rb->buf[r]);
383 vec[0].len = free_cnt;
384 vec[1].len = 0;
388 /* The non-copying data writer. `vec' is an array of two places. Set
389 the values at `vec' to hold the current writeable data at `rb'. If
390 the writeable data is in one segment the second segment has zero
391 length. */
393 LIB_EXPORT void
394 jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb,
395 jack_ringbuffer_data_t * vec)
397 size_t free_cnt;
398 size_t cnt2;
399 size_t w;
401 w = rb->write_ptr;
402 free_cnt = jack_ringbuffer_write_space(rb);
403 cnt2 = w + free_cnt;
405 if (cnt2 > rb->size) {
407 /* Two part vector: the rest of the buffer after the current write
408 ptr, plus some from the start of the buffer. */
410 vec[0].buf = &(rb->buf[w]);
411 vec[0].len = rb->size - w;
412 vec[1].buf = rb->buf;
413 vec[1].len = cnt2 & rb->size_mask;
414 } else {
415 vec[0].buf = &(rb->buf[w]);
416 vec[0].len = free_cnt;
417 vec[1].len = 0;