2010-05-29 07:09:12 +04:00
|
|
|
/*
|
|
|
|
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation, version 2.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
|
|
|
* NON INFRINGEMENT. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* Atomic primitives.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _ASM_TILE_ATOMIC_H
|
|
|
|
#define _ASM_TILE_ATOMIC_H
|
|
|
|
|
2012-04-02 00:38:46 +04:00
|
|
|
#include <asm/cmpxchg.h>
|
|
|
|
|
2010-05-29 07:09:12 +04:00
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
|
|
|
|
#include <linux/compiler.h>
|
2012-03-28 21:30:03 +04:00
|
|
|
#include <linux/types.h>
|
2010-05-29 07:09:12 +04:00
|
|
|
|
|
|
|
#define ATOMIC_INIT(i) { (i) }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_read - read atomic variable
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically reads the value of @v.
|
|
|
|
*/
|
|
|
|
static inline int atomic_read(const atomic_t *v)
|
|
|
|
{
|
2015-09-18 12:13:10 +03:00
|
|
|
return READ_ONCE(v->counter);
|
2010-05-29 07:09:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_sub_return - subtract integer and return
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
* @i: integer value to subtract
|
|
|
|
*
|
|
|
|
* Atomically subtracts @i from @v and returns @v - @i
|
|
|
|
*/
|
|
|
|
#define atomic_sub_return(i, v) atomic_add_return((int)(-(i)), (v))
|
|
|
|
|
2016-04-18 02:16:03 +03:00
|
|
|
#define atomic_fetch_sub(i, v) atomic_fetch_add(-(int)(i), (v))
|
|
|
|
|
2010-05-29 07:09:12 +04:00
|
|
|
/**
|
|
|
|
* atomic_sub - subtract integer from atomic variable
|
|
|
|
* @i: integer value to subtract
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically subtracts @i from @v.
|
|
|
|
*/
|
|
|
|
#define atomic_sub(i, v) atomic_add((int)(-(i)), (v))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_sub_and_test - subtract value from variable and test result
|
|
|
|
* @i: integer value to subtract
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically subtracts @i from @v and returns true if the result is
|
|
|
|
* zero, or false for all other cases.
|
|
|
|
*/
|
|
|
|
#define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_inc_return - increment memory and return
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically increments @v by 1 and returns the new value.
|
|
|
|
*/
|
|
|
|
#define atomic_inc_return(v) atomic_add_return(1, (v))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_dec_return - decrement memory and return
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically decrements @v by 1 and returns the new value.
|
|
|
|
*/
|
|
|
|
#define atomic_dec_return(v) atomic_sub_return(1, (v))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_inc - increment atomic variable
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically increments @v by 1.
|
|
|
|
*/
|
|
|
|
#define atomic_inc(v) atomic_add(1, (v))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_dec - decrement atomic variable
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically decrements @v by 1.
|
|
|
|
*/
|
|
|
|
#define atomic_dec(v) atomic_sub(1, (v))
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_dec_and_test - decrement and test
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically decrements @v by 1 and returns true if the result is 0.
|
|
|
|
*/
|
|
|
|
#define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_inc_and_test - increment and test
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
*
|
|
|
|
* Atomically increments @v by 1 and returns true if the result is 0.
|
|
|
|
*/
|
|
|
|
#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
|
|
|
|
|
tile: rework <asm/cmpxchg.h>
The macrology in cmpxchg.h was designed to allow arbitrary pointer
and integer values to be passed through the routines. To support
cmpxchg() on 64-bit values on the 32-bit tilepro architecture, we
used the idiom "(typeof(val))(typeof(val-val))". This way, in the
"size 8" branch of the switch, when the underlying cmpxchg routine
returns a 64-bit quantity, we cast it first to a typeof(val-val)
quantity (i.e. size_t if "val" is a pointer) with no warnings about
casting between pointers and integers of different sizes, then cast
onwards to typeof(val), again with no warnings. If val is not a
pointer type, the additional cast is a no-op. We can't replace the
typeof(val-val) cast with (for example) unsigned long, since then if
"val" is really a 64-bit type, we cast away the high bits.
HOWEVER, this fails with current gcc (through 4.7 at least) if "val"
is a pointer to an incomplete type. Unfortunately gcc isn't smart
enough to realize that "val - val" will always be a size_t type
even if it's an incomplete type pointer.
Accordingly, I've reworked the way we handle the casting. We have
given up the ability to use cmpxchg() on 64-bit values on tilepro,
which is OK in the kernel since we should use cmpxchg64() explicitly
on such values anyway. As a result, I can just use simple "unsigned
long" casts internally.
As I reworked it, I realized it would be cleaner to move the
architecture-specific conditionals for cmpxchg and xchg out of the
atomic.h headers and into cmpxchg, and then use the cmpxchg() and
xchg() primitives directly in atomic.h and elsewhere. This allowed
the cmpxchg.h header to stand on its own without relying on the
implicit include of it that is performed by <asm/atomic.h>.
It also allowed collapsing the atomic_xchg/atomic_cmpxchg routines
from atomic_{32,64}.h into atomic.h.
I improved the tests that guard the allowed size of the arguments
to the routines to use a __compiletime_error() test. (By avoiding
the use of BUILD_BUG, I could include cmpxchg.h into bitops.h as
well and use the macros there, which is otherwise impossible due
to include order dependency issues.)
The tilepro _atomic_xxx internal methods were previously set up to
take atomic_t and atomic64_t arguments, which isn't as convenient
with the new model, so I modified them to take int or u64 arguments,
which is consistent with how they used the arguments internally
anyway, so provided some nice simplification there too.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2013-09-06 16:56:45 +04:00
|
|
|
/**
|
|
|
|
* atomic_xchg - atomically exchange contents of memory with a new value
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
* @i: integer value to store in memory
|
|
|
|
*
|
|
|
|
* Atomically sets @v to @i and returns old @v
|
|
|
|
*/
|
|
|
|
static inline int atomic_xchg(atomic_t *v, int n)
|
|
|
|
{
|
|
|
|
return xchg(&v->counter, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic_cmpxchg - atomically exchange contents of memory if it matches
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
* @o: old value that memory should have
|
|
|
|
* @n: new value to write to memory if it matches
|
|
|
|
*
|
|
|
|
* Atomically checks if @v holds @o and replaces it with @n if so.
|
|
|
|
* Returns the old value at @v.
|
|
|
|
*/
|
|
|
|
static inline int atomic_cmpxchg(atomic_t *v, int o, int n)
|
|
|
|
{
|
|
|
|
return cmpxchg(&v->counter, o, n);
|
|
|
|
}
|
|
|
|
|
2010-05-29 07:09:12 +04:00
|
|
|
/**
|
|
|
|
* atomic_add_negative - add and test if negative
|
|
|
|
* @v: pointer of type atomic_t
|
|
|
|
* @i: integer value to add
|
|
|
|
*
|
|
|
|
* Atomically adds @i to @v and returns true if the result is
|
|
|
|
* negative, or false when result is greater than or equal to zero.
|
|
|
|
*/
|
|
|
|
#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0)
|
|
|
|
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
|
|
|
|
#ifndef __tilegx__
|
|
|
|
#include <asm/atomic_32.h>
|
|
|
|
#else
|
|
|
|
#include <asm/atomic_64.h>
|
|
|
|
#endif
|
|
|
|
|
2013-02-01 21:37:48 +04:00
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
|
tile: rework <asm/cmpxchg.h>
The macrology in cmpxchg.h was designed to allow arbitrary pointer
and integer values to be passed through the routines. To support
cmpxchg() on 64-bit values on the 32-bit tilepro architecture, we
used the idiom "(typeof(val))(typeof(val-val))". This way, in the
"size 8" branch of the switch, when the underlying cmpxchg routine
returns a 64-bit quantity, we cast it first to a typeof(val-val)
quantity (i.e. size_t if "val" is a pointer) with no warnings about
casting between pointers and integers of different sizes, then cast
onwards to typeof(val), again with no warnings. If val is not a
pointer type, the additional cast is a no-op. We can't replace the
typeof(val-val) cast with (for example) unsigned long, since then if
"val" is really a 64-bit type, we cast away the high bits.
HOWEVER, this fails with current gcc (through 4.7 at least) if "val"
is a pointer to an incomplete type. Unfortunately gcc isn't smart
enough to realize that "val - val" will always be a size_t type
even if it's an incomplete type pointer.
Accordingly, I've reworked the way we handle the casting. We have
given up the ability to use cmpxchg() on 64-bit values on tilepro,
which is OK in the kernel since we should use cmpxchg64() explicitly
on such values anyway. As a result, I can just use simple "unsigned
long" casts internally.
As I reworked it, I realized it would be cleaner to move the
architecture-specific conditionals for cmpxchg and xchg out of the
atomic.h headers and into cmpxchg, and then use the cmpxchg() and
xchg() primitives directly in atomic.h and elsewhere. This allowed
the cmpxchg.h header to stand on its own without relying on the
implicit include of it that is performed by <asm/atomic.h>.
It also allowed collapsing the atomic_xchg/atomic_cmpxchg routines
from atomic_{32,64}.h into atomic.h.
I improved the tests that guard the allowed size of the arguments
to the routines to use a __compiletime_error() test. (By avoiding
the use of BUILD_BUG, I could include cmpxchg.h into bitops.h as
well and use the macros there, which is otherwise impossible due
to include order dependency issues.)
The tilepro _atomic_xxx internal methods were previously set up to
take atomic_t and atomic64_t arguments, which isn't as convenient
with the new model, so I modified them to take int or u64 arguments,
which is consistent with how they used the arguments internally
anyway, so provided some nice simplification there too.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2013-09-06 16:56:45 +04:00
|
|
|
/**
|
|
|
|
* atomic64_xchg - atomically exchange contents of memory with a new value
|
|
|
|
* @v: pointer of type atomic64_t
|
|
|
|
* @i: integer value to store in memory
|
|
|
|
*
|
|
|
|
* Atomically sets @v to @i and returns old @v
|
|
|
|
*/
|
2013-09-25 08:14:08 +04:00
|
|
|
static inline long long atomic64_xchg(atomic64_t *v, long long n)
|
tile: rework <asm/cmpxchg.h>
The macrology in cmpxchg.h was designed to allow arbitrary pointer
and integer values to be passed through the routines. To support
cmpxchg() on 64-bit values on the 32-bit tilepro architecture, we
used the idiom "(typeof(val))(typeof(val-val))". This way, in the
"size 8" branch of the switch, when the underlying cmpxchg routine
returns a 64-bit quantity, we cast it first to a typeof(val-val)
quantity (i.e. size_t if "val" is a pointer) with no warnings about
casting between pointers and integers of different sizes, then cast
onwards to typeof(val), again with no warnings. If val is not a
pointer type, the additional cast is a no-op. We can't replace the
typeof(val-val) cast with (for example) unsigned long, since then if
"val" is really a 64-bit type, we cast away the high bits.
HOWEVER, this fails with current gcc (through 4.7 at least) if "val"
is a pointer to an incomplete type. Unfortunately gcc isn't smart
enough to realize that "val - val" will always be a size_t type
even if it's an incomplete type pointer.
Accordingly, I've reworked the way we handle the casting. We have
given up the ability to use cmpxchg() on 64-bit values on tilepro,
which is OK in the kernel since we should use cmpxchg64() explicitly
on such values anyway. As a result, I can just use simple "unsigned
long" casts internally.
As I reworked it, I realized it would be cleaner to move the
architecture-specific conditionals for cmpxchg and xchg out of the
atomic.h headers and into cmpxchg, and then use the cmpxchg() and
xchg() primitives directly in atomic.h and elsewhere. This allowed
the cmpxchg.h header to stand on its own without relying on the
implicit include of it that is performed by <asm/atomic.h>.
It also allowed collapsing the atomic_xchg/atomic_cmpxchg routines
from atomic_{32,64}.h into atomic.h.
I improved the tests that guard the allowed size of the arguments
to the routines to use a __compiletime_error() test. (By avoiding
the use of BUILD_BUG, I could include cmpxchg.h into bitops.h as
well and use the macros there, which is otherwise impossible due
to include order dependency issues.)
The tilepro _atomic_xxx internal methods were previously set up to
take atomic_t and atomic64_t arguments, which isn't as convenient
with the new model, so I modified them to take int or u64 arguments,
which is consistent with how they used the arguments internally
anyway, so provided some nice simplification there too.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2013-09-06 16:56:45 +04:00
|
|
|
{
|
|
|
|
return xchg64(&v->counter, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* atomic64_cmpxchg - atomically exchange contents of memory if it matches
|
|
|
|
* @v: pointer of type atomic64_t
|
|
|
|
* @o: old value that memory should have
|
|
|
|
* @n: new value to write to memory if it matches
|
|
|
|
*
|
|
|
|
* Atomically checks if @v holds @o and replaces it with @n if so.
|
|
|
|
* Returns the old value at @v.
|
|
|
|
*/
|
2013-09-25 08:14:08 +04:00
|
|
|
static inline long long atomic64_cmpxchg(atomic64_t *v, long long o,
|
|
|
|
long long n)
|
tile: rework <asm/cmpxchg.h>
The macrology in cmpxchg.h was designed to allow arbitrary pointer
and integer values to be passed through the routines. To support
cmpxchg() on 64-bit values on the 32-bit tilepro architecture, we
used the idiom "(typeof(val))(typeof(val-val))". This way, in the
"size 8" branch of the switch, when the underlying cmpxchg routine
returns a 64-bit quantity, we cast it first to a typeof(val-val)
quantity (i.e. size_t if "val" is a pointer) with no warnings about
casting between pointers and integers of different sizes, then cast
onwards to typeof(val), again with no warnings. If val is not a
pointer type, the additional cast is a no-op. We can't replace the
typeof(val-val) cast with (for example) unsigned long, since then if
"val" is really a 64-bit type, we cast away the high bits.
HOWEVER, this fails with current gcc (through 4.7 at least) if "val"
is a pointer to an incomplete type. Unfortunately gcc isn't smart
enough to realize that "val - val" will always be a size_t type
even if it's an incomplete type pointer.
Accordingly, I've reworked the way we handle the casting. We have
given up the ability to use cmpxchg() on 64-bit values on tilepro,
which is OK in the kernel since we should use cmpxchg64() explicitly
on such values anyway. As a result, I can just use simple "unsigned
long" casts internally.
As I reworked it, I realized it would be cleaner to move the
architecture-specific conditionals for cmpxchg and xchg out of the
atomic.h headers and into cmpxchg, and then use the cmpxchg() and
xchg() primitives directly in atomic.h and elsewhere. This allowed
the cmpxchg.h header to stand on its own without relying on the
implicit include of it that is performed by <asm/atomic.h>.
It also allowed collapsing the atomic_xchg/atomic_cmpxchg routines
from atomic_{32,64}.h into atomic.h.
I improved the tests that guard the allowed size of the arguments
to the routines to use a __compiletime_error() test. (By avoiding
the use of BUILD_BUG, I could include cmpxchg.h into bitops.h as
well and use the macros there, which is otherwise impossible due
to include order dependency issues.)
The tilepro _atomic_xxx internal methods were previously set up to
take atomic_t and atomic64_t arguments, which isn't as convenient
with the new model, so I modified them to take int or u64 arguments,
which is consistent with how they used the arguments internally
anyway, so provided some nice simplification there too.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
2013-09-06 16:56:45 +04:00
|
|
|
{
|
|
|
|
return cmpxchg64(&v->counter, o, n);
|
|
|
|
}
|
|
|
|
|
2013-02-01 21:37:48 +04:00
|
|
|
static inline long long atomic64_dec_if_positive(atomic64_t *v)
|
|
|
|
{
|
|
|
|
long long c, old, dec;
|
|
|
|
|
|
|
|
c = atomic64_read(v);
|
|
|
|
for (;;) {
|
|
|
|
dec = c - 1;
|
|
|
|
if (unlikely(dec < 0))
|
|
|
|
break;
|
|
|
|
old = atomic64_cmpxchg((v), c, dec);
|
|
|
|
if (likely(old == c))
|
|
|
|
break;
|
|
|
|
c = old;
|
|
|
|
}
|
|
|
|
return dec;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __ASSEMBLY__ */
|
|
|
|
|
2010-05-29 07:09:12 +04:00
|
|
|
#endif /* _ASM_TILE_ATOMIC_H */
|