Index: uspace/app/rcutest/rcutest.c
===================================================================
--- uspace/app/rcutest/rcutest.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/app/rcutest/rcutest.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -35,5 +35,5 @@
  */
 
-#include <atomic.h>
+#include <stdatomic.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -618,6 +618,6 @@
 
 typedef struct {
-	atomic_t time;
-	atomic_t max_start_time_of_done_sync;
+	atomic_size_t time;
+	atomic_size_t max_start_time_of_done_sync;
 
 	size_t total_workers;
@@ -630,5 +630,5 @@
 	size_t upd_iters;
 
-	atomic_t seed;
+	atomic_size_t seed;
 	int failed;
 } seq_test_info_t;
@@ -651,6 +651,6 @@
 	rcu_register_fibril();
 
-	size_t seed = (size_t) atomic_preinc(&arg->seed);
-	bool first = (seed == 1);
+	size_t seed = atomic_fetch_add(&arg->seed, 1);
+	bool first = (seed == 0);
 
 	for (size_t k = 0; k < arg->read_iters; ++k) {
@@ -661,5 +661,5 @@
 
 		rcu_read_lock();
-		atomic_count_t start_time = atomic_preinc(&arg->time);
+		size_t start_time = atomic_fetch_add(&arg->time, 1);
 
 		/* Do some work. */
@@ -677,5 +677,5 @@
 		 * (but did not - since it already announced it completed).
 		 */
-		if (start_time <= atomic_get(&arg->max_start_time_of_done_sync)) {
+		if (start_time <= atomic_load(&arg->max_start_time_of_done_sync)) {
 			arg->failed = 1;
 		}
@@ -695,10 +695,10 @@
 
 	for (size_t k = 0; k < arg->upd_iters; ++k) {
-		atomic_count_t start_time = atomic_get(&arg->time);
+		size_t start_time = atomic_load(&arg->time);
 		rcu_synchronize();
 
 		/* This is prone to a race but if it happens it errs to the safe side.*/
-		if (atomic_get(&arg->max_start_time_of_done_sync) < start_time) {
-			atomic_set(&arg->max_start_time_of_done_sync, start_time);
+		if (atomic_load(&arg->max_start_time_of_done_sync) < start_time) {
+			atomic_store(&arg->max_start_time_of_done_sync, start_time);
 		}
 	}
@@ -716,6 +716,6 @@
 
 	seq_test_info_t info = {
-		.time = { 0 },
-		.max_start_time_of_done_sync = { 0 },
+		.time = 0,
+		.max_start_time_of_done_sync = 0,
 		.read_iters = 10 * 1000,
 		.upd_iters = 5 * 1000,
@@ -725,5 +725,5 @@
 		.done_cnt_mtx = FIBRIL_MUTEX_INITIALIZER(info.done_cnt_mtx),
 		.done_cnt_changed = FIBRIL_CONDVAR_INITIALIZER(info.done_cnt_changed),
-		.seed = { 0 },
+		.seed = 0,
 		.failed = 0,
 	};
Index: uspace/app/tester/float/float1.c
===================================================================
--- uspace/app/tester/float/float1.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/app/tester/float/float1.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -32,5 +32,5 @@
 #include <stdlib.h>
 #include <stddef.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <fibril.h>
 #include <fibril_synch.h>
@@ -45,5 +45,5 @@
 
 static FIBRIL_SEMAPHORE_INITIALIZE(threads_finished, 0);
-static atomic_t threads_fault;
+static atomic_int threads_fault;
 
 static errno_t e(void *data)
@@ -60,5 +60,5 @@
 
 		if ((uint32_t) (e * PRECISION) != E_10E8) {
-			atomic_inc(&threads_fault);
+			atomic_fetch_add(&threads_fault, 1);
 			break;
 		}
@@ -71,7 +71,7 @@
 const char *test_float1(void)
 {
-	atomic_count_t total = 0;
+	int total = 0;
 
-	atomic_set(&threads_fault, 0);
+	atomic_store(&threads_fault, 0);
 	fibril_test_spawn_runners(THREADS);
 
@@ -92,10 +92,10 @@
 	TPRINTF("\n");
 
-	for (unsigned int i = 0; i < total; i++) {
-		TPRINTF("Threads left: %" PRIua "\n", total - i);
+	for (int i = 0; i < total; i++) {
+		TPRINTF("Threads left: %d\n", total - i);
 		fibril_semaphore_down(&threads_finished);
 	}
 
-	if (atomic_get(&threads_fault) == 0)
+	if (atomic_load(&threads_fault) == 0)
 		return NULL;
 
Index: uspace/app/tester/thread/thread1.c
===================================================================
--- uspace/app/tester/thread/thread1.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/app/tester/thread/thread1.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -31,5 +31,5 @@
 #define DELAY    10
 
-#include <atomic.h>
+#include <stdatomic.h>
 #include <errno.h>
 #include <fibril.h>
@@ -40,5 +40,5 @@
 #include "../tester.h"
 
-static atomic_t finish;
+static atomic_bool finish;
 
 static FIBRIL_SEMAPHORE_INITIALIZE(threads_finished, 0);
@@ -48,5 +48,5 @@
 	fibril_detach(fibril_get_id());
 
-	while (atomic_get(&finish))
+	while (!atomic_load(&finish))
 		fibril_usleep(100000);
 
@@ -57,13 +57,12 @@
 const char *test_thread1(void)
 {
-	unsigned int i;
-	atomic_count_t total = 0;
+	int total = 0;
 
-	atomic_set(&finish, 1);
+	atomic_store(&finish, false);
 
 	fibril_test_spawn_runners(THREADS);
 
 	TPRINTF("Creating threads");
-	for (i = 0; i < THREADS; i++) {
+	for (int i = 0; i < THREADS; i++) {
 		fid_t f = fibril_create(threadtest, NULL);
 		if (!f) {
@@ -80,8 +79,7 @@
 	TPRINTF("\n");
 
-	atomic_set(&finish, 0);
-	for (i = 0; i < total; i++) {
-		TPRINTF("Threads left: %" PRIua "\n",
-		    total - i);
+	atomic_store(&finish, true);
+	for (int i = 0; i < total; i++) {
+		TPRINTF("Threads left: %d\n", total - i);
 		fibril_semaphore_down(&threads_finished);
 	}
Index: uspace/app/wavplay/main.c
===================================================================
--- uspace/app/wavplay/main.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/app/wavplay/main.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -35,5 +35,5 @@
 
 #include <assert.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <errno.h>
 #include <fibril_synch.h>
@@ -189,5 +189,5 @@
 typedef struct {
 	hound_context_t *ctx;
-	atomic_t *count;
+	atomic_int *count;
 	const char *file;
 } fib_play_t;
@@ -203,5 +203,5 @@
 	fib_play_t *p = arg;
 	const errno_t ret = hplay_ctx(p->ctx, p->file);
-	atomic_dec(p->count);
+	atomic_fetch_sub(p->count, 1);
 	free(arg);
 	return ret;
@@ -279,6 +279,5 @@
 	/* Init parallel playback variables */
 	hound_context_t *hound_ctx = NULL;
-	atomic_t playcount;
-	atomic_set(&playcount, 0);
+	atomic_int playcount = 0;
 
 	/* Init parallel playback context if necessary */
@@ -332,5 +331,5 @@
 				data->ctx = hound_ctx;
 				fid_t fid = fibril_create(play_wrapper, data);
-				atomic_inc(&playcount);
+				atomic_fetch_add(&playcount, 1);
 				fibril_add_ready(fid);
 			} else {
@@ -341,5 +340,5 @@
 
 	/* Wait for all fibrils to finish */
-	while (atomic_get(&playcount) > 0)
+	while (atomic_load(&playcount) > 0)
 		fibril_usleep(1000000);
 
Index: uspace/lib/c/arch/arm32/src/atomic.c
===================================================================
--- uspace/lib/c/arch/arm32/src/atomic.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/c/arch/arm32/src/atomic.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -81,4 +81,38 @@
 }
 
+unsigned short __atomic_fetch_add_2(volatile unsigned short *mem, unsigned short val, int model)
+{
+	(void) model;
+
+	unsigned short ret;
+
+	/*
+	 * The following instructions between labels 1 and 2 constitute a
+	 * Restartable Atomic Seqeunce. Should the sequence be non-atomic,
+	 * the kernel will restart it.
+	 */
+	asm volatile (
+	    "1:\n"
+	    "	adr %[ret], 1b\n"
+	    "	str %[ret], %[rp0]\n"
+	    "	adr %[ret], 2f\n"
+	    "	str %[ret], %[rp1]\n"
+	    "	ldrh %[ret], %[addr]\n"
+	    "	add %[ret], %[ret], %[imm]\n"
+	    "	strh %[ret], %[addr]\n"
+	    "2:\n"
+	    : [ret] "=&r" (ret),
+	      [rp0] "=m" (ras_page[0]),
+	      [rp1] "=m" (ras_page[1]),
+	      [addr] "+m" (*mem)
+	    : [imm] "r" (val)
+	);
+
+	ras_page[0] = 0;
+	ras_page[1] = 0xffffffff;
+
+	return ret - val;
+}
+
 unsigned __atomic_fetch_add_4(volatile unsigned *mem, unsigned val, int model)
 {
Index: uspace/lib/c/generic/private/futex.h
===================================================================
--- uspace/lib/c/generic/private/futex.h	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/c/generic/private/futex.h	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -37,5 +37,5 @@
 
 #include <assert.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <errno.h>
 #include <libc.h>
@@ -43,5 +43,5 @@
 
 typedef struct futex {
-	atomic_t val;
+	volatile atomic_int val;
 #ifdef CONFIG_DEBUG_FUTEX
 	void *owner;
@@ -53,5 +53,5 @@
 #ifdef CONFIG_DEBUG_FUTEX
 
-#define FUTEX_INITIALIZE(val) {{ (val) }, NULL }
+#define FUTEX_INITIALIZE(val) { (val) , NULL }
 #define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
 
@@ -73,5 +73,5 @@
 #else
 
-#define FUTEX_INITIALIZE(val) {{ (val) }}
+#define FUTEX_INITIALIZE(val) { (val) }
 #define FUTEX_INITIALIZER     FUTEX_INITIALIZE(1)
 
@@ -107,6 +107,8 @@
 	// TODO: Add tests for this.
 
-	if ((atomic_signed_t) atomic_predec(&futex->val) >= 0)
+	if (atomic_fetch_sub_explicit(&futex->val, 1, memory_order_acquire) > 0)
 		return EOK;
+
+	/* There wasn't any token. We must defer to the underlying semaphore. */
 
 	usec_t timeout;
@@ -129,5 +131,5 @@
 	}
 
-	return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) &futex->val.count, (sysarg_t) timeout);
+	return __SYSCALL2(SYS_FUTEX_SLEEP, (sysarg_t) futex, (sysarg_t) timeout);
 }
 
@@ -143,6 +145,6 @@
 static inline errno_t futex_up(futex_t *futex)
 {
-	if ((atomic_signed_t) atomic_postinc(&futex->val) < 0)
-		return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) &futex->val.count);
+	if (atomic_fetch_add_explicit(&futex->val, 1, memory_order_release) < 0)
+		return __SYSCALL1(SYS_FUTEX_WAKEUP, (sysarg_t) futex);
 
 	return EOK;
@@ -152,38 +154,4 @@
     const struct timespec *expires)
 {
-	if (expires && expires->tv_sec == 0 && expires->tv_nsec == 0) {
-		/* Nonblocking down. */
-
-		/*
-		 * Try good old CAS a few times.
-		 * Not too much though, we don't want to bloat the caller.
-		 */
-		for (int i = 0; i < 2; i++) {
-			atomic_signed_t old = atomic_get(&futex->val);
-			if (old <= 0)
-				return ETIMEOUT;
-
-			if (cas(&futex->val, old, old - 1))
-				return EOK;
-		}
-
-		// TODO: builtin atomics with relaxed ordering can make this
-		//       faster.
-
-		/*
-		 * If we don't succeed with CAS, we can't just return failure
-		 * because that would lead to spurious failures where
-		 * futex_down_timeout returns ETIMEOUT despite there being
-		 * available tokens. That could break some algorithms.
-		 * We also don't want to loop on CAS indefinitely, because
-		 * that would make the semaphore not wait-free, even when all
-		 * atomic operations and the underlying base semaphore are all
-		 * wait-free.
-		 * Instead, we fall back to regular down_timeout(), with
-		 * an already expired deadline. That way we delegate all these
-		 * concerns to the base semaphore.
-		 */
-	}
-
 	/*
 	 * This combination of a "composable" sleep followed by futex_up() on
@@ -208,6 +176,15 @@
 {
 	/*
-	 * down_timeout with an already expired deadline should behave like
-	 * trydown.
+	 * We can't just use CAS here.
+	 * If we don't succeed with CAS, we can't return failure
+	 * because that would lead to spurious failures where
+	 * futex_down_timeout returns ETIMEOUT despite there being
+	 * available tokens. That would break some algorithms.
+	 * We also don't want to loop on CAS indefinitely, because
+	 * that would make the semaphore not wait-free, even when all
+	 * atomic operations and the underlying base semaphore are all
+	 * wait-free.
+	 * It's much less trouble (and code bloat) to just do regular
+	 * down_timeout(), with an already expired deadline.
 	 */
 	struct timespec tv = { .tv_sec = 0, .tv_nsec = 0 };
Index: uspace/lib/c/generic/thread/fibril.c
===================================================================
--- uspace/lib/c/generic/thread/fibril.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/c/generic/thread/fibril.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -88,5 +88,5 @@
 /* This futex serializes access to global data. */
 static futex_t fibril_futex = FUTEX_INITIALIZER;
-static futex_t ready_semaphore = FUTEX_INITIALIZE(0);
+static futex_t ready_semaphore;
 static long ready_st_count;
 
@@ -117,19 +117,4 @@
 }
 
-static inline long _ready_count(void)
-{
-	/*
-	 * The number of available tokens is always equal to the number
-	 * of fibrils in the ready list + the number of free IPC buffer
-	 * buckets.
-	 */
-
-	if (multithreaded)
-		return atomic_get(&ready_semaphore.val);
-
-	_ready_debug_check();
-	return ready_st_count;
-}
-
 static inline void _ready_up(void)
 {
@@ -152,5 +137,5 @@
 }
 
-static atomic_t threads_in_ipc_wait = { 0 };
+static atomic_int threads_in_ipc_wait;
 
 /** Function that spans the whole life-cycle of a fibril.
@@ -303,5 +288,6 @@
 	fibril_t *f = list_pop(&ready_list, fibril_t, link);
 	if (!f)
-		atomic_inc(&threads_in_ipc_wait);
+		atomic_fetch_add_explicit(&threads_in_ipc_wait, 1,
+		    memory_order_relaxed);
 	if (!locked)
 		futex_unlock(&fibril_futex);
@@ -317,5 +303,6 @@
 	rc = _ipc_wait(&call, expires);
 
-	atomic_dec(&threads_in_ipc_wait);
+	atomic_fetch_sub_explicit(&threads_in_ipc_wait, 1,
+	    memory_order_relaxed);
 
 	if (rc != EOK && rc != ENOENT) {
@@ -386,5 +373,5 @@
 	_ready_up();
 
-	if (atomic_get(&threads_in_ipc_wait)) {
+	if (atomic_load_explicit(&threads_in_ipc_wait, memory_order_relaxed)) {
 		DPRINTF("Poking.\n");
 		/* Wakeup one thread sleeping in SYS_IPC_WAIT. */
@@ -811,5 +798,5 @@
 	if (!multithreaded) {
 		_ready_debug_check();
-		atomic_set(&ready_semaphore.val, ready_st_count);
+		futex_initialize(&ready_semaphore, ready_st_count);
 		multithreaded = true;
 	}
Index: uspace/lib/c/generic/thread/futex.c
===================================================================
--- uspace/lib/c/generic/thread/futex.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/c/generic/thread/futex.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -34,5 +34,5 @@
 
 #include <assert.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <fibril.h>
 #include <io/kio.h>
@@ -52,5 +52,5 @@
 void futex_initialize(futex_t *futex, int val)
 {
-	atomic_set(&futex->val, val);
+	atomic_store_explicit(&futex->val, val, memory_order_relaxed);
 }
 
@@ -59,5 +59,5 @@
 void __futex_assert_is_locked(futex_t *futex, const char *name)
 {
-	void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
+	void *owner = atomic_load_explicit(&futex->owner, memory_order_relaxed);
 	fibril_t *self = (fibril_t *) fibril_get_id();
 	if (owner != self) {
@@ -69,5 +69,5 @@
 void __futex_assert_is_not_locked(futex_t *futex, const char *name)
 {
-	void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
+	void *owner = atomic_load_explicit(&futex->owner, memory_order_relaxed);
 	fibril_t *self = (fibril_t *) fibril_get_id();
 	if (owner == self) {
@@ -91,7 +91,8 @@
 	futex_down(futex);
 
-	void *prev_owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
+	void *prev_owner = atomic_load_explicit(&futex->owner,
+	    memory_order_relaxed);
 	assert(prev_owner == NULL);
-	__atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED);
+	atomic_store_explicit(&futex->owner, self, memory_order_relaxed);
 }
 
@@ -101,5 +102,5 @@
 	DPRINTF("Unlocking futex %s (%p) by fibril %p.\n", name, futex, self);
 	__futex_assert_is_locked(futex, name);
-	__atomic_store_n(&futex->owner, NULL, __ATOMIC_RELAXED);
+	atomic_store_explicit(&futex->owner, NULL, memory_order_relaxed);
 	futex_up(futex);
 }
@@ -110,8 +111,9 @@
 	bool success = futex_trydown(futex);
 	if (success) {
-		void *owner = __atomic_load_n(&futex->owner, __ATOMIC_RELAXED);
+		void *owner = atomic_load_explicit(&futex->owner,
+		    memory_order_relaxed);
 		assert(owner == NULL);
 
-		__atomic_store_n(&futex->owner, self, __ATOMIC_RELAXED);
+		atomic_store_explicit(&futex->owner, self, memory_order_relaxed);
 
 		DPRINTF("Trylock on futex %s (%p) by fibril %p succeeded.\n", name, futex, self);
@@ -130,5 +132,5 @@
 
 	__futex_assert_is_locked(futex, name);
-	__atomic_store_n(&futex->owner, new_owner, __ATOMIC_RELAXED);
+	atomic_store_explicit(&futex->owner, new_owner, memory_order_relaxed);
 }
 
Index: pace/lib/c/include/atomic.h
===================================================================
--- uspace/lib/c/include/atomic.h	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ 	(revision )
@@ -1,99 +1,0 @@
-/*
- * Copyright (c) 2009 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ATOMIC_H_
-#define LIBC_ATOMIC_H_
-
-#include <stdatomic.h>
-#include <stdbool.h>
-#include <stddef.h>
-
-typedef size_t atomic_count_t;
-typedef ssize_t atomic_signed_t;
-
-#define PRIua  "zu"          /**< Format for atomic_count_t. */
-
-typedef struct atomic {
-	volatile atomic_size_t count;
-} atomic_t;
-
-static inline void atomic_set(atomic_t *val, atomic_count_t i)
-{
-	atomic_store(&val->count, i);
-}
-
-static inline atomic_count_t atomic_get(atomic_t *val)
-{
-	return atomic_load(&val->count);
-}
-
-static inline bool cas(atomic_t *val, atomic_count_t ov, atomic_count_t nv)
-{
-	return atomic_compare_exchange_strong(&val->count, &ov, nv);
-}
-
-static inline atomic_count_t atomic_postinc(atomic_t *val)
-{
-	return atomic_fetch_add(&val->count, 1);
-}
-
-static inline atomic_count_t atomic_postdec(atomic_t *val)
-{
-	return atomic_fetch_sub(&val->count, 1);
-}
-
-static inline atomic_count_t atomic_preinc(atomic_t *val)
-{
-	return atomic_postinc(val) + 1;
-}
-
-static inline atomic_count_t atomic_predec(atomic_t *val)
-{
-	return atomic_postdec(val) - 1;
-}
-
-static inline void atomic_inc(atomic_t *val)
-{
-	atomic_postinc(val);
-}
-
-static inline void atomic_dec(atomic_t *val)
-{
-	atomic_postdec(val);
-}
-
-#endif
-
-/** @}
- */
Index: pace/lib/c/include/atomicdflt.h
===================================================================
--- uspace/lib/c/include/atomicdflt.h	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*
- * Copyright (c) 2006 Jakub Jermar
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libc
- * @{
- */
-/** @file
- */
-
-#ifndef LIBC_ATOMICDFLT_H_
-#define LIBC_ATOMICDFLT_H_
-
-#ifndef LIBC_ARCH_ATOMIC_H_
-#error This file cannot be included directly, include atomic.h instead.
-#endif
-
-#include <types/common.h>
-#include <stdbool.h>
-
-typedef struct atomic {
-	volatile atomic_count_t count;
-} atomic_t;
-
-static inline void atomic_set(atomic_t *val, atomic_count_t i)
-{
-	val->count = i;
-}
-
-static inline atomic_count_t atomic_get(atomic_t *val)
-{
-	return val->count;
-}
-
-#ifndef CAS
-static inline bool cas(atomic_t *val, atomic_count_t ov, atomic_count_t nv)
-{
-	return __sync_bool_compare_and_swap(&val->count, ov, nv);
-}
-#endif
-
-#endif
-
-/** @}
- */
Index: uspace/lib/c/include/refcount.h
===================================================================
--- uspace/lib/c/include/refcount.h	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/c/include/refcount.h	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -40,20 +40,16 @@
 #define LIBC_REFCOUNT_H_
 
-// TODO: #include <stdatomic.h>
-
 #include <assert.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <stdbool.h>
 
 /* Wrapped in a structure to prevent direct manipulation. */
 typedef struct atomic_refcount {
-	//volatile atomic_int __cnt;
-	atomic_t __cnt;
+	volatile atomic_int __cnt;
 } atomic_refcount_t;
 
 static inline void refcount_init(atomic_refcount_t *rc)
 {
-	//atomic_store_explicit(&rc->__cnt, 0, memory_order_relaxed);
-	atomic_set(&rc->__cnt, 0);
+	atomic_store_explicit(&rc->__cnt, 0, memory_order_relaxed);
 }
 
@@ -72,8 +68,6 @@
 	//      still needs to be synchronized independently of the refcount.
 
-	//int old = atomic_fetch_add_explicit(&rc->__cnt, 1,
-	//    memory_order_relaxed);
-
-	atomic_signed_t old = atomic_postinc(&rc->__cnt);
+	int old = atomic_fetch_add_explicit(&rc->__cnt, 1,
+	    memory_order_relaxed);
 
 	/* old < 0 indicates that the function is used incorrectly. */
@@ -94,8 +88,6 @@
 	// XXX: The decrementers don't need to synchronize with each other,
 	//      but they do need to synchronize with the one doing deallocation.
-	//int old = atomic_fetch_sub_explicit(&rc->__cnt, 1,
-	//    memory_order_release);
-
-	atomic_signed_t old = atomic_postdec(&rc->__cnt);
+	int old = atomic_fetch_sub_explicit(&rc->__cnt, 1,
+	    memory_order_release);
 
 	assert(old >= 0);
@@ -104,8 +96,14 @@
 		// XXX: We are holding the last reference, so we must now
 		//      synchronize with all the other decrementers.
-		//int val = atomic_load_explicit(&rc->__cnt,
-		//    memory_order_acquire);
-		//assert(val == -1);
-		return true;
+
+		int val = atomic_load_explicit(&rc->__cnt,
+		    memory_order_acquire);
+		assert(val == -1);
+
+		/*
+		 * The compiler probably wouldn't optimize the memory barrier
+		 * away, but better safe than sorry.
+		 */
+		return val < 0;
 	}
 
Index: uspace/lib/graph/graph.c
===================================================================
--- uspace/lib/graph/graph.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/graph/graph.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -70,5 +70,5 @@
 {
 	link_initialize(&vs->link);
-	atomic_set(&vs->ref_cnt, 0);
+	atomic_flag_clear(&vs->claimed);
 	vs->notif_sess = NULL;
 	fibril_mutex_initialize(&vs->mode_mtx);
@@ -83,5 +83,5 @@
 	// TODO
 	link_initialize(&rnd->link);
-	atomic_set(&rnd->ref_cnt, 0);
+	refcount_init(&rnd->ref_cnt);
 }
 
@@ -173,4 +173,7 @@
 	}
 
+	if (rnd)
+		refcount_up(&rnd->ref_cnt);
+
 	fibril_mutex_unlock(&renderer_list_mtx);
 
@@ -200,5 +203,5 @@
 void graph_destroy_visualizer(visualizer_t *vs)
 {
-	assert(atomic_get(&vs->ref_cnt) == 0);
+	assert(!atomic_flag_test_and_set(&vs->claimed));
 	assert(vs->notif_sess == NULL);
 	assert(!fibril_mutex_is_locked(&vs->mode_mtx));
@@ -214,7 +217,6 @@
 {
 	// TODO
-	assert(atomic_get(&rnd->ref_cnt) == 0);
-
-	free(rnd);
+	if (refcount_down(&rnd->ref_cnt))
+		free(rnd);
 }
 
@@ -493,5 +495,5 @@
 {
 	/* Claim the visualizer. */
-	if (!cas(&vs->ref_cnt, 0, 1)) {
+	if (atomic_flag_test_and_set(&vs->claimed)) {
 		async_answer_0(icall, ELIMIT);
 		return;
@@ -559,5 +561,5 @@
 	async_hangup(vs->notif_sess);
 	vs->notif_sess = NULL;
-	atomic_set(&vs->ref_cnt, 0);
+	atomic_flag_clear(&vs->claimed);
 }
 
@@ -567,5 +569,4 @@
 
 	/* Accept the connection. */
-	atomic_inc(&rnd->ref_cnt);
 	async_answer_0(icall, EOK);
 
@@ -588,5 +589,5 @@
 
 terminate:
-	atomic_dec(&rnd->ref_cnt);
+	graph_destroy_renderer(rnd);
 }
 
Index: uspace/lib/graph/graph.h
===================================================================
--- uspace/lib/graph/graph.h	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/graph/graph.h	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -40,5 +40,6 @@
 #include <loc.h>
 #include <async.h>
-#include <atomic.h>
+#include <stdatomic.h>
+#include <refcount.h>
 #include <fibril_synch.h>
 #include <adt/list.h>
@@ -121,5 +122,5 @@
 	 * Field is fully managed by libgraph.
 	 */
-	atomic_t ref_cnt;
+	atomic_flag claimed;
 
 	/**
@@ -272,5 +273,5 @@
 	link_t link;
 
-	atomic_t ref_cnt;
+	atomic_refcount_t ref_cnt;
 
 	sysarg_t reg_svc_handle;
Index: uspace/lib/gui/terminal.c
===================================================================
--- uspace/lib/gui/terminal.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/gui/terminal.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -45,5 +45,4 @@
 #include <adt/list.h>
 #include <adt/prodcons.h>
-#include <atomic.h>
 #include <stdarg.h>
 #include <str.h>
@@ -694,5 +693,5 @@
 	}
 
-	if (atomic_postinc(&term->refcnt) == 0)
+	if (!atomic_flag_test_and_set(&term->refcnt))
 		chargrid_set_cursor_visibility(term->frontbuf, true);
 
@@ -707,5 +706,5 @@
 	link_initialize(&term->link);
 	fibril_mutex_initialize(&term->mtx);
-	atomic_set(&term->refcnt, 0);
+	atomic_flag_clear(&term->refcnt);
 
 	prodcons_initialize(&term->input_pc);
Index: uspace/lib/gui/terminal.h
===================================================================
--- uspace/lib/gui/terminal.h	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/lib/gui/terminal.h	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -44,5 +44,5 @@
 #include <adt/list.h>
 #include <adt/prodcons.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <str.h>
 #include "widget.h"
@@ -55,5 +55,5 @@
 	fibril_mutex_t mtx;
 	link_t link;
-	atomic_t refcnt;
+	atomic_flag refcnt;
 
 	prodcons_t input_pc;
Index: uspace/srv/hid/console/console.c
===================================================================
--- uspace/srv/hid/console/console.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/srv/hid/console/console.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -34,5 +34,4 @@
 
 #include <async.h>
-#include <atomic.h>
 #include <stdio.h>
 #include <adt/prodcons.h>
@@ -51,4 +50,5 @@
 #include <task.h>
 #include <fibril_synch.h>
+#include <stdatomic.h>
 #include <stdlib.h>
 #include <str.h>
@@ -61,5 +61,5 @@
 
 typedef struct {
-	atomic_t refcnt;      /**< Connection reference count */
+	atomic_flag refcnt;      /**< Connection reference count */
 	prodcons_t input_pc;  /**< Incoming keyboard events */
 
@@ -524,5 +524,5 @@
 	}
 
-	if (atomic_postinc(&cons->refcnt) == 0)
+	if (!atomic_flag_test_and_set(&cons->refcnt))
 		cons_set_cursor_vis(cons, true);
 
@@ -612,5 +612,5 @@
 		for (size_t i = 0; i < CONSOLE_COUNT; i++) {
 			consoles[i].index = i;
-			atomic_set(&consoles[i].refcnt, 0);
+			atomic_flag_clear(&consoles[i].refcnt);
 			fibril_mutex_initialize(&consoles[i].mtx);
 			prodcons_initialize(&consoles[i].input_pc);
Index: uspace/srv/vfs/vfs_register.c
===================================================================
--- uspace/srv/vfs/vfs_register.c	(revision 4621d2311994bf63dea425ed923239d4ca1babc9)
+++ uspace/srv/vfs/vfs_register.c	(revision 508b0df1a393bdc2b6b8e8f8f45be1a5be4a868b)
@@ -49,5 +49,5 @@
 #include <as.h>
 #include <assert.h>
-#include <atomic.h>
+#include <stdatomic.h>
 #include <vfs/vfs.h>
 #include "vfs.h"
@@ -57,7 +57,5 @@
 LIST_INITIALIZE(fs_list);
 
-atomic_t fs_handle_next = {
-	.count = 1
-};
+static atomic_int fs_handle_next = 1;
 
 /** Verify the VFS info structure.
@@ -236,5 +234,5 @@
 	 * system a global file system handle.
 	 */
-	fs_info->fs_handle = (fs_handle_t) atomic_postinc(&fs_handle_next);
+	fs_info->fs_handle = atomic_fetch_add(&fs_handle_next, 1);
 	async_answer_1(req, EOK, (sysarg_t) fs_info->fs_handle);
 
