123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- *
- * simple atomic ops testing program
- * (no parallel stuff, just see if the opcodes are "legal")
- *
- * Defines: TYPE - not defined => use atomic_t and the corresponding
- * atomic functions
- * - long => use volatile long* and the atomic_*_long functions
- * - int => use volatile int* and the atomic_*_int functions
- * MEMBAR - if defined use mb_atomic_* instead of atomic_*
- * NOSMP - use non smp versions
- * NOASM - don't use asm inline version
- * __CPU_xxx - use __CPU_xxx code
- * SPARC64_MODE - compile for a sparc 64 in 64 bit mode (gcc -m64
- * must be used on solaris in this case)
- * Example:
- * gcc -Wall -O3 -D__CPU_i386 -DNOSMP -DMEMBAR -DTYPE=long atomic_test2.c
- *
- * Compile with: gcc -Wall -O3 -D__CPU_i386 ... on x86 machines
- * gcc -Wall -O3 -D__CPU_x86_64 ... on amd64 machines
- * gcc -mips2 -Wall -O2 -D__CPU_mips2 ... on mips machines
- * gcc -m64 -Wall -O2 -D__CPU_mips64 ... on mips64 machines
- * gcc -O3 -Wall -D__CPU_ppc ... on powerpc machines
- * gcc -m64 -O3 -Wall -D__CPU_ppc64 ... on powerpc machines
- * gcc -m64 -O3 -Wall -D__CPU_sparc64 -DSPARC64_MODE ... on
- * ultrasparc machines
- * gcc -mcpu=v9 -O3 -Wall -D__CPU_sparc64 ... for 32 bit code
- * (sparc32plus) on
- * ultrasparc machines
- * gcc -O3 -Wall -D__CPU_sparc ... on sparc v8 machines
- * -- andrei
- *
- *
- */
- #include <stdio.h>
- #ifndef NOASM
- #define CC_GCC_LIKE_ASM
- #endif
- #include "../atomic_ops.h"
- #if defined ATOMIC_OPS_USE_LOCK || defined MEMBAR_USES_LOCK || \
- defined ATOMIC_OPS_USE_LOCK_SET
- /* hack to make lock work */
- #include "../lock_ops.h"
- #endif
- #ifdef MEMBAR_USES_LOCK
- gen_lock_t* __membar_lock=0; /* init in atomic_ops.c */
- gen_lock_t dummy_membar_lock;
- #endif
- #ifdef ATOMIC_OPS_USE_LOCK_SET
- gen_lock_set_t* _atomic_lock_set=0;
- gen_lock_set_t dummy_atomic_lock_set;
- gen_lock_t locks_array[_ATOMIC_LS_SIZE];
- #elif defined ATOMIC_OPS_USE_LOCK
- gen_lock_t* _atomic_lock=0;
- gen_lock_t dummy_atomic_lock;
- #endif /* ATOMIC_OPS_USE_LOCK / _SET */
- #if defined MB || defined MEMBAR
- #undef MB
- #define MB mb_
- #define MEMBAR_STR "membar "
- #else
- #define MB /* empty */
- #define MEMBAR_STR ""
- #endif
- #ifndef TYPE
- #define SUF
- #define ATOMIC_TYPE atomic_t
- #define VALUE_TYPE volatile int
- #define get_val(v) (v->val)
- #else
- #define _SUF(T) _##T
- #define _SUF1(T) _SUF(T)
- #define SUF _SUF1(TYPE)
- #define ATOMIC_TYPE volatile TYPE
- #define VALUE_TYPE ATOMIC_TYPE
- #define get_val(v) (*v)
- #endif
- #define _STR(S) #S
- #define STR(S) _STR(S)
- static char* flags=
- #ifdef NOASM
- "no_inline_asm "
- #endif
- #ifdef NOSMP
- "nosmp "
- #else
- "smp "
- #endif
- MEMBAR_STR
- #ifndef HAVE_ASM_INLINE_MEMBAR
- "no_asm_membar(slow) "
- #endif
- #ifndef HAVE_ASM_INLINE_ATOMIC_OPS
- "no_asm_atomic_ops"
- #ifdef ATOMIC_OPS_USE_LOCK_SET
- ":use_lock_set"
- #elif defined ATOMIC_OPS_USE_LOCK
- ":use_lock"
- #endif
- " "
- #endif
- #ifdef TYPE
- STR(TYPE) " "
- #else
- "atomic_t "
- #endif
- ;
- /* macros for atomic_* functions */
- #define _AT_DECL(OP, P, S) \
- P##atomic_##OP##S
- /* to make sure all the macro passed as params are expanded,
- * go through a 2 level deep macro decl. */
- #define _AT_DECL1(OP, P, S) _AT_DECL(OP, P, S)
- #define AT_DECL(OP) _AT_DECL1(OP, MB, SUF)
- #define at_set AT_DECL(set)
- #define at_get AT_DECL(get)
- #define at_inc AT_DECL(inc)
- #define at_dec AT_DECL(dec)
- #define at_inc_and_test AT_DECL(inc_and_test)
- #define at_dec_and_test AT_DECL(dec_and_test)
- #define at_and AT_DECL(and)
- #define at_or AT_DECL(or)
- #define at_get_and_set AT_DECL(get_and_set)
- #define at_cmpxchg AT_DECL(cmpxchg)
- #define at_add AT_DECL(add)
- #define CHECK_ERR(txt, x, y) \
- if (x!=y) { \
- fprintf(stderr, "ERROR: line %d: %s failed: expected 0x%02x but got "\
- "0x%02x.\n", \
- __LINE__, #txt, (unsigned) x, (unsigned) y);\
- goto error; \
- }
- #define VERIFY(ops, y) \
- ops ; \
- CHECK_ERR( ops, y, get_val(v))
- int main(int argc, char** argv)
- {
- ATOMIC_TYPE var;
- VALUE_TYPE r;
- ATOMIC_TYPE* v;
- v=&var;
- #ifdef MEMBAR_USES_LOCK
- __membar_lock=&dummy_membar_lock;
- if (lock_init(__membar_lock)==0){
- fprintf(stderr, "ERROR: failed to initialize membar_lock\n");
- __membar_lock=0;
- goto error;
- }
- _membar_lock; /* start with the lock "taken" so that we can safely use
- unlock/lock sequences on it later */
- #endif
- #ifdef ATOMIC_OPS_USE_LOCK_SET
- /* init the lock (emulate atomic_ops.c) */
- dummy_atomic_lock_set.locks=&locks_array[0];
- _atomic_lock_set=&dummy_atomic_lock_set;
- if (lock_set_init(_atomic_lock_set)==0){
- fprintf(stderr, "ERROR: failed to initialize atomic_lock\n");
- _atomic_lock_set=0;
- goto error;
- }
- #elif defined ATOMIC_OPS_USE_LOCK
- /* init the lock (emulate atomic_ops.c) */
- _atomic_lock=&dummy_atomic_lock;
- if (lock_init(_atomic_lock)==0){
- fprintf(stderr, "ERROR: failed to initialize atomic_lock\n");
- _atomic_lock=0;
- goto error;
- }
- #endif
- printf("%s\n", flags);
- printf("starting memory barrier opcode tests...\n");
- membar();
- printf(" membar() .............................. ok\n");
- membar_write();
- printf(" membar_write() ........................ ok\n");
- membar_read();
- printf(" membar_read() ......................... ok\n");
- membar_depends();
- printf(" membar_depends() ...................... ok\n");
- membar_enter_lock();
- printf(" membar_enter_lock() ................... ok\n");
- membar_leave_lock();
- printf(" membar_leave_lock() ................... ok\n");
- membar_atomic_op();
- printf(" membar_atomic_op() .................... ok\n");
- membar_atomic_setget();
- printf(" membar_atomic_setget() ................ ok\n");
- membar_read_atomic_op();
- printf(" membar_read_atomic_op() ............... ok\n");
- membar_read_atomic_setget();
- printf(" membar_read_atomic_setget() ........... ok\n");
- membar_write_atomic_op();
- printf(" membar_write_atomic_op() .............. ok\n");
- membar_write_atomic_setget();
- printf(" membar_write_atomic_setget() .......... ok\n");
- printf("\nstarting atomic ops basic tests...\n");
- VERIFY(at_set(v, 1), 1);
- printf(" atomic_set, v should be 1 ............. %2d\n", (int)at_get(v));
- VERIFY(at_inc(v), 2);
- printf(" atomic_inc, v should be 2 ............. %2d\n", (int)at_get(v));
- VERIFY(r=at_inc_and_test(v), 3);
- printf(" atomic_inc_and_test, v should be 3 ... %2d\n", (int)at_get(v));
- printf(" r should be 0 ... %2d\n", (int)r);
- VERIFY(at_dec(v), 2);
- printf(" atomic_dec, v should be 2 ............. %2d\n", (int)at_get(v));
- VERIFY(r=at_dec_and_test(v), 1);
- printf(" atomic_dec_and_test, v should be 1 ... %2d\n", (int)at_get(v));
- printf(" r should be 0 ... %2d\n", (int)r);
- VERIFY(r=at_dec_and_test(v), 0);
- printf(" atomic_dec_and_test, v should be 0 ... %2d\n", (int)at_get(v));
- printf(" r should be 1 ... %2d\n", (int)r);
- VERIFY(r=at_dec_and_test(v), -1);
- printf(" atomic_dec_and_test, v should be -1 ... %2d\n", (int)at_get(v));
- printf(" r should be 0 ... %2d\n", (int)r);
- VERIFY(at_and(v, 2), 2);
- printf(" atomic_and, v should be 2 ............. %2d\n", (int)at_get(v));
- VERIFY(at_or(v, 5), 7);
- printf(" atomic_or, v should be 7 ............. %2d\n", (int)at_get(v));
- VERIFY(r=at_get_and_set(v, 0), 0);
- printf(" atomic_get_and_set, v should be 0 ..... %2d\n", (int)at_get(v));
- VERIFY(r=at_cmpxchg(v, 0, 7), 7);
- CHECK_ERR(cmpxchg, r, 0);
- printf(" atomic_cmpxchg, v should be 7 ......... %2d\n", (int)at_get(v));
- printf(" r should be 0 ......... %2d\n", (int)r);
- VERIFY(r=at_cmpxchg(v, 2, 3), 7);
- CHECK_ERR(cmpxchg, r, 7);
- printf(" atomic_cmpxchg (fail), v should be 7 .. %2d\n", (int)at_get(v));
- printf(" r should be 7 .. %2d\n", (int)r);
- VERIFY(r=at_add(v, 2), 9);
- CHECK_ERR(atomic_add, r, 9);
- printf(" atomic_add, v should be 9 ............. %2d\n", (int)at_get(v));
- printf(" r should be 9 ............. %2d\n", (int)r);
- VERIFY(r=at_add(v, -10), -1);
- CHECK_ERR(atomic_add, r, -1);
- printf(" atomic_add, v should be -1 ............ %2d\n", (int)at_get(v));
- printf(" r should be -1 ............ %2d\n", (int)r);
- printf("\ndone.\n");
- #ifdef MEMBAR_USES_LOCK
- lock_destroy(__membar_lock);
- #endif
- #ifdef ATOMIC_OPS_USE_LOCK_SET
- lock_set_destroy(_atomic_lock_set);
- #elif defined ATOMIC_OPS_USE_LOCK
- lock_destroy(_atomic_lock);
- #endif
- return 0;
- error:
- #ifdef MEMBAR_USES_LOCK
- if (__membar_lock)
- lock_destroy(__membar_lock);
- #endif
- #ifdef ATOMIC_OPS_USE_LOCK_SET
- if (_atomic_lock_set)
- lock_set_destroy(_atomic_lock_set);
- #elif defined ATOMIC_OPS_USE_LOCK
- if (_atomic_lock)
- lock_destroy(_atomic_lock);
- #endif
- return -1;
- }
|