#ifndef RTATOMIC_H
#define RTATOMIC_H
#define SMP
#include <asm/atomic.h>

/******************************************************************************/
/******************************************************************************/
/*****************     Copyright 2004, 2005 Chronolytics Inc.   ***************/
/*****************     All Right Reserved                       ***************/
/******************************************************************************/
/******************************************************************************/

static volatile const char __attribute__ ((unused)) rcsid_RTATOMIC_H[] = "$Id: RTAtomic.h,v 1.6 2005/08/20 21:39:25 dave Exp $";


/**
 * [User usable] Atomic compare and swap.
 *
 * @value     Pointer to the value to compare and swap.
 * @old_value Value that *value has to have for the swap to occur.
 * @new_value New value to set it *value == old_value.
 * @return    !0 if the swap succeeded. 0 if failed.
 */
static __inline__
unsigned RTAtomic_CompareAndSwap (volatile unsigned *value,
		       unsigned old_value, unsigned new_value)
{
	unsigned result;
	asm __volatile__ (
		"lock cmpxchg %3, %1"
		: "=a" (result), "+m" ((*value))
		: "a" (old_value), "r" (new_value)
		: "memory");
	return result == old_value;
}

/* this function is in atomic.h in 2.6, but not everyone has that */
#ifndef RTAtomic_Incr_Return
#define RTAtomic_Incr_Return(v)  (RTAtomic_Add_Return(1,v))

static __inline__ int RTAtomic_Add_Return(int i, volatile unsigned int *p)
   {
   int __i = i;
   struct atomic { volatile int counter; } *v =  (struct atomic *) p;
   __asm__ __volatile__(
     "lock xaddl %0, %1;"
     :"=r"(i)
     :"m"(v->counter), "0"(i));
     return i + __i;
}
#endif /* atomic_inc_return */

struct __xchg_dummy { unsigned long a[100]; };  /* magic */
#define __xg(x) ((struct __xchg_dummy *)(x))

  /* swap value and memory atomically */
static __inline__ unsigned long RTAtomic_AtomicSwap(volatile unsigned long *p, unsigned long v)
   {
    __asm__ __volatile__ ("lock xchgl %0,%1"
                :"=r" (v)
                :"m" (*__xg(p)), "0" (v)
                :"memory");
   return v;

}

static __inline__ void * RTAtomic_AtomicSwapPointer(volatile void *p, void *value)
   {
    __asm__ __volatile__ ("lock xchgl %0,%1"
                :"=r" (value)
                :"m" (*__xg(p)), "0" (value)
                :"memory");
   return value;

}

#endif /* RTATOMIC_H */

