summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/al/atomic.h78
-rw-r--r--include/al/random.h17
-rw-r--r--src/ring_buffer.c44
-rw-r--r--tests/ring_buffer.c6
4 files changed, 78 insertions, 67 deletions
diff --git a/include/al/atomic.h b/include/al/atomic.h
index 1b733ad..7f8a087 100644
--- a/include/al/atomic.h
+++ b/include/al/atomic.h
@@ -12,44 +12,54 @@
#define AL_ATOMIC_ACQ_REL c89atomic_memory_order_acq_rel
#define AL_ATOMIC_SEQ_CST c89atomic_memory_order_seq_cst
-#define al_atomic_ptr_load(p, order) c89atomic_load_explicit_ptr(((volatile void **)p), order)
-#define al_atomic_ptr_store(p, v, order) c89atomic_store_explicit_ptr(((volatile void **)p), (void *)v, order)
+#define atomic(T) _al_atomic_##T
-#define atomic_size_t c89atomic_uint64
-#define al_atomic_size_t_load(p, order) ((size_t)c89atomic_load_explicit_64(p, order))
-#define al_atomic_size_t_store(p, v, order) c89atomic_store_explicit_64(p, ((size_t)v), order)
+#define al_atomic_load(T) _al_atomic_load_##T
+#define al_atomic_store(T) _al_atomic_store_##T
+#define al_atomic_add(T) _al_atomic_add_##T
+#define al_atomic_sub(T) _al_atomic_sub_##T
-#define atomic_s64 c89atomic_int64
-#define al_atomic_s64_load(p, order) ((s64)c89atomic_load_explicit_i64(p, order))
-#define al_atomic_s64_store(p, v, order) c89atomic_store_explicit_i64(p, ((s64)v), order)
+// Special case for pointers.
+#define _al_atomic_load_void(p, order) c89atomic_load_explicit_ptr(((volatile void **)p), order)
+#define _al_atomic_store_void(p, v, order) c89atomic_store_explicit_ptr(((volatile void **)p), (void *)v, order)
-#define atomic_u64 c89atomic_uint64
-#define al_atomic_u64_load(p, order) ((u64)c89atomic_load_explicit_64(p, order))
-#define al_atomic_u64_store(p, v, order) c89atomic_store_explicit_64(p, ((u64)v), order)
-#define al_atomic_u64_add(p, v, order) c89atomic_fetch_add_explicit_64(p, ((u64)v), order)
-#define al_atomic_u64_sub(p, v, order) c89atomic_fetch_sub_explicit_64(p, ((u64)v), order)
+// c89atomic compat.
+typedef f64 c89atomic_f64;
+typedef f32 c89atomic_f32;
-#define atomic_f64 f64
-#define al_atomic_f64_load(p, order) ((f64)c89atomic_load_explicit_f64(p, order))
-#define al_atomic_f64_store(p, v, order) c89atomic_store_explicit_f64(p, ((f64)v), order)
+#define AL_ATOMIC_DEFINE(T, C, S) \
+ typedef c89atomic_##C atomic(T); \
+ static inline T al_atomic_load(T)(atomic(T) *a, int order) \
+ { \
+ return c89atomic_load_explicit_##S(a, order); \
+ } \
+ static inline void al_atomic_store(T)(atomic(T) *a, T value, int order) \
+ { \
+ c89atomic_store_explicit_##S(a, value, order); \
+ } \
+ static inline T al_atomic_add(T)(atomic(T) *a, T value, int order) \
+ { \
+ return c89atomic_fetch_add_explicit_##S(a, value, order); \
+ } \
+ static inline T al_atomic_sub(T)(atomic(T) *a, T value, int order) \
+ { \
+ return c89atomic_fetch_sub_explicit_##S(a, value, order); \
+ }
-#define atomic_s32 c89atomic_int32
-#define al_atomic_s32_load(p, order) ((s32)c89atomic_load_explicit_i32(p, order))
-#define al_atomic_s32_store(p, v, order) c89atomic_store_explicit_i32(p, ((s32)v), order)
-#define al_atomic_s32_add(p, v, order) c89atomic_fetch_add_explicit_i32(p, ((s32)v), order)
-#define al_atomic_s32_sub(p, v, order) c89atomic_fetch_sub_explicit_i32(p, ((s32)v), order)
-
-#define atomic_u16 c89atomic_uint16
-#define al_atomic_u16_load(p, order) c89atomic_load_explicit_16(p, order)
-#define al_atomic_u16_store(p, v, order) c89atomic_store_explicit_16(p, ((u16)v), order)
-#define al_atomic_u16_add(p, v, order) c89atomic_fetch_add_explicit_16(p, ((u16)v), order)
-
-#define atomic_u8 c89atomic_uint8
-#define al_atomic_u8_load(p, order) c89atomic_load_explicit_8(p, order)
-#define al_atomic_u8_store(p, v, order) c89atomic_store_explicit_8(p, ((u8)v), order)
-
-#define atomic_bool c89atomic_uint8
-#define al_atomic_bool_load(p, order) c89atomic_load_explicit_8(p, order)
-#define al_atomic_bool_store(p, v, order) c89atomic_store_explicit_8(p, ((bool)v), order)
+#if defined C89ATOMIC_64BIT
+AL_ATOMIC_DEFINE(size_t, uint64, 64)
+#elif defined C89ATOMIC_32BIT
+AL_ATOMIC_DEFINE(size_t, uint32, 32)
+#endif
+AL_ATOMIC_DEFINE(u64, uint64, 64);
+AL_ATOMIC_DEFINE(s64, int64, i64);
+AL_ATOMIC_DEFINE(u32, uint32, 32);
+AL_ATOMIC_DEFINE(s32, int32, i32);
+AL_ATOMIC_DEFINE(u16, uint16, 16);
+AL_ATOMIC_DEFINE(s16, int16, i16);
+AL_ATOMIC_DEFINE(u8, uint8, 8);
+AL_ATOMIC_DEFINE(s8, int8, i8);
+AL_ATOMIC_DEFINE(f64, f64, f64);
+AL_ATOMIC_DEFINE(f32, f32, f32);
#endif // _AL_ATOMIC_H
diff --git a/include/al/random.h b/include/al/random.h
index 40c8654..9d27c18 100644
--- a/include/al/random.h
+++ b/include/al/random.h
@@ -18,17 +18,18 @@ static s32 al_rand(void)
return rand();
}
-static atomic_u16 _al_rand_value = 1;
+// Each file that includes this header will have a separate counter.
+static atomic(u16) _al_inc_value = 1;
-// Temporary, can guarantee no collisions for the current use case. This functions per-file,
-// so each file this is included in will have a seperate counter.
-static u16 al_rand_u16(void)
+// This is apart of random because currently al_inc_u16() is used as a substitute
+// for proper random ID generation.
+static u16 al_inc_u16(void)
{
- u16 ret = al_atomic_u16_add(&_al_rand_value, 1, AL_ATOMIC_RELAXED);
- if (ret == UINT16_MAX) {
- al_atomic_u16_store(&_al_rand_value, 1, AL_ATOMIC_RELAXED);
+ if (al_atomic_load(u16)(&_al_inc_value, AL_ATOMIC_ACQUIRE) == UINT16_MAX) {
+ al_atomic_store(u16)(&_al_inc_value, 1, AL_ATOMIC_RELEASE);
+ return 1;
}
- return ret;
+ return al_atomic_add(u16)(&_al_inc_value, 1, AL_ATOMIC_RELEASE);
}
AL_UNUSED_FUNCTION_POP
diff --git a/src/ring_buffer.c b/src/ring_buffer.c
index c985d86..adb22ad 100644
--- a/src/ring_buffer.c
+++ b/src/ring_buffer.c
@@ -23,20 +23,20 @@ static inline void add(struct al_ring_buffer *buf, u8 **v, u8 *ptr, size_t n)
ptr += n;
al_assert(ptr <= buf->end);
if (ptr == buf->end) ptr = buf->start;
- al_atomic_ptr_store(v, ptr, AL_ATOMIC_RELEASE);
+ al_atomic_store(void)(v, ptr, AL_ATOMIC_RELEASE);
}
size_t al_ring_buffer_space(struct al_ring_buffer *buf)
{
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_RELAXED);
- u8 *rp = previous(buf, (u8 *)al_atomic_ptr_load(&buf->read, AL_ATOMIC_RELAXED));
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
+ u8 *rp = previous(buf, (u8 *)al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED));
return (wp <= rp) ? rp - wp : (buf->end - wp) + (rp - buf->start);
}
u8 *al_ring_buffer_write_chunk(struct al_ring_buffer *buf, size_t *size)
{
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_ACQUIRE);
- u8 *rp = previous(buf, al_atomic_ptr_load(&buf->read, AL_ATOMIC_RELAXED));
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_ACQUIRE);
+ u8 *rp = previous(buf, al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED));
*size = (wp <= rp ? rp : buf->end) - wp;
return wp;
}
@@ -48,15 +48,15 @@ void al_ring_buffer_append(struct al_ring_buffer *buf, u8 *ptr, size_t n)
size_t al_ring_buffer_occupied(struct al_ring_buffer *buf)
{
- u8 *rp = al_atomic_ptr_load(&buf->read, AL_ATOMIC_RELAXED);
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_RELAXED);
+ u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED);
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
return (rp <= wp) ? wp - rp : (buf->end - rp) + (wp - buf->start);
}
u8 *al_ring_buffer_read_chunk(struct al_ring_buffer *buf, size_t *size)
{
- u8 *rp = al_atomic_ptr_load(&buf->read, AL_ATOMIC_ACQUIRE);
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_RELAXED);
+ u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_ACQUIRE);
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
*size = (rp <= wp ? wp : buf->end) - rp;
return rp;
}
@@ -68,8 +68,8 @@ void al_ring_buffer_consume(struct al_ring_buffer *buf, u8 *ptr, size_t n)
size_t al_ring_buffer_write(struct al_ring_buffer *buf, u8 *data, size_t n)
{
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_ACQUIRE);
- u8 *rp = previous(buf, al_atomic_ptr_load(&buf->read, AL_ATOMIC_RELAXED));
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_ACQUIRE);
+ u8 *rp = previous(buf, al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED));
size_t size = AL_MIN((wp <= rp ? rp : buf->end) - wp, (ptrdiff_t)n);
@@ -83,15 +83,15 @@ size_t al_ring_buffer_write(struct al_ring_buffer *buf, u8 *data, size_t n)
size += wrap;
}
- al_atomic_ptr_store(&buf->write, wp, AL_ATOMIC_RELEASE);
+ al_atomic_store(void)(&buf->write, wp, AL_ATOMIC_RELEASE);
return size;
}
size_t al_ring_buffer_read(struct al_ring_buffer *buf, u8 *ptr, size_t n)
{
- u8 *rp = al_atomic_ptr_load(&buf->read, AL_ATOMIC_ACQUIRE);
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_RELAXED);
+ u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_ACQUIRE);
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
size_t size = AL_MIN((rp <= wp ? wp : buf->end) - rp, (ptrdiff_t)n);
@@ -105,15 +105,15 @@ size_t al_ring_buffer_read(struct al_ring_buffer *buf, u8 *ptr, size_t n)
size += wrap;
}
- al_atomic_ptr_store(&buf->read, rp, AL_ATOMIC_RELEASE);
+ al_atomic_store(void)(&buf->read, rp, AL_ATOMIC_RELEASE);
return size;
}
size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, size_t n)
{
- u8 *rp = al_atomic_ptr_load(&buf->read, AL_ATOMIC_RELAXED);
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_RELAXED);
+ u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_RELAXED);
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
ptrdiff_t size;
@@ -145,8 +145,8 @@ size_t al_ring_buffer_peek(struct al_ring_buffer *buf, u8 *ptr, size_t offset, s
size_t al_ring_buffer_discard(struct al_ring_buffer *buf, size_t n)
{
- u8 *rp = al_atomic_ptr_load(&buf->read, AL_ATOMIC_ACQUIRE);
- u8 *wp = al_atomic_ptr_load(&buf->write, AL_ATOMIC_RELAXED);
+ u8 *rp = al_atomic_load(void)(&buf->read, AL_ATOMIC_ACQUIRE);
+ u8 *wp = al_atomic_load(void)(&buf->write, AL_ATOMIC_RELAXED);
size_t discard = AL_MIN((rp <= wp ? wp : buf->end) - rp, (ptrdiff_t)n);
rp += discard;
@@ -157,7 +157,7 @@ size_t al_ring_buffer_discard(struct al_ring_buffer *buf, size_t n)
discard += wrap;
}
- al_atomic_ptr_store(&buf->read, rp, AL_ATOMIC_RELEASE);
+ al_atomic_store(void)(&buf->read, rp, AL_ATOMIC_RELEASE);
return discard;
}
@@ -165,6 +165,6 @@ size_t al_ring_buffer_discard(struct al_ring_buffer *buf, size_t n)
// Not thread-safe.
void al_ring_buffer_reset(struct al_ring_buffer *buf)
{
- al_atomic_ptr_store(&buf->read, buf->start, AL_ATOMIC_RELAXED);
- al_atomic_ptr_store(&buf->write, buf->start, AL_ATOMIC_RELAXED);
+ al_atomic_store(void)(&buf->read, buf->start, AL_ATOMIC_RELAXED);
+ al_atomic_store(void)(&buf->write, buf->start, AL_ATOMIC_RELAXED);
}
diff --git a/tests/ring_buffer.c b/tests/ring_buffer.c
index a8e26ef..30b583e 100644
--- a/tests/ring_buffer.c
+++ b/tests/ring_buffer.c
@@ -18,8 +18,8 @@ static bool ring_buffer_test_init(void)
AL_TEST_EQ(buf.start, buffer, ptr);
AL_TEST_EQ(buf.end, buffer + TEST_BUFFER_SIZE, ptr);
- AL_TEST_EQ(al_atomic_ptr_load(&buf.read, AL_ATOMIC_RELAXED), buffer, ptr);
- AL_TEST_EQ(al_atomic_ptr_load(&buf.write, AL_ATOMIC_RELAXED), buffer, ptr);
+ AL_TEST_EQ(al_atomic_load(void)(&buf.read, AL_ATOMIC_RELAXED), buffer, ptr);
+ AL_TEST_EQ(al_atomic_load(void)(&buf.write, AL_ATOMIC_RELAXED), buffer, ptr);
AL_TEST_END();
}
@@ -112,7 +112,7 @@ static bool ring_buffer_test_read_and_write(void)
AL_TEST_EQ(al_ring_buffer_write(&buf, buffer_half, sizeof(buffer_half)), sizeof(buffer_half), size_t);
AL_TEST_EQ(al_ring_buffer_occupied(&buf), TEST_BUFFER_SIZE - data_size, size_t);
- AL_TEST_LT(al_atomic_ptr_load(&buf.write, AL_ATOMIC_RELAXED), al_atomic_ptr_load(&buf.read, AL_ATOMIC_RELAXED), ptr);
+ AL_TEST_LT(al_atomic_load(void)(&buf.write, AL_ATOMIC_RELAXED), al_atomic_load(void)(&buf.read, AL_ATOMIC_RELAXED), ptr);
size_t space = al_ring_buffer_space(&buf);
AL_TEST_EQ(space, data_size - 1, size_t);