blob: ba9e4b72d8214d6a87f23ef89721a90759069539 [file] [log] [blame]
wdenkbb2d9272003-06-25 22:26:29 +00001/*
2 * linux/include/asm-arm/atomic.h
3 *
4 * Copyright (c) 1996 Russell King.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Changelog:
11 * 27-06-1996 RMK Created
12 * 13-04-1997 RMK Made functions atomic!
13 * 07-12-1997 RMK Upgraded for v2.1.
14 * 26-08-1998 PJB Added #ifdef __KERNEL__
15 */
16#ifndef __ASM_ARM_ATOMIC_H
17#define __ASM_ARM_ATOMIC_H
18
19#include <linux/config.h>
20
21#ifdef CONFIG_SMP
22#error SMP not supported
23#endif
24
25typedef struct { volatile int counter; } atomic_t;
26
27#define ATOMIC_INIT(i) { (i) }
28
29#ifdef __KERNEL__
30#include <asm/proc/system.h>
31
32#define atomic_read(v) ((v)->counter)
33#define atomic_set(v,i) (((v)->counter) = (i))
34
35static inline void atomic_add(int i, volatile atomic_t *v)
36{
37 unsigned long flags;
38
39 local_irq_save(flags);
40 v->counter += i;
41 local_irq_restore(flags);
42}
43
44static inline void atomic_sub(int i, volatile atomic_t *v)
45{
46 unsigned long flags;
47
48 local_irq_save(flags);
49 v->counter -= i;
50 local_irq_restore(flags);
51}
52
53static inline void atomic_inc(volatile atomic_t *v)
54{
55 unsigned long flags;
56
57 local_irq_save(flags);
58 v->counter += 1;
59 local_irq_restore(flags);
60}
61
62static inline void atomic_dec(volatile atomic_t *v)
63{
64 unsigned long flags;
65
66 local_irq_save(flags);
67 v->counter -= 1;
68 local_irq_restore(flags);
69}
70
71static inline int atomic_dec_and_test(volatile atomic_t *v)
72{
73 unsigned long flags;
74 int val;
75
76 local_irq_save(flags);
77 val = v->counter;
78 v->counter = val -= 1;
79 local_irq_restore(flags);
80
81 return val == 0;
82}
83
84static inline int atomic_add_negative(int i, volatile atomic_t *v)
85{
86 unsigned long flags;
87 int val;
88
89 local_irq_save(flags);
90 val = v->counter;
91 v->counter = val += i;
92 local_irq_restore(flags);
93
94 return val < 0;
95}
96
97static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
98{
99 unsigned long flags;
100
101 local_irq_save(flags);
102 *addr &= ~mask;
103 local_irq_restore(flags);
104}
105
106/* Atomic operations are already serializing on ARM */
107#define smp_mb__before_atomic_dec() barrier()
108#define smp_mb__after_atomic_dec() barrier()
109#define smp_mb__before_atomic_inc() barrier()
110#define smp_mb__after_atomic_inc() barrier()
111
112#endif
113#endif