|
|
@@ -27,6 +27,35 @@ |
|
|
|
#endif /* USE_MLOCK */ |
|
|
|
#include "JackCompilerDeps.h" |
|
|
|
|
|
|
|
/* Portable definitions for acquire and release fences */ |
|
|
|
#if defined(_MSC_VER) |
|
|
|
#if defined(_M_AMD64) || defined(_M_IX86) || defined(_M_X64) |
|
|
|
/* Only compiler fences are needed on x86. In fact, GCC |
|
|
|
* will generate no instructions for acq/rel fences on |
|
|
|
* x86 */ |
|
|
|
#include <intrin.h> |
|
|
|
#define JACK_ACQ_FENCE() _ReadBarrier() |
|
|
|
#define JACK_REL_FENCE() _WriteBarrier() |
|
|
|
#else |
|
|
|
/* Use full memory fence for non-x86 systems with msvc */ |
|
|
|
#include <windows.h> |
|
|
|
#define JACK_ACQ_FENCE() MemoryBarrier() |
|
|
|
#define JACK_REL_FENCE() MemoryBarrier() |
|
|
|
#endif |
|
|
|
#elif defined(__GNUC__) |
|
|
|
#ifdef __ATOMIC_ACQUIRE |
|
|
|
#define JACK_ACQ_FENCE() __atomic_thread_fence(__ATOMIC_ACQUIRE) |
|
|
|
#define JACK_REL_FENCE() __atomic_thread_fence(__ATOMIC_RELEASE) |
|
|
|
#else |
|
|
|
/* Fallback to the legacy __sync builtin (full memory fence) */ |
|
|
|
#define JACK_ACQ_FENCE() __sync_synchronize() |
|
|
|
#define JACK_REL_FENCE() __sync_synchronize() |
|
|
|
#endif |
|
|
|
#else |
|
|
|
#define JACK_ACQ_FENCE() |
|
|
|
#define JACK_REL_FENCE() |
|
|
|
#endif |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
char *buf; |
|
|
|
size_t len; |
|
|
@@ -35,8 +64,8 @@ jack_ringbuffer_data_t ; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
char *buf; |
|
|
|
volatile size_t write_ptr; |
|
|
|
volatile size_t read_ptr; |
|
|
|
size_t write_ptr; |
|
|
|
size_t read_ptr; |
|
|
|
size_t size; |
|
|
|
size_t size_mask; |
|
|
|
int mlocked; |
|
|
@@ -126,7 +155,7 @@ jack_ringbuffer_reset (jack_ringbuffer_t * rb) |
|
|
|
{ |
|
|
|
rb->read_ptr = 0; |
|
|
|
rb->write_ptr = 0; |
|
|
|
memset(rb->buf, 0, rb->size); |
|
|
|
memset(rb->buf, 0, rb->size); |
|
|
|
} |
|
|
|
|
|
|
|
/* Reset the read and write pointers to zero. This is not thread |
|
|
@@ -152,13 +181,10 @@ jack_ringbuffer_read_space (const jack_ringbuffer_t * rb) |
|
|
|
size_t w, r; |
|
|
|
|
|
|
|
w = rb->write_ptr; |
|
|
|
JACK_ACQ_FENCE(); |
|
|
|
r = rb->read_ptr; |
|
|
|
|
|
|
|
if (w > r) { |
|
|
|
return w - r; |
|
|
|
} else { |
|
|
|
return (w - r + rb->size) & rb->size_mask; |
|
|
|
} |
|
|
|
return (w - r) & rb->size_mask; |
|
|
|
} |
|
|
|
|
|
|
|
/* Return the number of bytes available for writing. This is the |
|
|
@@ -172,14 +198,9 @@ jack_ringbuffer_write_space (const jack_ringbuffer_t * rb) |
|
|
|
|
|
|
|
w = rb->write_ptr; |
|
|
|
r = rb->read_ptr; |
|
|
|
JACK_ACQ_FENCE(); |
|
|
|
|
|
|
|
if (w > r) { |
|
|
|
return ((r - w + rb->size) & rb->size_mask) - 1; |
|
|
|
} else if (w < r) { |
|
|
|
return (r - w) - 1; |
|
|
|
} else { |
|
|
|
return rb->size - 1; |
|
|
|
} |
|
|
|
return (r - w - 1) & rb->size_mask; |
|
|
|
} |
|
|
|
|
|
|
|
/* The copying data reader. Copy at most `cnt' bytes from `rb' to |
|
|
@@ -199,6 +220,8 @@ jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt) |
|
|
|
|
|
|
|
to_read = cnt > free_cnt ? free_cnt : cnt; |
|
|
|
|
|
|
|
/* note: relaxed load here, rb->read_ptr cannot be |
|
|
|
* modified from writing thread */ |
|
|
|
cnt2 = rb->read_ptr + to_read; |
|
|
|
|
|
|
|
if (cnt2 > rb->size) { |
|
|
@@ -210,10 +233,12 @@ jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt) |
|
|
|
} |
|
|
|
|
|
|
|
memcpy (dest, &(rb->buf[rb->read_ptr]), n1); |
|
|
|
JACK_REL_FENCE(); /* ensure pointer increment happens after copy */ |
|
|
|
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask; |
|
|
|
|
|
|
|
if (n2) { |
|
|
|
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2); |
|
|
|
JACK_REL_FENCE(); /* ensure pointer increment happens after copy */ |
|
|
|
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask; |
|
|
|
} |
|
|
|
|
|
|
@@ -278,6 +303,8 @@ jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt) |
|
|
|
|
|
|
|
to_write = cnt > free_cnt ? free_cnt : cnt; |
|
|
|
|
|
|
|
/* note: relaxed load here, rb->write_ptr cannot be |
|
|
|
* modified from reading thread */ |
|
|
|
cnt2 = rb->write_ptr + to_write; |
|
|
|
|
|
|
|
if (cnt2 > rb->size) { |
|
|
@@ -289,10 +316,12 @@ jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt) |
|
|
|
} |
|
|
|
|
|
|
|
memcpy (&(rb->buf[rb->write_ptr]), src, n1); |
|
|
|
JACK_REL_FENCE(); /* ensure pointer increment happens after copy */ |
|
|
|
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask; |
|
|
|
|
|
|
|
if (n2) { |
|
|
|
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2); |
|
|
|
JACK_REL_FENCE(); /* ensure pointer increment happens after copy */ |
|
|
|
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask; |
|
|
|
} |
|
|
|
|
|
|
@@ -305,6 +334,7 @@ LIB_EXPORT void |
|
|
|
jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt) |
|
|
|
{ |
|
|
|
size_t tmp = (rb->read_ptr + cnt) & rb->size_mask; |
|
|
|
JACK_REL_FENCE(); /* ensure pointer increment happens after copy (by user) */ |
|
|
|
rb->read_ptr = tmp; |
|
|
|
} |
|
|
|
|
|
|
@@ -314,6 +344,7 @@ LIB_EXPORT void |
|
|
|
jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt) |
|
|
|
{ |
|
|
|
size_t tmp = (rb->write_ptr + cnt) & rb->size_mask; |
|
|
|
JACK_REL_FENCE(); /* ensure pointer increment happens after copy (by user) */ |
|
|
|
rb->write_ptr = tmp; |
|
|
|
} |
|
|
|
|
|
|
@@ -328,17 +359,10 @@ jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb, |
|
|
|
{ |
|
|
|
size_t free_cnt; |
|
|
|
size_t cnt2; |
|
|
|
size_t w, r; |
|
|
|
size_t r; |
|
|
|
|
|
|
|
w = rb->write_ptr; |
|
|
|
r = rb->read_ptr; |
|
|
|
|
|
|
|
if (w > r) { |
|
|
|
free_cnt = w - r; |
|
|
|
} else { |
|
|
|
free_cnt = (w - r + rb->size) & rb->size_mask; |
|
|
|
} |
|
|
|
|
|
|
|
free_cnt = jack_ringbuffer_read_space(rb); |
|
|
|
cnt2 = r + free_cnt; |
|
|
|
|
|
|
|
if (cnt2 > rb->size) { |
|
|
@@ -372,19 +396,10 @@ jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb, |
|
|
|
{ |
|
|
|
size_t free_cnt; |
|
|
|
size_t cnt2; |
|
|
|
size_t w, r; |
|
|
|
size_t w; |
|
|
|
|
|
|
|
w = rb->write_ptr; |
|
|
|
r = rb->read_ptr; |
|
|
|
|
|
|
|
if (w > r) { |
|
|
|
free_cnt = ((r - w + rb->size) & rb->size_mask) - 1; |
|
|
|
} else if (w < r) { |
|
|
|
free_cnt = (r - w) - 1; |
|
|
|
} else { |
|
|
|
free_cnt = rb->size - 1; |
|
|
|
} |
|
|
|
|
|
|
|
free_cnt = jack_ringbuffer_write_space(rb); |
|
|
|
cnt2 = w + free_cnt; |
|
|
|
|
|
|
|
if (cnt2 > rb->size) { |
|
|
|