Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 14075
b: refs/heads/master
c: 8426e1f
h: refs/heads/master
i:
  14073: 3aecce8
  14071: 7c6e6f9
v: v3
  • Loading branch information
Nick Piggin authored and Linus Torvalds committed Nov 14, 2005
1 parent 91fd013 commit aef8e5e
Show file tree
Hide file tree
Showing 24 changed files with 322 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4a6dae6d382e9edf3ff440b819e554ed706359bc
refs/heads/master: 8426e1f6af0fd7f44d040af7263750c5a52f3cc3
14 changes: 13 additions & 1 deletion trunk/Documentation/atomic_ops.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ boolean is return which indicates whether the resulting counter value
is negative. It requires explicit memory barrier semantics around the
operation.

Finally:
Then:

int atomic_cmpxchg(atomic_t *v, int old, int new);

Expand All @@ -129,6 +129,18 @@ atomic_cmpxchg requires explicit memory barriers around the operation.
The semantics for atomic_cmpxchg are the same as those defined for 'cas'
below.

Finally:

int atomic_add_unless(atomic_t *v, int a, int u);

If the atomic value v is not equal to u, this function adds a to v, and
returns non zero. If v is equal to u then it returns zero. This is done as
an atomic operation.

atomic_add_unless requires explicit memory barriers around the operation.

atomic_inc_not_zero, equivalent to atomic_add_unless(v, 1, 0)


If a caller requires memory barrier semantics around an atomic_t
operation which does not return a value, a set of interfaces are
Expand Down
15 changes: 15 additions & 0 deletions trunk/arch/sparc/lib/atomic32.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}

int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;

spin_lock_irqsave(ATOMIC_HASH(v), flags);
ret = v->counter;
if (ret != u)
v->counter += a;
spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
return ret != u;
}

static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
/* Atomic operations are already serializing */
void atomic_set(atomic_t *v, int i)
{
unsigned long flags;
Expand Down
10 changes: 10 additions & 0 deletions trunk/include/asm-alpha/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,16 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)

#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))

#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic64_dec_return(v) atomic64_sub_return(1,(v))

Expand Down
11 changes: 11 additions & 0 deletions trunk/include/asm-arm/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,17 @@ static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)

#endif /* __LINUX_ARM_ARCH__ */

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int c, old;

c = atomic_read(v);
while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
c = old;
return c != u;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_add(i, v) (void) atomic_add_return(i, v)
#define atomic_inc(v) (void) atomic_add_return(1, v)
#define atomic_sub(i, v) (void) atomic_sub_return(i, v)
Expand Down
15 changes: 15 additions & 0 deletions trunk/include/asm-arm26/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;

local_irq_save(flags);
ret = v->counter;
if (ret != u)
v->counter += a;
local_irq_restore(flags);

return ret != u;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
{
unsigned long flags;
Expand Down
14 changes: 14 additions & 0 deletions trunk/include/asm-cris/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,20 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;

cris_atomic_save(v, flags);
ret = v->counter;
if (ret != u)
v->counter += a;
cris_atomic_restore(v, flags);
return ret != u;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
Expand Down
10 changes: 10 additions & 0 deletions trunk/include/asm-frv/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,4 +416,14 @@ extern uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new);

#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))

#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#endif /* _ASM_ATOMIC_H */
14 changes: 14 additions & 0 deletions trunk/include/asm-h8300/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;

