#ifndef _LINUX_ATOMIC_H_
#define _LINUX_ATOMIC_H_


typedef struct { volatile int aVal; } atomic_t;

#define INIT_ATOMIC_VALUE(c) { (c) }

#define atomic_dec_and_test(p) (atomic_dec((p)) == 0)

#define atomic_read(p) ((p)->aVal)


#if defined ( X86 ) || defined(__x86__)

static __inline__ int atomic_inc (atomic_t * pCount)
{
	int  nCount;

	__asm__ __volatile__ (
		"movl $1, %0\n\t"
		"lock\n\t" 
		"xadd %0, %2\n\t"
		"incl %0"
	:	"=&r" (nCount), "=m" (pCount->aVal)
	:	"m" (pCount->aVal)
	:	"memory");

    return nCount;
}

static __inline__ int atomic_dec(atomic_t * pCount)
{
	int nCount;

	__asm__ __volatile__ (
		"movl $-1, %0\n\t"
		"lock\n\t"
		"xadd %0, %2\n\t"
		"decl %0"
	:	"=&r" (nCount), "=m" (pCount->aVal)
	:	"m" (pCount->aVal)
	:	"memory");

    return nCount;
}

#elif defined ( POWERPC ) || defined(__powerpc__) || defined (ppc)

static __inline__ int atomic_inc(atomic_t * pCount)
{
	int nCount;

	__asm__ __volatile__ (
		"1: lwarx   %0,0,%2\n\t"
		"   addic   %0,%0,1\n\t"
		"   stwcx.  %0,0,%2\n\t"
		"   bne-    1b\n\t"
                "   sync"
		: "=&r" (nCount), "=m" (pCount->aVal)
		: "r" (pCount), "m" (pCount->aVal)
		: "cc");

	return nCount;
}


static __inline__ int atomic_dec(atomic_t * pCount)
{
	int  nCount;

	__asm__ __volatile__ (
		"1: lwarx   %0,0,%2\n\t"
		"   subic   %0,%0,1\n\t"
		"   stwcx.  %0,0,%2\n\t"
		"   bne-    1b\n\t"
		"   sync"
		: "=&r" (nCount), "=m" (pCount->aVal)
		: "r" (pCount), "m" (pCount->aVal)
		: "cc");

	return nCount;
}


#elif defined(__s390__)

#define __CS_LOOP(old_val, new_val, ptr, op_val, op_string)		\
       __asm__ __volatile__("   l     %0,0(%2)\n"			\
                            "0: lr    %1,%0\n"			\
                            op_string "  %1,%3\n"			\
                            "   cs    %0,%1,0(%2)\n"			\
                            "   jl    0b"				\
                            : "=&d" (old_val), "=&d" (new_val)		\
		     : "a" (ptr), "d" (op_val) : "cc" );

static __inline__ int atomic_inc(volatile atomic_t *v)
{
int old_val, new_val;
__CS_LOOP(old_val, new_val, v, 1, "ar");
       return new_val;
}


static __inline__ int atomic_dec(volatile atomic_t *v)
{
int old_val, new_val;
__CS_LOOP(old_val, new_val, v, 1, "sr");
       return new_val;
}
#elif defined ( SPARC )


#define atomic_set(v, i)	(((v)->aVal) = ((i) << 8))

static __inline__ int __atomic_add(int i, atomic_t *v)
{
register volatile int *ptr asm("g1");
register int increment asm("g2");

ptr = &v->aVal;
increment = i;

__asm__ __volatile__(
"mov	%%o7, %%g4\n\t"
"call	___atomic_add\n\t"
" add	%%o7, 8, %%o7\n"
: "=&r" (increment)
: "0" (increment), "r" (ptr)
: "g3", "g4", "g7", "memory", "cc");

return increment;
}

static __inline__ int __atomic_sub(int i, atomic_t *v)
{
register volatile int *ptr asm("g1");
register int increment asm("g2");

ptr = &v->aVal;
increment = i;

__asm__ __volatile__(
"mov	%%o7, %%g4\n\t"
"call	___atomic_sub\n\t"
" add	%%o7, 8, %%o7\n"
: "=&r" (increment)
: "0" (increment), "r" (ptr)
: "g3", "g4", "g7", "memory", "cc");

return increment;
}

#define atomic_add(i, v) ((void)__atomic_add((i), (v)))
#define atomic_sub(i, v) ((void)__atomic_sub((i), (v)))

#define atomic_dec_return(v) __atomic_sub(1, (v))
#define atomic_inc_return(v) __atomic_add(1, (v))

#define atomic_sub_and_test(i, v) (__atomic_sub((i), (v)) == 0)
#define atomic_dec_and_test(v) (__atomic_sub(1, (v)) == 0)

#define atomic_inc(v) ((void)__atomic_add(1, (v)))
#define atomic_dec(v) ((void)__atomic_sub(1, (v)))

#define atomic_add_negative(i, v) (__atomic_add((i), (v)) < 0)

/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec()	barrier()
#define smp_mb__after_atomic_dec()	barrier()
#define smp_mb__before_atomic_inc()	barrier()
#define smp_mb__after_atomic_inc()	barrier()

#endif
#else

#error - need to define your processors atomic inc and dec here

#endif


