mirror of https://github.com/sipwise/kamailio.git
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.
302 lines
8.7 KiB
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;
|
|
}
|