You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/test/atomic_test2.c

302 lines
8.7 KiB

/*
*
* simple atomic ops testing program
* (no paralel 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;
}