diff options
Diffstat (limited to 'mesalib/src/util')
-rw-r--r-- | mesalib/src/util/.gitignore | 1 | ||||
-rw-r--r-- | mesalib/src/util/Makefile.am | 4 | ||||
-rw-r--r-- | mesalib/src/util/Makefile.sources | 10 | ||||
-rw-r--r-- | mesalib/src/util/SConscript | 9 | ||||
-rw-r--r-- | mesalib/src/util/hash_table.c | 75 | ||||
-rw-r--r-- | mesalib/src/util/hash_table.h | 19 | ||||
-rw-r--r-- | mesalib/src/util/register_allocate.c | 14 | ||||
-rw-r--r-- | mesalib/src/util/u_atomic.h | 188 | ||||
-rw-r--r-- | mesalib/src/util/u_atomic_test.c | 137 |
9 files changed, 425 insertions, 32 deletions
diff --git a/mesalib/src/util/.gitignore b/mesalib/src/util/.gitignore index e945ecbb5..ecf4985fe 100644 --- a/mesalib/src/util/.gitignore +++ b/mesalib/src/util/.gitignore @@ -1 +1,2 @@ format_srgb.c +u_atomic_test diff --git a/mesalib/src/util/Makefile.am b/mesalib/src/util/Makefile.am index 8d5f90e97..c7e183e8d 100644 --- a/mesalib/src/util/Makefile.am +++ b/mesalib/src/util/Makefile.am @@ -37,8 +37,12 @@ libmesautil_la_SOURCES = \ $(MESA_UTIL_FILES) \ $(MESA_UTIL_GENERATED_FILES) +check_PROGRAMS = u_atomic_test +TESTS = $(check_PROGRAMS) + BUILT_SOURCES = $(MESA_UTIL_GENERATED_FILES) CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = format_srgb.py SConscript format_srgb.c: $(srcdir)/format_srgb.py $(AM_V_GEN) $(PYTHON2) $< > $@ diff --git a/mesalib/src/util/Makefile.sources b/mesalib/src/util/Makefile.sources index 9e274241d..5f87fc32a 100644 --- a/mesalib/src/util/Makefile.sources +++ b/mesalib/src/util/Makefile.sources @@ -1,10 +1,18 @@ MESA_UTIL_FILES := \ + format_srgb.h \ hash_table.c \ + hash_table.h \ + macros.h \ ralloc.c \ + ralloc.h \ register_allocate.c \ register_allocate.h \ rgtc.c \ - strtod.cpp + rgtc.h \ + strtod.cpp \ + strtod.h \ + texcompress_rgtc_tmp.h \ + u_atomic.h MESA_UTIL_GENERATED_FILES = \ format_srgb.c diff --git a/mesalib/src/util/SConscript b/mesalib/src/util/SConscript index ade1d6c6c..34b9a2dea 100644 --- a/mesalib/src/util/SConscript +++ b/mesalib/src/util/SConscript @@ -36,3 +36,12 @@ mesautil = env.ConvenienceLibrary( env.Alias('mesautil', mesautil) Export('mesautil') + + +# http://www.scons.org/wiki/UnitTests +u_atomic_test = env.Program( + target = 'u_atomic_test', + source = ['u_atomic_test.c'], +) +alias = env.Alias("u_atomic_test", u_atomic_test, u_atomic_test[0].abspath) +AlwaysBuild(alias) diff --git a/mesalib/src/util/hash_table.c b/mesalib/src/util/hash_table.c index 920bdfd33..0ad038377 100644 --- a/mesalib/src/util/hash_table.c +++ b/mesalib/src/util/hash_table.c @@ -42,6 +42,7 @@ #include <stdlib.h> #include <string.h> +#include <assert.h> #include "hash_table.h" #include "ralloc.h" @@ -110,6 +111,7 @@ entry_is_present(const struct hash_table *ht, struct hash_entry *entry) struct hash_table * _mesa_hash_table_create(void *mem_ctx, + uint32_t (*key_hash_function)(const void *key), bool (*key_equals_function)(const void *a, const void *b)) { @@ -123,6 +125,7 @@ _mesa_hash_table_create(void *mem_ctx, ht->size = hash_sizes[ht->size_index].size; ht->rehash = hash_sizes[ht->size_index].rehash; ht->max_entries = hash_sizes[ht->size_index].max_entries; + ht->key_hash_function = key_hash_function; ht->key_equals_function = key_equals_function; ht->table = rzalloc_array(ht, struct hash_entry, ht->size); ht->entries = 0; @@ -176,15 +179,8 @@ _mesa_hash_table_set_deleted_key(struct hash_table *ht, const void *deleted_key) ht->deleted_key = deleted_key; } -/** - * Finds a hash table entry with the given key and hash of that key. - * - * Returns NULL if no entry is found. Note that the data pointer may be - * modified by the user. - */ -struct hash_entry * -_mesa_hash_table_search(struct hash_table *ht, uint32_t hash, - const void *key) +static struct hash_entry * +hash_table_search(struct hash_table *ht, uint32_t hash, const void *key) { uint32_t start_hash_address = hash % ht->size; uint32_t hash_address = start_hash_address; @@ -210,6 +206,31 @@ _mesa_hash_table_search(struct hash_table *ht, uint32_t hash, return NULL; } +/** + * Finds a hash table entry with the given key and hash of that key. + * + * Returns NULL if no entry is found. Note that the data pointer may be + * modified by the user. + */ +struct hash_entry * +_mesa_hash_table_search(struct hash_table *ht, const void *key) +{ + assert(ht->key_hash_function); + return hash_table_search(ht, ht->key_hash_function(key), key); +} + +struct hash_entry * +_mesa_hash_table_search_pre_hashed(struct hash_table *ht, uint32_t hash, + const void *key) +{ + assert(ht->key_hash_function == NULL || hash == ht->key_hash_function(key)); + return hash_table_search(ht, hash, key); +} + +static struct hash_entry * +hash_table_insert(struct hash_table *ht, uint32_t hash, + const void *key, void *data); + static void _mesa_hash_table_rehash(struct hash_table *ht, int new_size_index) { @@ -235,22 +256,15 @@ _mesa_hash_table_rehash(struct hash_table *ht, int new_size_index) ht->deleted_entries = 0; hash_table_foreach(&old_ht, entry) { - _mesa_hash_table_insert(ht, entry->hash, - entry->key, entry->data); + hash_table_insert(ht, entry->hash, entry->key, entry->data); } ralloc_free(old_ht.table); } -/** - * Inserts the key with the given hash into the table. - * - * Note that insertion may rearrange the table on a resize or rehash, - * so previously found hash_entries are no longer valid after this function. - */ -struct hash_entry * -_mesa_hash_table_insert(struct hash_table *ht, uint32_t hash, - const void *key, void *data) +static struct hash_entry * +hash_table_insert(struct hash_table *ht, uint32_t hash, + const void *key, void *data) { uint32_t start_hash_address, hash_address; @@ -307,6 +321,27 @@ _mesa_hash_table_insert(struct hash_table *ht, uint32_t hash, } /** + * Inserts the key with the given hash into the table. + * + * Note that insertion may rearrange the table on a resize or rehash, + * so previously found hash_entries are no longer valid after this function. + */ +struct hash_entry * +_mesa_hash_table_insert(struct hash_table *ht, const void *key, void *data) +{ + assert(ht->key_hash_function); + return hash_table_insert(ht, ht->key_hash_function(key), key, data); +} + +struct hash_entry * +_mesa_hash_table_insert_with_hash(struct hash_table *ht, uint32_t hash, + const void *key, void *data) +{ + assert(ht->key_hash_function == NULL || hash == ht->key_hash_function(key)); + return hash_table_insert(ht, hash, key, data); +} + +/** * This function deletes the given hash table entry. * * Note that deletion doesn't otherwise modify the table, so an iteration over diff --git a/mesalib/src/util/hash_table.h b/mesalib/src/util/hash_table.h index d6b6ebf40..5561e1584 100644 --- a/mesalib/src/util/hash_table.h +++ b/mesalib/src/util/hash_table.h @@ -46,6 +46,7 @@ struct hash_entry { struct hash_table { struct hash_entry *table; + uint32_t (*key_hash_function)(const void *key); bool (*key_equals_function)(const void *a, const void *b); const void *deleted_key; uint32_t size; @@ -58,6 +59,7 @@ struct hash_table { struct hash_table * _mesa_hash_table_create(void *mem_ctx, + uint32_t (*key_hash_function)(const void *key), bool (*key_equals_function)(const void *a, const void *b)); void _mesa_hash_table_destroy(struct hash_table *ht, @@ -66,11 +68,15 @@ void _mesa_hash_table_set_deleted_key(struct hash_table *ht, const void *deleted_key); struct hash_entry * -_mesa_hash_table_insert(struct hash_table *ht, uint32_t hash, - const void *key, void *data); +_mesa_hash_table_insert(struct hash_table *ht, const void *key, void *data); struct hash_entry * -_mesa_hash_table_search(struct hash_table *ht, uint32_t hash, - const void *key); +_mesa_hash_table_insert_with_hash(struct hash_table *ht, uint32_t hash, + const void *key, void *data); +struct hash_entry * +_mesa_hash_table_search(struct hash_table *ht, const void *key); +struct hash_entry * +_mesa_hash_table_search_pre_hashed(struct hash_table *ht, uint32_t hash, + const void *key); void _mesa_hash_table_remove(struct hash_table *ht, struct hash_entry *entry); @@ -85,6 +91,11 @@ uint32_t _mesa_hash_string(const char *key); bool _mesa_key_string_equal(const void *a, const void *b); bool _mesa_key_pointer_equal(const void *a, const void *b); +static inline uint32_t _mesa_key_hash_string(const void *key) +{ + return _mesa_hash_string((const char *)key); +} + static inline uint32_t _mesa_hash_pointer(const void *pointer) { return _mesa_hash_data(&pointer, sizeof(pointer)); diff --git a/mesalib/src/util/register_allocate.c b/mesalib/src/util/register_allocate.c index 6cf7ce721..af7a20c09 100644 --- a/mesalib/src/util/register_allocate.c +++ b/mesalib/src/util/register_allocate.c @@ -79,7 +79,7 @@ #include "main/bitset.h" #include "register_allocate.h" -#define NO_REG ~0 +#define NO_REG ~0U struct ra_reg { BITSET_WORD *conflicts; @@ -251,7 +251,7 @@ void ra_add_transitive_reg_conflict(struct ra_regs *regs, unsigned int base_reg, unsigned int reg) { - int i; + unsigned int i; ra_add_reg_conflict(regs, reg, base_reg); @@ -328,7 +328,7 @@ ra_set_finalize(struct ra_regs *regs, unsigned int **q_values) for (rc = 0; rc < regs->count; rc++) { int conflicts = 0; - int i; + unsigned int i; if (!reg_belongs_to_class(rc, regs->classes[c])) continue; @@ -374,7 +374,7 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) struct ra_graph *g; unsigned int i; - g = rzalloc(regs, struct ra_graph); + g = rzalloc(NULL, struct ra_graph); g->regs = regs; g->nodes = rzalloc_array(g, struct ra_node, count); g->count = count; @@ -481,7 +481,7 @@ ra_simplify(struct ra_graph *g) } } - if (!progress && best_optimistic_node != ~0) { + if (!progress && best_optimistic_node != ~0U) { decrement_q(g, best_optimistic_node); g->stack[g->stack_count] = best_optimistic_node; g->stack_count++; @@ -501,10 +501,10 @@ ra_simplify(struct ra_graph *g) static bool ra_select(struct ra_graph *g) { - int i; int start_search_reg = 0; while (g->stack_count != 0) { + unsigned int i; unsigned int ri; unsigned int r = -1; int n = g->stack[g->stack_count - 1]; @@ -585,7 +585,7 @@ ra_set_node_reg(struct ra_graph *g, unsigned int n, unsigned int reg) static float ra_get_spill_benefit(struct ra_graph *g, unsigned int n) { - int j; + unsigned int j; float benefit = 0; int n_class = g->nodes[n].class; diff --git a/mesalib/src/util/u_atomic.h b/mesalib/src/util/u_atomic.h new file mode 100644 index 000000000..401003638 --- /dev/null +++ b/mesalib/src/util/u_atomic.h @@ -0,0 +1,188 @@ +/** + * Many similar implementations exist. See for example libwsbm + * or the linux kernel include/atomic.h + * + * No copyright claimed on this file. + * + */ + +#ifndef U_ATOMIC_H +#define U_ATOMIC_H + +#include <stdbool.h> + +/* Favor OS-provided implementations. + * + * Where no OS-provided implementation is available, fall back to + * locally coded assembly, compiler intrinsic or ultimately a + * mutex-based implementation. + */ +#if defined(__sun) +#define PIPE_ATOMIC_OS_SOLARIS +#elif defined(_MSC_VER) +#define PIPE_ATOMIC_MSVC_INTRINSIC +#elif defined(__GNUC__) +#define PIPE_ATOMIC_GCC_INTRINSIC +#else +#error "Unsupported platform" +#endif + + +/* Implementation using GCC-provided synchronization intrinsics + */ +#if defined(PIPE_ATOMIC_GCC_INTRINSIC) + +#define PIPE_ATOMIC "GCC Sync Intrinsics" + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) +#define p_atomic_dec_zero(v) (__sync_sub_and_fetch((v), 1) == 0) +#define p_atomic_inc(v) (void) __sync_add_and_fetch((v), 1) +#define p_atomic_dec(v) (void) __sync_sub_and_fetch((v), 1) +#define p_atomic_inc_return(v) __sync_add_and_fetch((v), 1) +#define p_atomic_dec_return(v) __sync_sub_and_fetch((v), 1) +#define p_atomic_cmpxchg(v, old, _new) \ + __sync_val_compare_and_swap((v), (old), (_new)) + +#endif + + + +/* Unlocked version for single threaded environments, such as some + * windows kernel modules. + */ +#if defined(PIPE_ATOMIC_OS_UNLOCKED) + +#define PIPE_ATOMIC "Unlocked" + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) +#define p_atomic_dec_zero(_v) (p_atomic_dec_return(_v) == 0) +#define p_atomic_inc(_v) ((void) p_atomic_inc_return(_v)) +#define p_atomic_dec(_v) ((void) p_atomic_dec_return(_v)) +#define p_atomic_inc_return(_v) (++(*(_v))) +#define p_atomic_dec_return(_v) (--(*(_v))) +#define p_atomic_cmpxchg(_v, _old, _new) (*(_v) == (_old) ? (*(_v) = (_new), (_old)) : *(_v)) + +#endif + + +#if defined(PIPE_ATOMIC_MSVC_INTRINSIC) + +#define PIPE_ATOMIC "MSVC Intrinsics" + +/* We use the Windows header's Interlocked* functions instead of the + * _Interlocked* intrinsics wherever we can, as support for the latter varies + * with target CPU, whereas Windows headers take care of all portability + * issues: using intrinsics where available, falling back to library + * implementations where not. + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include <windows.h> +#include <intrin.h> +#include <assert.h> + +#pragma intrinsic(_InterlockedCompareExchange8) + +/* MSVC supports decltype keyword, but it's only supported on C++ and doesn't + * quite work here; and if a C++-only solution is worthwhile, then it would be + * better to use templates / function overloading, instead of decltype magic. + * Therefore, we rely on implicit casting to LONGLONG for the functions that return + */ + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +#define p_atomic_dec_zero(_v) \ + (p_atomic_dec_return(_v) == 0) + +#define p_atomic_inc(_v) \ + ((void) p_atomic_inc_return(_v)) + +#define p_atomic_inc_return(_v) (\ + sizeof *(_v) == sizeof(short) ? InterlockedIncrement16((short *) (_v)) : \ + sizeof *(_v) == sizeof(long) ? InterlockedIncrement ((long *) (_v)) : \ + sizeof *(_v) == sizeof(__int64) ? InterlockedIncrement64((__int64 *)(_v)) : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_dec(_v) \ + ((void) p_atomic_dec_return(_v)) + +#define p_atomic_dec_return(_v) (\ + sizeof *(_v) == sizeof(short) ? InterlockedDecrement16((short *) (_v)) : \ + sizeof *(_v) == sizeof(long) ? InterlockedDecrement ((long *) (_v)) : \ + sizeof *(_v) == sizeof(__int64) ? InterlockedDecrement64((__int64 *)(_v)) : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_cmpxchg(_v, _old, _new) (\ + sizeof *(_v) == sizeof(char) ? _InterlockedCompareExchange8((char *) (_v), (char) (_new), (char) (_old)) : \ + sizeof *(_v) == sizeof(short) ? InterlockedCompareExchange16((short *) (_v), (short) (_new), (short) (_old)) : \ + sizeof *(_v) == sizeof(long) ? InterlockedCompareExchange ((long *) (_v), (long) (_new), (long) (_old)) : \ + sizeof *(_v) == sizeof(__int64) ? InterlockedCompareExchange64((__int64 *)(_v), (__int64)(_new), (__int64)(_old)) : \ + (assert(!"should not get here"), 0)) + +#endif + +#if defined(PIPE_ATOMIC_OS_SOLARIS) + +#define PIPE_ATOMIC "Solaris OS atomic functions" + +#include <atomic.h> +#include <assert.h> + +#define p_atomic_set(_v, _i) (*(_v) = (_i)) +#define p_atomic_read(_v) (*(_v)) + +#define p_atomic_dec_zero(v) (\ + sizeof(*v) == sizeof(uint8_t) ? atomic_dec_8_nv ((uint8_t *)(v)) == 0 : \ + sizeof(*v) == sizeof(uint16_t) ? atomic_dec_16_nv((uint16_t *)(v)) == 0 : \ + sizeof(*v) == sizeof(uint32_t) ? atomic_dec_32_nv((uint32_t *)(v)) == 0 : \ + sizeof(*v) == sizeof(uint64_t) ? atomic_dec_64_nv((uint64_t *)(v)) == 0 : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_inc(v) (void) (\ + sizeof(*v) == sizeof(uint8_t) ? atomic_inc_8 ((uint8_t *)(v)) : \ + sizeof(*v) == sizeof(uint16_t) ? atomic_inc_16((uint16_t *)(v)) : \ + sizeof(*v) == sizeof(uint32_t) ? atomic_inc_32((uint32_t *)(v)) : \ + sizeof(*v) == sizeof(uint64_t) ? atomic_inc_64((uint64_t *)(v)) : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_inc_return(v) ((typeof(*v)) \ + sizeof(*v) == sizeof(uint8_t) ? atomic_inc_8_nv ((uint8_t *)(v)) : \ + sizeof(*v) == sizeof(uint16_t) ? atomic_inc_16_nv((uint16_t *)(v)) : \ + sizeof(*v) == sizeof(uint32_t) ? atomic_inc_32_nv((uint32_t *)(v)) : \ + sizeof(*v) == sizeof(uint64_t) ? atomic_inc_64_nv((uint64_t *)(v)) : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_dec(v) ((void) \ + sizeof(*v) == sizeof(uint8_t) ? atomic_dec_8 ((uint8_t *)(v)) : \ + sizeof(*v) == sizeof(uint16_t) ? atomic_dec_16((uint16_t *)(v)) : \ + sizeof(*v) == sizeof(uint32_t) ? atomic_dec_32((uint32_t *)(v)) : \ + sizeof(*v) == sizeof(uint64_t) ? atomic_dec_64((uint64_t *)(v)) : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_dec_return(v) ((typeof(*v)) \ + sizeof(*v) == sizeof(uint8_t) ? atomic_dec_8_nv ((uint8_t *)(v)) : \ + sizeof(*v) == sizeof(uint16_t) ? atomic_dec_16_nv((uint16_t *)(v)) : \ + sizeof(*v) == sizeof(uint32_t) ? atomic_dec_32_nv((uint32_t *)(v)) : \ + sizeof(*v) == sizeof(uint64_t) ? atomic_dec_64_nv((uint64_t *)(v)) : \ + (assert(!"should not get here"), 0)) + +#define p_atomic_cmpxchg(v, old, _new) ((typeof(*v)) \ + sizeof(*v) == sizeof(uint8_t) ? atomic_cas_8 ((uint8_t *)(v), (uint8_t )(old), (uint8_t )(_new)) : \ + sizeof(*v) == sizeof(uint16_t) ? atomic_cas_16((uint16_t *)(v), (uint16_t)(old), (uint16_t)(_new)) : \ + sizeof(*v) == sizeof(uint32_t) ? atomic_cas_32((uint32_t *)(v), (uint32_t)(old), (uint32_t)(_new)) : \ + sizeof(*v) == sizeof(uint64_t) ? atomic_cas_64((uint64_t *)(v), (uint64_t)(old), (uint64_t)(_new)) : \ + (assert(!"should not get here"), 0)) + +#endif + +#ifndef PIPE_ATOMIC +#error "No pipe_atomic implementation selected" +#endif + + + +#endif /* U_ATOMIC_H */ diff --git a/mesalib/src/util/u_atomic_test.c b/mesalib/src/util/u_atomic_test.c new file mode 100644 index 000000000..4845e753e --- /dev/null +++ b/mesalib/src/util/u_atomic_test.c @@ -0,0 +1,137 @@ +/************************************************************************** + * + * Copyright 2014 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/* Force assertions, even on debug builds. */ +#undef NDEBUG + + +#include <stdint.h> +#include <inttypes.h> +#include <assert.h> + +#include "u_atomic.h" + + +#define test_atomic_cmpxchg(type, ones) \ + static void test_atomic_cmpxchg_##type (void) { \ + type v, r; \ + \ + p_atomic_set(&v, ones); \ + assert(v == ones && "p_atomic_set"); \ + \ + r = p_atomic_read(&v); \ + assert(r == ones && "p_atomic_read"); \ + \ + v = ones; \ + r = p_atomic_cmpxchg(&v, 0, 1); \ + assert(v == ones && "p_atomic_cmpxchg"); \ + assert(r == ones && "p_atomic_cmpxchg"); \ + r = p_atomic_cmpxchg(&v, ones, 0); \ + assert(v == 0 && "p_atomic_cmpxchg"); \ + assert(r == ones && "p_atomic_cmpxchg"); \ + \ + (void) r; \ + } + + +#define test_atomic(type, ones) \ + test_atomic_cmpxchg(type, ones) \ + \ + static void test_atomic_##type (void) { \ + type v, r; \ + bool b; \ + \ + test_atomic_cmpxchg_##type(); \ + \ + v = 2; \ + b = p_atomic_dec_zero(&v); \ + assert(v == 1 && "p_atomic_dec_zero"); \ + assert(b == false && "p_atomic_dec_zero"); \ + b = p_atomic_dec_zero(&v); \ + assert(v == 0 && "p_atomic_dec_zero"); \ + assert(b == true && "p_atomic_dec_zero"); \ + b = p_atomic_dec_zero(&v); \ + assert(v == ones && "p_atomic_dec_zero"); \ + assert(b == false && "p_atomic_dec_zero"); \ + \ + v = ones; \ + p_atomic_inc(&v); \ + assert(v == 0 && "p_atomic_inc"); \ + \ + v = ones; \ + r = p_atomic_inc_return(&v); \ + assert(v == 0 && "p_atomic_inc_return"); \ + assert(r == v && "p_atomic_inc_return"); \ + \ + v = 0; \ + p_atomic_dec(&v); \ + assert(v == ones && "p_atomic_dec"); \ + \ + v = 0; \ + r = p_atomic_dec_return(&v); \ + assert(v == ones && "p_atomic_dec_return"); \ + assert(r == v && "p_atomic_dec_return"); \ + \ + (void) r; \ + (void) b; \ + } + + +test_atomic(int, -1) +test_atomic(unsigned, ~0U) + +test_atomic(int16_t, INT16_C(-1)) +test_atomic(uint16_t, UINT16_C(0xffff)) +test_atomic(int32_t, INT32_C(-1)) +test_atomic(uint32_t, UINT32_C(0xffffffff)) +test_atomic(int64_t, INT64_C(-1)) +test_atomic(uint64_t, UINT64_C(0xffffffffffffffff)) + +test_atomic_cmpxchg(int8_t, INT8_C(-1)) +test_atomic_cmpxchg(uint8_t, UINT8_C(0xff)) +test_atomic_cmpxchg(bool, true) + +int +main() +{ + test_atomic_int(); + test_atomic_unsigned(); + + test_atomic_int16_t(); + test_atomic_uint16_t(); + test_atomic_int32_t(); + test_atomic_uint32_t(); + test_atomic_int64_t(); + test_atomic_uint64_t(); + + test_atomic_cmpxchg_int8_t(); + test_atomic_cmpxchg_uint8_t(); + test_atomic_cmpxchg_bool(); + + return 0; +} |