Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SPARC]: Make bitops use same spinlocks as atomics.

Recent workqueue changes basically make this a formal requirement.

Also, move atomic32.o from lib-y to obj-y since it exports symbols
to modules.

Signed-off-by: David S. Miller <davem@davemloft.net>

+58 -207
-8
arch/sparc/kernel/sparc_ksyms.c
··· 83 83 /* Private functions with odd calling conventions. */ 84 84 extern void ___atomic24_add(void); 85 85 extern void ___atomic24_sub(void); 86 - extern void ___set_bit(void); 87 - extern void ___clear_bit(void); 88 - extern void ___change_bit(void); 89 86 extern void ___rw_read_enter(void); 90 87 extern void ___rw_read_try(void); 91 88 extern void ___rw_read_exit(void); ··· 121 124 /* Atomic operations. */ 122 125 EXPORT_SYMBOL(___atomic24_add); 123 126 EXPORT_SYMBOL(___atomic24_sub); 124 - 125 - /* Bit operations. */ 126 - EXPORT_SYMBOL(___set_bit); 127 - EXPORT_SYMBOL(___clear_bit); 128 - EXPORT_SYMBOL(___change_bit); 129 127 130 128 /* Per-CPU information table */ 131 129 EXPORT_PER_CPU_SYMBOL(__cpu_data);
+1 -4
arch/sparc/kernel/time.c
··· 78 78 extern char __copy_user_begin[], __copy_user_end[]; 79 79 extern char __atomic_begin[], __atomic_end[]; 80 80 extern char __bzero_begin[], __bzero_end[]; 81 - extern char __bitops_begin[], __bitops_end[]; 82 81 83 82 unsigned long pc = regs->pc; 84 83 ··· 87 88 (pc >= (unsigned long) __atomic_begin && 88 89 pc < (unsigned long) __atomic_end) || 89 90 (pc >= (unsigned long) __bzero_begin && 90 - pc < (unsigned long) __bzero_end) || 91 - (pc >= (unsigned long) __bitops_begin && 92 - pc < (unsigned long) __bitops_end)) 91 + pc < (unsigned long) __bzero_end)) 93 92 pc = regs->u_regs[UREG_RETPC]; 94 93 return pc; 95 94 }
+2 -2
arch/sparc/lib/Makefile
··· 7 7 lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ 8 8 strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ 9 9 strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ 10 - copy_user.o locks.o atomic.o atomic32.o bitops.o \ 10 + copy_user.o locks.o atomic.o \ 11 11 lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o 12 12 13 - obj-y += iomap.o 13 + obj-y += iomap.o atomic32.o
+39
arch/sparc/lib/atomic32.c
··· 76 76 spin_unlock_irqrestore(ATOMIC_HASH(v), flags); 77 77 } 78 78 EXPORT_SYMBOL(atomic_set); 79 + 80 + unsigned long ___set_bit(unsigned long *addr, unsigned long mask) 81 + { 82 + unsigned long old, flags; 83 + 84 + spin_lock_irqsave(ATOMIC_HASH(addr), flags); 85 + old = *addr; 86 + *addr = old | mask; 87 + spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); 88 + 89 + return old & mask; 90 + } 91 + EXPORT_SYMBOL(___set_bit); 92 + 93 + unsigned long ___clear_bit(unsigned long *addr, unsigned long mask) 94 + { 95 + unsigned long old, flags; 96 + 97 + spin_lock_irqsave(ATOMIC_HASH(addr), flags); 98 + old = *addr; 99 + *addr = old & ~mask; 100 + spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); 101 + 102 + return old & mask; 103 + } 104 + EXPORT_SYMBOL(___clear_bit); 105 + 106 + unsigned long ___change_bit(unsigned long *addr, unsigned long mask) 107 + { 108 + unsigned long old, flags; 109 + 110 + spin_lock_irqsave(ATOMIC_HASH(addr), flags); 111 + old = *addr; 112 + *addr = old ^ mask; 113 + spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); 114 + 115 + return old & mask; 116 + } 117 + EXPORT_SYMBOL(___change_bit);
-109
arch/sparc/lib/bitops.S
··· 1 - /* bitops.S: Low level assembler bit operations. 2 - * 3 - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 4 - */ 5 - 6 - #include <asm/ptrace.h> 7 - #include <asm/psr.h> 8 - 9 - .text 10 - .align 4 11 - 12 - .globl __bitops_begin 13 - __bitops_begin: 14 - 15 - /* Take bits in %g2 and set them in word at %g1, 16 - * return whether bits were set in original value 17 - * in %g2. %g4 holds value to restore into %o7 18 - * in delay slot of jmpl return, %g3 + %g5 + %g7 can be 19 - * used as temporaries and thus is considered clobbered 20 - * by all callers. 21 - */ 22 - .globl ___set_bit 23 - ___set_bit: 24 - rd %psr, %g3 25 - nop; nop; nop; 26 - or %g3, PSR_PIL, %g5 27 - wr %g5, 0x0, %psr 28 - nop; nop; nop 29 - #ifdef CONFIG_SMP 30 - set bitops_spinlock, %g5 31 - 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. 32 - orcc %g7, 0x0, %g0 ! Did we get it? 33 - bne 2b ! Nope... 34 - #endif 35 - ld [%g1], %g7 36 - or %g7, %g2, %g5 37 - and %g7, %g2, %g2 38 - #ifdef CONFIG_SMP 39 - st %g5, [%g1] 40 - set bitops_spinlock, %g5 41 - stb %g0, [%g5] 42 - #else 43 - st %g5, [%g1] 44 - #endif 45 - wr %g3, 0x0, %psr 46 - nop; nop; nop 47 - jmpl %o7, %g0 48 - mov %g4, %o7 49 - 50 - /* Same as above, but clears the bits from %g2 instead. */ 51 - .globl ___clear_bit 52 - ___clear_bit: 53 - rd %psr, %g3 54 - nop; nop; nop 55 - or %g3, PSR_PIL, %g5 56 - wr %g5, 0x0, %psr 57 - nop; nop; nop 58 - #ifdef CONFIG_SMP 59 - set bitops_spinlock, %g5 60 - 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. 61 - orcc %g7, 0x0, %g0 ! Did we get it? 62 - bne 2b ! Nope... 63 - #endif 64 - ld [%g1], %g7 65 - andn %g7, %g2, %g5 66 - and %g7, %g2, %g2 67 - #ifdef CONFIG_SMP 68 - st %g5, [%g1] 69 - set bitops_spinlock, %g5 70 - stb %g0, [%g5] 71 - #else 72 - st %g5, [%g1] 73 - #endif 74 - wr %g3, 0x0, %psr 75 - nop; nop; nop 76 - jmpl %o7, %g0 77 - mov %g4, %o7 78 - 79 - /* Same thing again, but this time toggles the bits from %g2. */ 80 - .globl ___change_bit 81 - ___change_bit: 82 - rd %psr, %g3 83 - nop; nop; nop 84 - or %g3, PSR_PIL, %g5 85 - wr %g5, 0x0, %psr 86 - nop; nop; nop 87 - #ifdef CONFIG_SMP 88 - set bitops_spinlock, %g5 89 - 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. 90 - orcc %g7, 0x0, %g0 ! Did we get it? 91 - bne 2b ! Nope... 92 - #endif 93 - ld [%g1], %g7 94 - xor %g7, %g2, %g5 95 - and %g7, %g2, %g2 96 - #ifdef CONFIG_SMP 97 - st %g5, [%g1] 98 - set bitops_spinlock, %g5 99 - stb %g0, [%g5] 100 - #else 101 - st %g5, [%g1] 102 - #endif 103 - wr %g3, 0x0, %psr 104 - nop; nop; nop 105 - jmpl %o7, %g0 106 - mov %g4, %o7 107 - 108 - .globl __bitops_end 109 - __bitops_end:
+16 -84
include/asm-sparc/bitops.h
··· 14 14 15 15 #ifdef __KERNEL__ 16 16 17 + extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask); 18 + extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask); 19 + extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask); 20 + 17 21 /* 18 22 * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0' 19 23 * is in the highest of the four bytes and bit '31' is the high bit ··· 26 22 */ 27 23 static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) 28 24 { 29 - register unsigned long mask asm("g2"); 30 - register unsigned long *ADDR asm("g1"); 31 - register int tmp1 asm("g3"); 32 - register int tmp2 asm("g4"); 33 - register int tmp3 asm("g5"); 34 - register int tmp4 asm("g7"); 25 + unsigned long *ADDR, mask; 35 26 36 27 ADDR = ((unsigned long *) addr) + (nr >> 5); 37 28 mask = 1 << (nr & 31); 38 29 39 - __asm__ __volatile__( 40 - "mov %%o7, %%g4\n\t" 41 - "call ___set_bit\n\t" 42 - " add %%o7, 8, %%o7\n" 43 - : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) 44 - : "0" (mask), "r" (ADDR) 45 - : "memory", "cc"); 46 - 47 - return mask != 0; 30 + return ___set_bit(ADDR, mask) != 0; 48 31 } 49 32 50 33 static inline void set_bit(unsigned long nr, volatile unsigned long *addr) 51 34 { 52 - register unsigned long mask asm("g2"); 53 - register unsigned long *ADDR asm("g1"); 54 - register int tmp1 asm("g3"); 55 - register int tmp2 asm("g4"); 56 - register int tmp3 asm("g5"); 57 - register int tmp4 asm("g7"); 35 + unsigned long *ADDR, mask; 58 36 59 37 ADDR = ((unsigned long *) addr) + (nr >> 5); 60 38 mask = 1 << (nr & 31); 61 39 62 - __asm__ __volatile__( 63 - "mov %%o7, %%g4\n\t" 64 - "call ___set_bit\n\t" 65 - " add %%o7, 8, %%o7\n" 66 - : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) 67 - : "0" (mask), "r" (ADDR) 68 - : "memory", "cc"); 40 + (void) ___set_bit(ADDR, mask); 69 41 } 70 42 71 43 static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) 72 44 { 73 - register unsigned long mask asm("g2"); 74 - register unsigned long *ADDR asm("g1"); 75 - register int tmp1 asm("g3"); 76 - register int tmp2 asm("g4"); 77 - register int tmp3 asm("g5"); 78 - register int tmp4 asm("g7"); 45 + unsigned long *ADDR, mask; 79 46 80 47 ADDR = ((unsigned long *) addr) + (nr >> 5); 81 48 mask = 1 << (nr & 31); 82 49 83 - __asm__ __volatile__( 84 - "mov %%o7, %%g4\n\t" 85 - "call ___clear_bit\n\t" 86 - " add %%o7, 8, %%o7\n" 87 - : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) 88 - : "0" (mask), "r" (ADDR) 89 - : "memory", "cc"); 90 - 91 - return mask != 0; 50 + return ___clear_bit(ADDR, mask) != 0; 92 51 } 93 52 94 53 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) 95 54 { 96 - register unsigned long mask asm("g2"); 97 - register unsigned long *ADDR asm("g1"); 98 - register int tmp1 asm("g3"); 99 - register int tmp2 asm("g4"); 100 - register int tmp3 asm("g5"); 101 - register int tmp4 asm("g7"); 55 + unsigned long *ADDR, mask; 102 56 103 57 ADDR = ((unsigned long *) addr) + (nr >> 5); 104 58 mask = 1 << (nr & 31); 105 59 106 - __asm__ __volatile__( 107 - "mov %%o7, %%g4\n\t" 108 - "call ___clear_bit\n\t" 109 - " add %%o7, 8, %%o7\n" 110 - : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) 111 - : "0" (mask), "r" (ADDR) 112 - : "memory", "cc"); 60 + (void) ___clear_bit(ADDR, mask); 113 61 } 114 62 115 63 static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) 116 64 { 117 - register unsigned long mask asm("g2"); 118 - register unsigned long *ADDR asm("g1"); 119 - register int tmp1 asm("g3"); 120 - register int tmp2 asm("g4"); 121 - register int tmp3 asm("g5"); 122 - register int tmp4 asm("g7"); 65 + unsigned long *ADDR, mask; 123 66 124 67 ADDR = ((unsigned long *) addr) + (nr >> 5); 125 68 mask = 1 << (nr & 31); 126 69 127 - __asm__ __volatile__( 128 - "mov %%o7, %%g4\n\t" 129 - "call ___change_bit\n\t" 130 - " add %%o7, 8, %%o7\n" 131 - : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) 132 - : "0" (mask), "r" (ADDR) 133 - : "memory", "cc"); 134 - 135 - return mask != 0; 70 + return ___change_bit(ADDR, mask) != 0; 136 71 } 137 72 138 73 static inline void change_bit(unsigned long nr, volatile unsigned long *addr) 139 74 { 140 - register unsigned long mask asm("g2"); 141 - register unsigned long *ADDR asm("g1"); 142 - register int tmp1 asm("g3"); 143 - register int tmp2 asm("g4"); 144 - register int tmp3 asm("g5"); 145 - register int tmp4 asm("g7"); 75 + unsigned long *ADDR, mask; 146 76 147 77 ADDR = ((unsigned long *) addr) + (nr >> 5); 148 78 mask = 1 << (nr & 31); 149 79 150 - __asm__ __volatile__( 151 - "mov %%o7, %%g4\n\t" 152 - "call ___change_bit\n\t" 153 - " add %%o7, 8, %%o7\n" 154 - : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) 155 - : "0" (mask), "r" (ADDR) 156 - : "memory", "cc"); 80 + (void) ___change_bit(ADDR, mask); 157 81 } 158 82 159 83 #include <asm-generic/bitops/non-atomic.h>