Just proposed one of my projects for inclusion: https://github.com/djcapelis/atomic-ring Lock-free Single Producer, Single Consumer (SPSC) queue. The dependencies include C11 and that's it. No POSIX required, should work on any arch you can find a C11 compiler for.
I had some thoughts, which I'm offering in hopes of clarifying my understanding, and possibly helping to improve your software in the process.
I don't see any correctness problems in your code, but I do see what look like several opportunities for optimization. Though please take these with a slight grain of salt, as I am still learning the C11 atomics.
Your aring_give() ends with a release barrier and your aring_take() begins with an acquire barrier. That makes sense to me, as a way of ensuring the sequencing of the reads/writes to aring->rb and to item. However I don't see why aring_give() needs to begin with an acquire and aring_take() needs to end with a release. I think both of these could be changed to memory_order_relaxed with no change in correctness.
But I think we can go a step further actually. Your atomic_fetch_add_explicit() and atomic_fetch_sub_explicit() operations operate on a shared aring->items member. Both the reader and writer write to this variable, which requires expensive locked operations and which will degrade under contention. I don't think this is actually necessary.
Instead you could eliminate aring->items completely and simply compute it based on aring->head and aring->tail. Only the writer writes to head and only the reader writes to tail, so you could use just atomic_load_explicit()/atomic_store_explicit() with memory_order_relaxed on these variables to read and write them. Then calculate the number of items present by comparing them. This could make the overall queue significantly more efficient.
I'd be curious to hear your thoughts on this.