Skip to content

Commit

Permalink
[SPARC]: Make bitops use same spinlocks as atomics.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Dec 18, 2006
1 parent 216da72 commit 8a8b836
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 207 deletions.
8 changes: 0 additions & 8 deletions arch/sparc/kernel/sparc_ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ extern int __divdi3(int, int);
/* Private functions with odd calling conventions. */
extern void ___atomic24_add(void);
extern void ___atomic24_sub(void);
extern void ___set_bit(void);
extern void ___clear_bit(void);
extern void ___change_bit(void);
extern void ___rw_read_enter(void);
extern void ___rw_read_try(void);
extern void ___rw_read_exit(void);
Expand Down Expand Up @@ -125,11 +122,6 @@ EXPORT_SYMBOL(pfn_base);
EXPORT_SYMBOL(___atomic24_add);
EXPORT_SYMBOL(___atomic24_sub);

/* Bit operations. */
EXPORT_SYMBOL(___set_bit);
EXPORT_SYMBOL(___clear_bit);
EXPORT_SYMBOL(___change_bit);

/* Per-CPU information table */
EXPORT_PER_CPU_SYMBOL(__cpu_data);

Expand Down
5 changes: 1 addition & 4 deletions arch/sparc/kernel/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ unsigned long profile_pc(struct pt_regs *regs)
extern char __copy_user_begin[], __copy_user_end[];
extern char __atomic_begin[], __atomic_end[];
extern char __bzero_begin[], __bzero_end[];
extern char __bitops_begin[], __bitops_end[];

unsigned long pc = regs->pc;

Expand All @@ -88,9 +87,7 @@ unsigned long profile_pc(struct pt_regs *regs)
(pc >= (unsigned long) __atomic_begin &&
pc < (unsigned long) __atomic_end) ||
(pc >= (unsigned long) __bzero_begin &&
pc < (unsigned long) __bzero_end) ||
(pc >= (unsigned long) __bitops_begin &&
pc < (unsigned long) __bitops_end))
pc < (unsigned long) __bzero_end))
pc = regs->u_regs[UREG_RETPC];
return pc;
}
Expand Down
4 changes: 2 additions & 2 deletions arch/sparc/lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ EXTRA_AFLAGS := -ansi -DST_DIV0=0x02
lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \
strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \
strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
copy_user.o locks.o atomic.o atomic32.o bitops.o \
copy_user.o locks.o atomic.o \
lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o

obj-y += iomap.o
obj-y += iomap.o atomic32.o
39 changes: 39 additions & 0 deletions arch/sparc/lib/atomic32.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,42 @@ void atomic_set(atomic_t *v, int i)
spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
}
EXPORT_SYMBOL(atomic_set);

unsigned long ___set_bit(unsigned long *addr, unsigned long mask)
{
unsigned long old, flags;

spin_lock_irqsave(ATOMIC_HASH(addr), flags);
old = *addr;
*addr = old | mask;
spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);

return old & mask;
}
EXPORT_SYMBOL(___set_bit);

unsigned long ___clear_bit(unsigned long *addr, unsigned long mask)
{
unsigned long old, flags;

spin_lock_irqsave(ATOMIC_HASH(addr), flags);
old = *addr;
*addr = old & ~mask;
spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);

return old & mask;
}
EXPORT_SYMBOL(___clear_bit);

unsigned long ___change_bit(unsigned long *addr, unsigned long mask)
{
unsigned long old, flags;

spin_lock_irqsave(ATOMIC_HASH(addr), flags);
old = *addr;
*addr = old ^ mask;
spin_unlock_irqrestore(ATOMIC_HASH(addr), flags);

return old & mask;
}
EXPORT_SYMBOL(___change_bit);
109 changes: 0 additions & 109 deletions arch/sparc/lib/bitops.S

This file was deleted.

100 changes: 16 additions & 84 deletions include/asm-sparc/bitops.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

#ifdef __KERNEL__

extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask);
extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask);
extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask);

/*
* Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0'
* is in the highest of the four bytes and bit '31' is the high bit
Expand All @@ -22,134 +26,62 @@
*/
static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr)
{
register unsigned long mask asm("g2");
register unsigned long *ADDR asm("g1");
register int tmp1 asm("g3");
register int tmp2 asm("g4");
register int tmp3 asm("g5");
register int tmp4 asm("g7");
unsigned long *ADDR, mask;

ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);

__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
"call ___set_bit\n\t"
" add %%o7, 8, %%o7\n"
: "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
: "0" (mask), "r" (ADDR)
: "memory", "cc");

return mask != 0;
return ___set_bit(ADDR, mask) != 0;
}

static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
{
register unsigned long mask asm("g2");
register unsigned long *ADDR asm("g1");
register int tmp1 asm("g3");
register int tmp2 asm("g4");
register int tmp3 asm("g5");
register int tmp4 asm("g7");
unsigned long *ADDR, mask;

ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);

__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
"call ___set_bit\n\t"
" add %%o7, 8, %%o7\n"
: "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
: "0" (mask), "r" (ADDR)
: "memory", "cc");
(void) ___set_bit(ADDR, mask);
}

static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
{
register unsigned long mask asm("g2");
register unsigned long *ADDR asm("g1");
register int tmp1 asm("g3");
register int tmp2 asm("g4");
register int tmp3 asm("g5");
register int tmp4 asm("g7");
unsigned long *ADDR, mask;

ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);

__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
"call ___clear_bit\n\t"
" add %%o7, 8, %%o7\n"
: "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
: "0" (mask), "r" (ADDR)
: "memory", "cc");

return mask != 0;
return ___clear_bit(ADDR, mask) != 0;
}

static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
{
register unsigned long mask asm("g2");
register unsigned long *ADDR asm("g1");
register int tmp1 asm("g3");
register int tmp2 asm("g4");
register int tmp3 asm("g5");
register int tmp4 asm("g7");
unsigned long *ADDR, mask;

ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);

__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
"call ___clear_bit\n\t"
" add %%o7, 8, %%o7\n"
: "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
: "0" (mask), "r" (ADDR)
: "memory", "cc");
(void) ___clear_bit(ADDR, mask);
}

static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
{
register unsigned long mask asm("g2");
register unsigned long *ADDR asm("g1");
register int tmp1 asm("g3");
register int tmp2 asm("g4");
register int tmp3 asm("g5");
register int tmp4 asm("g7");
unsigned long *ADDR, mask;

ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);

__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
"call ___change_bit\n\t"
" add %%o7, 8, %%o7\n"
: "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
: "0" (mask), "r" (ADDR)
: "memory", "cc");

return mask != 0;
return ___change_bit(ADDR, mask) != 0;
}

static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
{
register unsigned long mask asm("g2");
register unsigned long *ADDR asm("g1");
register int tmp1 asm("g3");
register int tmp2 asm("g4");
register int tmp3 asm("g5");
register int tmp4 asm("g7");
unsigned long *ADDR, mask;

ADDR = ((unsigned long *) addr) + (nr >> 5);
mask = 1 << (nr & 31);

__asm__ __volatile__(
"mov %%o7, %%g4\n\t"
"call ___change_bit\n\t"
" add %%o7, 8, %%o7\n"
: "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4)
: "0" (mask), "r" (ADDR)
: "memory", "cc");
(void) ___change_bit(ADDR, mask);
}

#include <asm-generic/bitops/non-atomic.h>
Expand Down

0 comments on commit 8a8b836

Please sign in to comment.