local_irq_save(flags);
ret = v->counter;
if (ret != u)
v->counter += a;
local_irq_restore(flags);
return ret != u;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *v)
{
__asm__ __volatile__("stc ccr,r1l\n\t"
Expand Down
19 changes: 19 additions & 0 deletions trunk/include/asm-i386/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,25 @@ static __inline__ int atomic_sub_return(int i, atomic_t *v)

#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))

/**
* atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
* Returns non-zero if @v was not @u, and zero otherwise.
*/
#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_inc_return(v) (atomic_add_return(1,v))
#define atomic_dec_return(v) (atomic_sub_return(1,v))

Expand Down
10 changes: 10 additions & 0 deletions trunk/include/asm-ia64/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,16 @@ ia64_atomic64_sub (__s64 i, atomic64_t *v)

#define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))

#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_add_return(i,v) \
({ \
int __ia64_aar_i = (i); \
Expand Down
10 changes: 10 additions & 0 deletions trunk/include/asm-m68k/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,16 @@ static inline void atomic_set_mask(unsigned long mask, unsigned long *v)

#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))

#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

/* Atomic operations are already serializing */
#define smp_mb__before_atomic_dec() barrier()
#define smp_mb__after_atomic_dec() barrier()
Expand Down
10 changes: 10 additions & 0 deletions trunk/include/asm-m68knommu/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ static inline int atomic_sub_return(int i, atomic_t * v)

#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))

#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic_inc_return(v) atomic_add_return(1,(v))

Expand Down
19 changes: 19 additions & 0 deletions trunk/include/asm-mips/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,25 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)

#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))

/**
* atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
* Returns non-zero if @v was not @u, and zero otherwise.
*/
#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_dec_return(v) atomic_sub_return(1,(v))
#define atomic_inc_return(v) atomic_add_return(1,(v))

Expand Down
19 changes: 19 additions & 0 deletions trunk/include/asm-parisc/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,25 @@ static __inline__ int atomic_read(const atomic_t *v)
/* exported interface */
#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))

/**
* atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
* Returns non-zero if @v was not @u, and zero otherwise.
*/
#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_add(i,v) ((void)(__atomic_add_return( ((int)i),(v))))
#define atomic_sub(i,v) ((void)(__atomic_add_return(-((int)i),(v))))
#define atomic_inc(v) ((void)(__atomic_add_return( 1,(v))))
Expand Down
25 changes: 25 additions & 0 deletions trunk/include/asm-powerpc/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,31 @@ static __inline__ int atomic_dec_return(atomic_t *v)

#define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))

/**
* atomic_add_unless - add unless the number is a given value
* @v: pointer of type atomic_t
* @a: the amount to add to v...
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
* Returns non-zero if @v was not @u, and zero otherwise.
*/
#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
for (;;) { \
if (unlikely(c == (u))) \
break; \
old = atomic_cmpxchg((v), c, c + (a)); \
if (likely(old == c)) \
break; \
c = old; \
} \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define atomic_sub_and_test(a, v) (atomic_sub_return((a), (v)) == 0)
#define atomic_dec_and_test(v) (atomic_dec_return((v)) == 0)

Expand Down
10 changes: 10 additions & 0 deletions trunk/include/asm-s390/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,16 @@ atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)

#define atomic_cmpxchg(v, o, n) (atomic_compare_and_swap((o), (n), &((v)->counter)))

#define atomic_add_unless(v, a, u) \
({ \
int c, old; \
c = atomic_read(v); \
while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
c = old; \
c != (u); \
})
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

#define smp_mb__before_atomic_dec() smp_mb()
#define smp_mb__after_atomic_dec() smp_mb()
#define smp_mb__before_atomic_inc() smp_mb()
Expand Down
15 changes: 15 additions & 0 deletions trunk/include/asm-sh/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,21 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;

local_irq_save(flags);
ret = v->counter;
if (ret != u)
v->counter += a;
local_irq_restore(flags);

return ret != u;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
{
unsigned long flags;
Expand Down
15 changes: 15 additions & 0 deletions trunk/include/asm-sh64/atomic.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,21 @@ static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
return ret;
}

static inline int atomic_add_unless(atomic_t *v, int a, int u)
{
int ret;
unsigned long flags;

local_irq_save(flags);
ret = v->counter;
if (ret != u)
v->counter += a;
local_irq_restore(flags);

return ret != u;
}
#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)

static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
{
unsigned long flags;
Expand Down
Loading

0 comments on commit aef8e5e

Please sign in to comment.