blob: 34c07fe5005a900346fff26b5e510006c3cd7140 [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
wdenkbb2d9272003-06-25 22:26:29 +000019#ifdef CONFIG_SMP
20#error SMP not supported
21#endif
22
23typedef struct { volatile int counter; } atomic_t;
24
25#define ATOMIC_INIT(i) { (i) }
26
27#ifdef __KERNEL__
Vasili Galka8e53b1e2014-06-10 16:16:14 +030028#include <asm/proc-armv/system.h>
wdenkbb2d9272003-06-25 22:26:29 +000029
30#define atomic_read(v) ((v)->counter)
31#define atomic_set(v,i) (((v)->counter) = (i))
32
33static inline void atomic_add(int i, volatile atomic_t *v)
34{
35 unsigned long flags;
36
37 local_irq_save(flags);
38 v->counter += i;
39 local_irq_restore(flags);
40}
41
42static inline void atomic_sub(int i, volatile atomic_t *v)
43{
44 unsigned long flags;
45
46 local_irq_save(flags);
47 v->counter -= i;
48 local_irq_restore(flags);
49}
50
51static inline void atomic_inc(volatile atomic_t *v)
52{
53 unsigned long flags;
54
55 local_irq_save(flags);
56 v->counter += 1;
57 local_irq_restore(flags);
58}
59
60static inline void atomic_dec(volatile atomic_t *v)
61{
62 unsigned long flags;
63
64 local_irq_save(flags);
65 v->counter -= 1;
66 local_irq_restore(flags);
67}
68
69static inline int atomic_dec_and_test(volatile atomic_t *v)
70{
71 unsigned long flags;
72 int val;
73
74 local_irq_save(flags);
75 val = v->counter;
76 v->counter = val -= 1;
77 local_irq_restore(flags);
78
79 return val == 0;
80}
81
82static inline int atomic_add_negative(int i, volatile atomic_t *v)
83{
84 unsigned long flags;
85 int val;
86
87 local_irq_save(flags);
88 val = v->counter;
89 v->counter = val += i;
90 local_irq_restore(flags);
91
92 return val < 0;
93}
94
95static inline void atomic_clear_mask(unsigned long mask, unsigned long *addr)
96{
97 unsigned long flags;
98
99 local_irq_save(flags);
100 *addr &= ~mask;
101 local_irq_restore(flags);
102}
103
104/* Atomic operations are already serializing on ARM */
105#define smp_mb__before_atomic_dec() barrier()
106#define smp_mb__after_atomic_dec() barrier()
107#define smp_mb__before_atomic_inc() barrier()
108#define smp_mb__after_atomic_inc() barrier()
109
110#endif
111#endif