1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#ifndef _ASM_IA64_RWSEM_H
23#define _ASM_IA64_RWSEM_H
24
25#ifndef _LINUX_RWSEM_H
26#error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
27#endif
28
29#include <asm/intrinsics.h>
30
31#define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000)
32#define RWSEM_ACTIVE_BIAS (1L)
33#define RWSEM_ACTIVE_MASK (0xffffffffL)
34#define RWSEM_WAITING_BIAS (-0x100000000L)
35#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
36#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
37
38
39
40
41static inline void
42__down_read (struct rw_semaphore *sem)
43{
44 long result = ia64_fetchadd8_acq((unsigned long *)&sem->count.counter, 1);
45
46 if (result < 0)
47 rwsem_down_read_failed(sem);
48}
49
50
51
52
53static inline long
54___down_write (struct rw_semaphore *sem)
55{
56 long old, new;
57
58 do {
59 old = atomic_long_read(&sem->count);
60 new = old + RWSEM_ACTIVE_WRITE_BIAS;
61 } while (atomic_long_cmpxchg_acquire(&sem->count, old, new) != old);
62
63 return old;
64}
65
66static inline void
67__down_write (struct rw_semaphore *sem)
68{
69 if (___down_write(sem))
70 rwsem_down_write_failed(sem);
71}
72
73static inline int
74__down_write_killable (struct rw_semaphore *sem)
75{
76 if (___down_write(sem))
77 if (IS_ERR(rwsem_down_write_failed_killable(sem)))
78 return -EINTR;
79
80 return 0;
81}
82
83
84
85
86static inline void
87__up_read (struct rw_semaphore *sem)
88{
89 long result = ia64_fetchadd8_rel((unsigned long *)&sem->count.counter, -1);
90
91 if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
92 rwsem_wake(sem);
93}
94
95
96
97
98static inline void
99__up_write (struct rw_semaphore *sem)
100{
101 long old, new;
102
103 do {
104 old = atomic_long_read(&sem->count);
105 new = old - RWSEM_ACTIVE_WRITE_BIAS;
106 } while (atomic_long_cmpxchg_release(&sem->count, old, new) != old);
107
108 if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0)
109 rwsem_wake(sem);
110}
111
112
113
114
115static inline int
116__down_read_trylock (struct rw_semaphore *sem)
117{
118 long tmp;
119 while ((tmp = atomic_long_read(&sem->count)) >= 0) {
120 if (tmp == atomic_long_cmpxchg_acquire(&sem->count, tmp, tmp+1)) {
121 return 1;
122 }
123 }
124 return 0;
125}
126
127
128
129
130static inline int
131__down_write_trylock (struct rw_semaphore *sem)
132{
133 long tmp = atomic_long_cmpxchg_acquire(&sem->count,
134 RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS);
135 return tmp == RWSEM_UNLOCKED_VALUE;
136}
137
138
139
140
141static inline void
142__downgrade_write (struct rw_semaphore *sem)
143{
144 long old, new;
145
146 do {
147 old = atomic_long_read(&sem->count);
148 new = old - RWSEM_WAITING_BIAS;
149 } while (atomic_long_cmpxchg_release(&sem->count, old, new) != old);
150
151 if (old < 0)
152 rwsem_downgrade_wake(sem);
153}
154
155#endif
156