-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
We have a few different ways to do the atomic operations, so split them out in to different headers rather than bloating atomic.h. Kernelspace gUSA will take this up to a third implementation. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
- Loading branch information
Paul Mundt
committed
Dec 11, 2006
1 parent
a45e724
commit ec723fb
Showing
3 changed files
with
180 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
#ifndef __ASM_SH_ATOMIC_IRQ_H | ||
#define __ASM_SH_ATOMIC_IRQ_H | ||
|
||
/* | ||
* To get proper branch prediction for the main line, we must branch | ||
* forward to code at the end of this object's .text section, then | ||
* branch back to restart the operation. | ||
*/ | ||
static inline void atomic_add(int i, atomic_t *v) | ||
{ | ||
unsigned long flags; | ||
|
||
local_irq_save(flags); | ||
*(long *)v += i; | ||
local_irq_restore(flags); | ||
} | ||
|
||
static inline void atomic_sub(int i, atomic_t *v) | ||
{ | ||
unsigned long flags; | ||
|
||
local_irq_save(flags); | ||
*(long *)v -= i; | ||
local_irq_restore(flags); | ||
} | ||
|
||
static inline int atomic_add_return(int i, atomic_t *v) | ||
{ | ||
unsigned long temp, flags; | ||
|
||
local_irq_save(flags); | ||
temp = *(long *)v; | ||
temp += i; | ||
*(long *)v = temp; | ||
local_irq_restore(flags); | ||
|
||
return temp; | ||
} | ||
|
||
static inline int atomic_sub_return(int i, atomic_t *v) | ||
{ | ||
unsigned long temp, flags; | ||
|
||
local_irq_save(flags); | ||
temp = *(long *)v; | ||
temp -= i; | ||
*(long *)v = temp; | ||
local_irq_restore(flags); | ||
|
||
return temp; | ||
} | ||
|
||
static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | ||
{ | ||
unsigned long flags; | ||
|
||
local_irq_save(flags); | ||
*(long *)v &= ~mask; | ||
local_irq_restore(flags); | ||
} | ||
|
||
static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | ||
{ | ||
unsigned long flags; | ||
|
||
local_irq_save(flags); | ||
*(long *)v |= mask; | ||
local_irq_restore(flags); | ||
} | ||
|
||
#endif /* __ASM_SH_ATOMIC_IRQ_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#ifndef __ASM_SH_ATOMIC_LLSC_H | ||
#define __ASM_SH_ATOMIC_LLSC_H | ||
|
||
/* | ||
* To get proper branch prediction for the main line, we must branch | ||
* forward to code at the end of this object's .text section, then | ||
* branch back to restart the operation. | ||
*/ | ||
static inline void atomic_add(int i, atomic_t *v) | ||
{ | ||
unsigned long tmp; | ||
|
||
__asm__ __volatile__ ( | ||
"1: movli.l @%2, %0 ! atomic_add \n" | ||
" add %1, %0 \n" | ||
" movco.l %0, @%2 \n" | ||
" bf 1b \n" | ||
: "=&z" (tmp) | ||
: "r" (i), "r" (&v->counter) | ||
: "t"); | ||
} | ||
|
||
static inline void atomic_sub(int i, atomic_t *v) | ||
{ | ||
unsigned long tmp; | ||
|
||
__asm__ __volatile__ ( | ||
"1: movli.l @%2, %0 ! atomic_sub \n" | ||
" sub %1, %0 \n" | ||
" movco.l %0, @%2 \n" | ||
" bf 1b \n" | ||
: "=&z" (tmp) | ||
: "r" (i), "r" (&v->counter) | ||
: "t"); | ||
} | ||
|
||
/* | ||
* SH-4A note: | ||
* | ||
* We basically get atomic_xxx_return() for free compared with | ||
* atomic_xxx(). movli.l/movco.l require r0 due to the instruction | ||
* encoding, so the retval is automatically set without having to | ||
* do any special work. | ||
*/ | ||
static inline int atomic_add_return(int i, atomic_t *v) | ||
{ | ||
unsigned long temp; | ||
|
||
__asm__ __volatile__ ( | ||
"1: movli.l @%2, %0 ! atomic_add_return \n" | ||
" add %1, %0 \n" | ||
" movco.l %0, @%2 \n" | ||
" bf 1b \n" | ||
" synco \n" | ||
: "=&z" (temp) | ||
: "r" (i), "r" (&v->counter) | ||
: "t"); | ||
|
||
return temp; | ||
} | ||
|
||
static inline int atomic_sub_return(int i, atomic_t *v) | ||
{ | ||
unsigned long temp; | ||
|
||
__asm__ __volatile__ ( | ||
"1: movli.l @%2, %0 ! atomic_sub_return \n" | ||
" sub %1, %0 \n" | ||
" movco.l %0, @%2 \n" | ||
" bf 1b \n" | ||
" synco \n" | ||
: "=&z" (temp) | ||
: "r" (i), "r" (&v->counter) | ||
: "t"); | ||
|
||
return temp; | ||
} | ||
|
||
static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) | ||
{ | ||
unsigned long tmp; | ||
|
||
__asm__ __volatile__ ( | ||
"1: movli.l @%2, %0 ! atomic_clear_mask \n" | ||
" and %1, %0 \n" | ||
" movco.l %0, @%2 \n" | ||
" bf 1b \n" | ||
: "=&z" (tmp) | ||
: "r" (~mask), "r" (&v->counter) | ||
: "t"); | ||
} | ||
|
||
static inline void atomic_set_mask(unsigned int mask, atomic_t *v) | ||
{ | ||
unsigned long tmp; | ||
|
||
__asm__ __volatile__ ( | ||
"1: movli.l @%2, %0 ! atomic_set_mask \n" | ||
" or %1, %0 \n" | ||
" movco.l %0, @%2 \n" | ||
" bf 1b \n" | ||
: "=&z" (tmp) | ||
: "r" (mask), "r" (&v->counter) | ||
: "t"); | ||
} | ||
|
||
#endif /* __ASM_SH_ATOMIC_LLSC_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters