Remove local_t
v2 cover Remove local_t
Current -next has only the trace subsystem left as a user of local_t
Tracing uses local_t for per cpu safe atomic operations in the form of cmpxchg and additions.
This patchset removes unused function in local.h and then genericizes local.h by removing local_t. This results in a very small set of functions.
"long" is used for now instead of local_t. With some additional work it would be possible to pass arbitrary types to local_xx() function like cmpxchg_local() and the this_cpu_xx() functions. Maybe a more flexible way of handling local_xx() would allow the use of these functions in other kernel subsystems.
Still RFC state. Lots of stuff todo. Compiles on my box.
V1->V2
- Preserve local.h
- Add a rationale why the remaining functions are useful and how they differ from this_cpu_xx.
RFC v2 1/3 Remove unused local.h functions
The ringbuffer logic is the last user of local.h and it uses only the following functions and types:
local_t
local_set()local_read()
local_add_return()local_add()local_sub()local_inc()local_dec()
local_cmpxchg()
Keep those and remove all other local.h functions
--- arch/alpha/include/asm/local.h | 61 ------------- arch/m32r/include/asm/local.h | 181 --------------------------------------- arch/mips/include/asm/local.h | 120 ------------------------- arch/powerpc/include/asm/local.h | 133 ---------------------------- arch/x86/include/asm/local.h | 118 ------------------------- include/asm-generic/local.h | 16 --- 6 files changed, 3 insertions(+), 626 deletions(-)
arch/powerpc/include/asm/local.h +0 -133
@@ -36,140 +36,7 @@ static __inline__ long local_add_return( return t; } -#define local_add_negative (a, l) (local_add_return((a), (l)) < 0) - -static __inline__long local_sub_return (long a,local_t *l) -{ -long t; - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%2 # local_sub_return\n\ -subf %0,%1,%0\n" - PPC405_ERR77(0,%2) - PPC_STLCX "%0,0,%2 \n\ - bne- 1b" - : "=&r" (t) - : "r" (a), "r" (&(l->a.counter)) - : "cc", "memory"); - -return t; -} - -static __inline__long local_inc_return (local_t *l) -{ -long t; - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%1 # local_inc_return\n\ -addic %0,%0,1\n" - PPC405_ERR77(0,%1) - PPC_STLCX "%0,0,%1 \n\ - bne- 1b" - : "=&r" (t) - : "r" (&(l->a.counter)) - : "cc", "xer", "memory"); - -return t; -} - -/* -* local_inc_and_test - increment and test -* @l: pointer of type local_t -* -* Atomically increments @l by 1 -* and returns true if the result is zero, or false for all -* other cases. -*/ -#define local_inc_and_test (l) (local_inc_return(l) == 0) - -static __inline__long local_dec_return (local_t *l) -{ -long t; - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%1 # local_dec_return\n\ -addic %0,%0,-1\n" - PPC405_ERR77(0,%1) - PPC_STLCX "%0,0,%1\n\ - bne- 1b" - : "=&r" (t) - : "r" (&(l->a.counter)) - : "cc", "xer", "memory"); - -return t; -} -#define local_cmpxchg (l, o, n) \ (cmpxchg_local(&((l)->a.counter), (o), (n))) -#define local_xchg (l, n) (xchg_local(&((l)->a.counter), (n))) - -/** -* local_add_unless - add unless the number is a given value -* @l: pointer of type local_t -* @a: the amount to add to v... -* @u: ...unless v is equal to u. -* -* Atomically adds @a to @l, so long as it was not @u. -* Returns non-zero if @l was not @u, and zero otherwise. -*/ -static __inline__int local_add_unless (local_t *l,long a,long u) -{ -long t; - - __asm__ __volatile__ ( -"1:" PPC_LLARX "%0,0,%1 # local_add_unless\n\ -cmpw 0,%0,%3 \n\ -beq- 2f \n\ -add %0,%2,%0 \n" - PPC405_ERR77(0,%2) -PPC_STLCX "%0,0,%1 \n\ -bne- 1b \n" -" subf %0,%2,%0 \n\ -2:" - : "=&r" (t) - : "r" (&(l->a.counter)), "r" (a), "r" (u) - : "cc", "memory"); - - return t != u; -} - -#define local_inc_not_zero (l) local_add_unless((l), 1, 0) - -#define local_sub_and_test (a, l) (local_sub_return((a), (l)) == 0) -#define local_dec_and_test (l) (local_dec_return((l)) == 0) - -/* -* Atomically test *l and decrement if it is greater than 0. -* The function returns the old value of *l minus 1. -*/ -static __inline__long local_dec_if_positive (local_t *l) -{ -long t; - - __asm__ __volatile__( -"1:" PPC_LLARX "%0,0,%1 # local_dec_if_positive\n\ -cmpwi %0,1\n\ -addi %0,%0,-1\n\ -blt- 2f\n" - PPC405_ERR77(0,%1) -PPC_STLCX "%0,0,%1\n\ -bne- 1b" -"\n\ -2:" : "=&b" (t) - : "r" (&(l->a.counter)) - : "cc", "memory"); - - return t; -} - -/* Use these for per-cpu local_t variables: on some archs they are -* much more efficient than these naive implementations. Note they take -* a variable, not an address. -*/ - -#define __local_inc (l) ((l)->a.counter++) -#define __local_dec (l) ((l)->a.counter++) -#define __local_add (i,l) ((l)->a.counter+=(i)) -#define __local_sub (i,l) ((l)->a.counter-=(i))#endif /* _ARCH_POWERPC_LOCAL_H */
arch/x86/include/asm/local.h +0 -118
131 lines not on this page · raw message
include/asm-generic/local.h +0 -16
@@ -32,24 +32,8 @@ typedef struct#define local_add (i,l) atomic_long_add((i),(&(l)->a))#define local_sub (i,l) atomic_long_sub((i),(&(l)->a)) -#define local_sub_and_test (i, l) atomic_long_sub_and_test((i), (&(l)->a)) -#define local_dec_and_test (l) atomic_long_dec_and_test(&(l)->a) -#define local_inc_and_test (l) atomic_long_inc_and_test(&(l)->a) -#define local_add_negative (i, l) atomic_long_add_negative((i), (&(l)->a))#define local_add_return (i, l) atomic_long_add_return((i), (&(l)->a)) -#define local_sub_return (i, l) atomic_long_sub_return((i), (&(l)->a)) -#define local_inc_return (l) atomic_long_inc_return(&(l)->a)#define local_cmpxchg (l, o, n) atomic_long_cmpxchg((&(l)->a), (o), (n)) -#define local_xchg (l, n) atomic_long_xchg((&(l)->a), (n)) -#define local_add_unless (l, _a, u) atomic_long_add_unless((&(l)->a), (_a), (u)) -#define local_inc_not_zero (l) atomic_long_inc_not_zero(&(l)->a) - -/* Non-atomic variants, ie. preemption disabled and won't be touched -* in interrupt, etc. Some archs can optimize this case well. */ -#define __local_inc (l) local_set((l), local_read(l) + 1) -#define __local_dec (l) local_set((l), local_read(l) - 1) -#define __local_add (i,l) local_set((l), local_read(l) + (i)) -#define __local_sub (i,l) local_set((l), local_read(l) - (i))#endif /* _ASM_GENERIC_LOCAL_H */
arch/alpha/include/asm/local.h +0 -61
68 lines not on this page · raw message
arch/m32r/include/asm/local.h +3 -178
211 lines not on this page · raw message
arch/mips/include/asm/local.h +0 -120
127 lines not on this page · raw message
RFC v2 2/3 Remove local_t type from tree.
In reply to Christoph LameterIt would be better if local ops would generically work on any scalar. local_t only allows the use of long. local_t also requires initializers and a read function that never does anything aside from setting or reading a variable.
Remove local_t and replace with long. For now the API still only supports a single type but asm-generic/local.h shows how it can be genericized similar to what cmpxchg_local() does.
With that we can get rid of local_read/set and LOCAL_INIT too.
We need to update the ringbuffer users to no longer refer to these functions.
--- arch/alpha/include/asm/local.h | 29 +++------ arch/m32r/include/asm/local.h | 37 +----------- arch/mips/include/asm/local.h | 39 ++++--------- arch/powerpc/include/asm/local.h | 26 ++------ arch/x86/include/asm/local.h | 35 ++++------- include/asm-generic/local.h | 66 +++++++++++++--------- kernel/trace/ring_buffer.c | 104 +++++++++++++++++------------------ kernel/trace/ring_buffer_benchmark.c | 4 - 8 files changed, 141 insertions(+), 199 deletions(-)
arch/powerpc/include/asm/local.h +8 -18
@@ -4,22 +4,7 @@#include <linux/percpu.h> #include <asm/atomic.h> -typedef struct -{ -atomic_long_t a; -}local_t ; - -#define LOCAL_INIT (i) { ATOMIC_LONG_INIT(i) } - -#define local_read (l) atomic_long_read(&(l)->a) -#define local_set (l,i) atomic_long_set(&(l)->a, (i)) - -#define local_add (i,l) atomic_long_add((i),(&(l)->a)) -#define local_sub (i,l) atomic_long_sub((i),(&(l)->a)) -#define local_inc (l) atomic_long_inc(&(l)->a) -#define local_dec (l) atomic_long_dec(&(l)->a) - -static __inline__long local_add_return (long a,local_t *l) +static __inline__long local_add_return (long a,long *l) {long t;
@@ -30,13 +15,18 @@ static __inline__ long local_add_return( PPC_STLCX "%0,0,%2 \n\ bne- 1b" : "=&r" (t) - : "r" (a), "r" (&(l->a.counter)) + : "r" (a), "r" (*l) : "cc", "memory"); return t; } +#define local_add (i, l) local_add_return((i), (l)) +#define local_sub (i, l) local_add_return(-(i), (l)) +#define local_inc (l) local_add_return(1, (l)) +#define local_dec (l) local_add_return(-1, (l)) +#define local_cmpxchg (l, o, n) \ - (cmpxchg_local(&((l)->a.counter), (o), (n))) + (cmpxchg_local((l), (o), (n)))#endif /* _ARCH_POWERPC_LOCAL_H */
arch/x86/include/asm/local.h +13 -22
@@ -7,38 +7,29 @@#include <asm/atomic.h> #include <asm/asm.h> -typedef struct { -atomic_long_t a; -}local_t ; - -#define LOCAL_INIT (i) { ATOMIC_LONG_INIT(i) } - -#define local_read (l) atomic_long_read(&(l)->a) -#define local_set (l, i) atomic_long_set(&(l)->a, (i)) - -static inline void local_inc (local_t *l) +static inline void local_inc (long *l) { asmvolatile (_ASM_INC"%0" - :"+m" (l->a.counter)); + :"+m" (*l)); } -static inline void local_dec (local_t *l) +static inline void local_dec (long *l) { asmvolatile (_ASM_DEC"%0" - :"+m" (l->a.counter)); + :"+m" (*l)); } -static inline void local_add (long i,local_t *l) +static inline void local_add (long i,long *l) { asmvolatile (_ASM_ADD"%1,%0" - :"+m" (l->a.counter) + :"+m" (*l) :"ir" (i)); } -static inline void local_sub (long i,local_t *l) +static inline void local_sub (long i,long *l) { asmvolatile (_ASM_SUB"%1,%0" - :"+m" (l->a.counter) + :"+m" (*l) :"ir" (i)); }
@@ -49,7 +40,7 @@ static inline void local_sub(long i, loc* * Atomically adds @i to @l and returns @i + @l */ -static inline long local_add_return (long i,local_t *l) +static inline long local_add_return (long i,long *l) {long __i;#ifdef CONFIG_M386
@@ -60,21 +51,21 @@ static inline long local_add_return(long/* Modern 486+ processor */ __i = i; asmvolatile (_ASM_XADD"%0, %1;" - :"+r" (i),"+m" (l->a.counter) + :"+r" (i),"+m" (*l) : :"memory" );return i + __i;#ifdef CONFIG_M386 no_xadd:/* Legacy 386 processor */ local_irq_save (flags); - __i =local_read (l); -local_set (l, i + __i); + __i = *l; + *l = i + __i;local_irq_restore (flags);return i + __i; #endif }#define local_cmpxchg (l, o, n) \ - (cmpxchg_local(&((l)->a.counter), (o), (n))) + (cmpxchg_local((l), (o), (n)))#endif /* _ASM_X86_LOCAL_H */
include/asm-generic/local.h +40 -26
79 lines not on this page · raw message
kernel/trace/ring_buffer.c +52 -52
272 lines not on this page · raw message
kernel/trace/ring_buffer_benchmark.c +2 -2
@@ -12,7 +12,7 @@struct rb_page {u64 ts; -local_t commit; +long commit;char data[4080 ]; };
@@ -113,7 +113,7 @@ static enum event_status read_page(int c ret =ring_buffer_read_page (buffer, &bpage,PAGE_SIZE , cpu,1 );if (ret >=0 ) { rpage = bpage; - commit =local_read (&rpage->commit); + commit = rpage->commit;for (i =0 ; i < commit && !kill_test; i += inc) {if (i >= (PAGE_SIZE - offsetof(struct rb_page , data))) {
arch/alpha/include/asm/local.h +10 -19
@@ -1,23 +1,9 @@#ifndef _ALPHA_LOCAL_H#define _ALPHA_LOCAL_H -#include <linux/percpu.h> -#include <asm/atomic.h> +#include <linux/types.h> -typedef struct -{ -atomic_long_t a; -}local_t ; - -#define LOCAL_INIT (i) { ATOMIC_LONG_INIT(i) } -#define local_read (l) atomic_long_read(&(l)->a) -#define local_set (l,i) atomic_long_set(&(l)->a, (i)) -#define local_inc (l) atomic_long_inc(&(l)->a) -#define local_dec (l) atomic_long_dec(&(l)->a) -#define local_add (i,l) atomic_long_add((i),(&(l)->a)) -#define local_sub (i,l) atomic_long_sub((i),(&(l)->a)) - -static __inline__long local_add_return (long i,local_t * l) +static __inline__long local_add_return (long i,long *l) {long temp, result; __asm__ __volatile__(
@@ -29,12 +15,17 @@ static __inline__ long local_add_return( ".subsection 2\n" "2: br 1b\n" ".previous" - :"=&r" (temp), "=m" (l->a.counter), "=&r" (result) - :"Ir" (i), "m" (l->a.counter) : "memory"); + :"=&r" (temp), "=m" (*l), "=&r" (result) + :"Ir" (i), "m" (*l) : "memory"); return result; } +#define local_inc (l) local_add_return(1, (l)) +#define local_dec (l) local_add_return(-1, (l)) +#define local_add (i,l) local_add_return((i),(l)) +#define local_sub (i,l) local_add_return(-(i),(l)) +#define local_cmpxchg (l, o, n) \ - (cmpxchg_local(&((l)->a.counter), (o), (n))) + (cmpxchg_local((l), (o), (n)))#endif /* _ALPHA_LOCAL_H */
arch/m32r/include/asm/local.h +3 -34
@@ -15,37 +15,6 @@#include <asm/system.h> #include <asm/local.h> -/* -* Atomic operations that C can't guarantee us. Useful for -* resource counting etc.. -*/ - -/* -* 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 int counter; }local_t ; - -#define LOCAL_INIT (i) { (i) } - -/** -* local_read - read local variable -* @l: pointer of type local_t -* -* Atomically reads the value of @l. -*/ -#define local_read (l) ((l)->counter) - -/** -* local_set - set local variable -* @l: pointer of type local_t -* @i: required value -* -* Atomically sets the value of @l to @i. -*/ -#define local_set (l, i) (((l)->counter) = (i)) -/** * local_add_return - add long to local variable and return it * @i: long value to add
@@ -53,7 +22,7 @@ typedef struct { volatile int counter; }* * Atomically adds @i to @l and return (@i + @l). */ -static inline long local_add_return (long i,local_t *l) +static inline long local_add_return (long i,long *l) {unsigned long flags;long result;
@@ -66,7 +35,7 @@ static inline long local_add_return(long"add %0, %2; \n\t" "st %0, @%1; \n\t" : "=&r" (result) - : "r" (&l->counter), "r" (i) + : "r" (*l), "r" (i) : "memory" #ifdef CONFIG_CHIP_M32700_TS1 ,"r4"
@@ -111,7 +80,7 @@ static inline long local_add_return(long*/ #define local_dec (l) local_sub(1, (l)) -#define local_cmpxchg (l, o, n) (cmpxchg_local(&((l)->counter), (o), (n))) +#define local_cmpxchg (l, o, n) (cmpxchg_local((l), (o), (n)))static inline void local_clear_mask (unsigned long mask,local_t *addr) {
arch/mips/include/asm/local.h +13 -26
@@ -7,25 +7,7 @@#include <asm/cmpxchg.h> #include <asm/war.h> -typedef struct -{ -atomic_long_t a; -}local_t ; - -#define LOCAL_INIT (i) { ATOMIC_LONG_INIT(i) } - -#define local_read (l) atomic_long_read(&(l)->a) -#define local_set (l, i) atomic_long_set(&(l)->a, (i)) - -#define local_add (i, l) atomic_long_add((i), (&(l)->a)) -#define local_sub (i, l) atomic_long_sub((i), (&(l)->a)) -#define local_inc (l) atomic_long_inc(&(l)->a) -#define local_dec (l) atomic_long_dec(&(l)->a) - -/* -* Same as above, but return the result value -*/ -static __inline__long local_add_return (long i,local_t * l) +static __inline__long local_add_return (long i,long * l) {unsigned long result;
@@ -40,8 +22,8 @@ static __inline__ long local_add_return( " beqzl %0, 1b \n" " addu %0, %1, %3 \n" " .set mips0 \n" - : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) - : "Ir" (i), "m" (l->a.counter) + : "=&r" (result), "=&r" (temp), "=m" (*l) + : "Ir" (i), "m" (*l) : "memory"); }else if (kernel_uses_llsc) {unsigned long temp;
@@ -54,23 +36,28 @@ static __inline__ long local_add_return( " beqz %0, 1b \n" " addu %0, %1, %3 \n" " .set mips0 \n" - : "=&r" (result), "=&r" (temp), "=m" (l->a.counter) - : "Ir" (i), "m" (l->a.counter) + : "=&r" (result), "=&r" (temp), "=m" (*l) + : "Ir" (i), "m" (*l) : "memory"); }else {unsigned long flags;local_irq_save (flags); - result = l->a.counter; + result = *l; result += i; - l->a.counter = result; + *l = result;local_irq_restore (flags); }return result; } +#define local_add (i, l) local_add_return((i), (l)) +#define local_sub (i, l) local_add_return(-(i), (l)) +#define local_inc (l) local_add_return(-1, (l)) +#define local_dec (l) local_add_return(-1, (l)) +#define local_cmpxchg (l, o, n) \ - ((long)cmpxchg_local(&((l)->a.counter), (o), (n))) + ((long)cmpxchg_local((l), (o), (n)))#endif /* _ARCH_MIPS_LOCAL_H */
Arnd Bergmann
maintainerRe: [RFC local_t removal V2 2/3] Remove local_t type from tree.
Quoted 5 lines · On Thursday 07 January 2010 23:35:26 Christoph Lameter wrote:
include/asm-generic/local.h +4
-1-#define local_add_return (i, l) atomic_long_add_return((i), (&(l)->a)) +local_irq_save (flags); +switch (size) { +case 1 : r = (*((u8 *)ptr) += value); +break ;
include/asm-generic/local.h line 42
Quoted 10 lines
include/asm-generic/local.h +10
-0+case 2 : r = (*((u16 *)ptr) += value); +break ; +case 4 : r = (*((u32 *)ptr) += value); +break ; +case 8 : r = (*((u64 *)ptr) += value); +break ; + } +local_irq_restore (flags); +return r; +}
This still misses 'volatile'.
Arnd
RFC v2 3/3 Eliminate local_cmpxchg
In reply to Christoph Lametercmpxchg_local is the same as local_cmpxchg.
Keep cmpxchg_local and change the 3 occurrences of local_cmpxchg to cmpxchg_local.
--- arch/alpha/include/asm/local.h | 3 --- arch/m32r/include/asm/local.h | 2 -- arch/mips/include/asm/local.h | 3 --- arch/powerpc/include/asm/local.h | 3 --- arch/x86/include/asm/local.h | 3 --- include/asm-generic/local.h | 2 -- kernel/trace/ring_buffer.c | 6 +++--- 7 files changed, 3 insertions(+), 19 deletions(-)
arch/alpha/include/asm/local.h +0 -3
@@ -25,7 +25,4 @@ static __inline__ long local_add_return(#define local_add (i,l) local_add_return((i),(l))#define local_sub (i,l) local_add_return(-(i),(l)) -#define local_cmpxchg (l, o, n) \ - (cmpxchg_local((l), (o), (n))) -#endif /* _ALPHA_LOCAL_H */
arch/m32r/include/asm/local.h +0 -2
@@ -80,8 +80,6 @@ static inline long local_add_return(long*/ #define local_dec (l) ((void)local_add_return(-1, (l)) -#define local_cmpxchg (l, o, n) (cmpxchg_local((l), (o), (n))) -static inline void local_clear_mask (unsigned long mask,local_t *addr) {unsigned long flags;
arch/mips/include/asm/local.h +0 -3
@@ -57,7 +57,4 @@ static __inline__ long local_add_return(#define local_inc (l) local_add_return(-1, (l))#define local_dec (l) local_add_return(-1, (l)) -#define local_cmpxchg (l, o, n) \ - ((long)cmpxchg_local((l), (o), (n))) -#endif /* _ARCH_MIPS_LOCAL_H */
arch/powerpc/include/asm/local.h +0 -3
@@ -26,7 +26,4 @@ static __inline__ long local_add_return(#define local_inc (l) local_add_return(-1, (l))#define local_dec (l) local_add_return(-1, (l)) -#define local_cmpxchg (l, o, n) \ - (cmpxchg_local((l), (o), (n))) -#endif /* _ARCH_POWERPC_LOCAL_H */
arch/x86/include/asm/local.h +0 -3
@@ -65,7 +65,4 @@ no_xadd: /* Legacy 386 processor */ #endif } -#define local_cmpxchg (l, o, n) \ - (cmpxchg_local((l), (o), (n))) -#endif /* _ASM_X86_LOCAL_H */
include/asm-generic/local.h +0 -2
@@ -53,6 +53,4 @@ static inline unsigned long __add_return#define local_add (i,l) local_add_return((i), (l))#define local_sub (i,l) local_add_return(-(i), (l)) -#define local_cmpxchg (l, o, n) cmpxchg_local((l), (o), (n)) -#endif /* _ASM_GENERIC_LOCAL_i */
kernel/trace/ring_buffer.c +3 -3
@@ -853,8 +853,8 @@ static int rb_tail_page_update(struct ri* cmpxchg to only update if an interrupt did not already * do it for us. If the cmpxchg fails, we don't care. */ - (void )local_cmpxchg (&next_page->write, old_write, val); - (void )local_cmpxchg (&next_page->entries, old_entries, eval); + (void )cmpxchg_local (&next_page->write, old_write, val); + (void )cmpxchg_local (&next_page->entries, old_entries, eval);/* * No need to worry about races with clearing out the commit.
@@ -1952,7 +1952,7 @@ rb_try_to_discard(struct ring_buffer_per*/ old_index += write_mask; new_index += write_mask; - index =local_cmpxchg (&bpage->write, old_index, new_index); + index =cmpxchg_local (&bpage->write, old_index, new_index);if (index == old_index)return 1 ; }