Skip to content

Commit

Permalink
atomic.h: add 64-bit atomic operations
Browse files Browse the repository at this point in the history
  • Loading branch information
liviuchircu committed Mar 20, 2014
1 parent 66354d1 commit 5fbc82f
Showing 1 changed file with 90 additions and 7 deletions.
97 changes: 90 additions & 7 deletions atomic.h
Expand Up @@ -29,20 +29,16 @@
#define _ATOMIC_OPS_H_

/************************* i386 & x86_64 ARCH ****************************/
#if defined(__CPU_i386) || defined(__CPU_x86_64)

#if defined(__CPU_i386) || defined(__CPU_x86_64)
#if defined(__SMP_yes)
#define LOCK "lock ; "
#else
#define LOCK ""
#endif
#endif

/*! \brief
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
* not some alias that contains the same information.
*/
typedef struct { volatile unsigned int counter; } atomic_t;
#if defined(__CPU_i386)

/*! \brief
* atomic_set - set atomic variable
Expand All @@ -53,6 +49,13 @@ typedef struct { volatile unsigned int counter; } atomic_t;
*/
#define atomic_set(v,i) (((v)->counter) = (i))

/*! \brief
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
* not some alias that contains the same information.
*/
typedef struct { volatile unsigned int counter; } atomic_t;

/*! \brief
* atomic_add - add integer to atomic variable
* @i: integer value to add
Expand Down Expand Up @@ -110,9 +113,89 @@ static __inline__ void atomic_dec(atomic_t *v)
:"=m" (v->counter)
:"m" (v->counter));
}

#undef NO_ATOMIC_OPS

#elif defined(__CPU_x86_64) /* __CPU_i386 */

/*! \brief
* Make sure gcc doesn't try to be clever and move things around
* on us. We need to use _exactly_ the address the user gave us,
* not some alias that contains the same information.
*/
typedef struct { volatile unsigned long counter; } atomic_t;

/*! \brief
* atomic_set - set atomic variable
* @v: pointer of type atomic_t
* @i: required value
*
* Atomically sets the value of @v to @i.
*/
#define atomic_set(v,i) (((v)->counter) = (i))

/*! \brief
* atomic_add - add integer to atomic variable
* @i: integer value to add
* @v: pointer of type atomic_t
*
* Atomically adds @i to @v.
*/
static __inline__ void atomic_add(unsigned long i, atomic_t *v)
{
__asm__ __volatile__(
LOCK "addq %1,%0"
:"=m" (v->counter)
:"er" (i), "m" (v->counter));
}

/*! \brief
* atomic_sub - subtract the atomic variable
* @i: integer value to subtract
* @v: pointer of type atomic_t
*
* Atomically subtracts @i from @v.
*/
static __inline__ void atomic_sub(unsigned long i, atomic_t *v)
{
__asm__ __volatile__(
LOCK "subq %1,%0"
:"=m" (v->counter)
:"er" (i), "m" (v->counter));
}

/*! \brief
* atomic_inc - increment atomic variable
* @v: pointer of type atomic_t
*
* Atomically increments @v by 1.
*/
static __inline__ void atomic_inc(atomic_t *v)
{
__asm__ __volatile__(
LOCK "incq %0"
:"=m" (v->counter)
:"m" (v->counter));
}

/*! \brief
* atomic_dec - decrement atomic variable
* @v: pointer of type atomic_t
*
* Atomically decrements @v by 1.
*/
static __inline__ void atomic_dec(atomic_t *v)
{
__asm__ __volatile__(
LOCK "decq %0"
:"=m" (v->counter)
:"m" (v->counter));
}

#undef NO_ATOMIC_OPS

/************************* other ARCH ****************************/

#else

#define NO_ATOMIC_OPS
Expand Down

0 comments on commit 5fbc82f

Please sign in to comment.