1 #ifndef __ASM_SH_SEMAPHORE_H
2 #define __ASM_SH_SEMAPHORE_H
4 #include <linux/linkage.h>
7 * SMP- and interrupt-safe semaphores.
9 * (C) Copyright 1996 Linus Torvalds
11 * SuperH verison by Niibe Yutaka
12 * (Currently no asm implementation but generic C code...)
15 #include <linux/spinlock.h>
17 #include <asm/system.h>
18 #include <asm/atomic.h>
23 wait_queue_head_t wait
;
30 # define __SEM_DEBUG_INIT(name) \
31 , (int)&(name).__magic
33 # define __SEM_DEBUG_INIT(name)
36 #define __SEMAPHORE_INITIALIZER(name,count) \
37 { ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
38 __SEM_DEBUG_INIT(name) }
40 #define __MUTEX_INITIALIZER(name) \
41 __SEMAPHORE_INITIALIZER(name,1)
43 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
44 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
46 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
47 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
49 extern inline void sema_init (struct semaphore
*sem
, int val
)
52 * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
54 * i'd rather use the more flexible initialization above, but sadly
55 * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
57 atomic_set(&sem
->count
, val
);
59 init_waitqueue_head(&sem
->wait
);
61 sem
->__magic
= (int)&sem
->__magic
;
65 static inline void init_MUTEX (struct semaphore
*sem
)
70 static inline void init_MUTEX_LOCKED (struct semaphore
*sem
)
76 asmlinkage
void __down_failed(void /* special register calling convention */);
77 asmlinkage
int __down_failed_interruptible(void /* params in registers */);
78 asmlinkage
int __down_failed_trylock(void /* params in registers */);
79 asmlinkage
void __up_wakeup(void /* special register calling convention */);
82 asmlinkage
void __down(struct semaphore
* sem
);
83 asmlinkage
int __down_interruptible(struct semaphore
* sem
);
84 asmlinkage
int __down_trylock(struct semaphore
* sem
);
85 asmlinkage
void __up(struct semaphore
* sem
);
86 extern struct rw_semaphore
*__down_read(struct rw_semaphore
*sem
, int carry
);
87 extern struct rw_semaphore
*__down_write(struct rw_semaphore
*sem
, int carry
);
88 asmlinkage
struct rw_semaphore
*__rwsem_wake(struct rw_semaphore
*sem
);
90 extern spinlock_t semaphore_wake_lock
;
92 extern __inline__
void down(struct semaphore
* sem
)
95 CHECK_MAGIC(sem
->__magic
);
98 if (atomic_dec_return(&sem
->count
) < 0)
102 extern __inline__
int down_interruptible(struct semaphore
* sem
)
106 CHECK_MAGIC(sem
->__magic
);
109 if (atomic_dec_return(&sem
->count
) < 0)
110 ret
= __down_interruptible(sem
);
114 extern __inline__
int down_trylock(struct semaphore
* sem
)
118 CHECK_MAGIC(sem
->__magic
);
121 if (atomic_dec_return(&sem
->count
) < 0)
122 ret
= __down_trylock(sem
);
127 * Note! This is subtle. We jump to wake people up only if
128 * the semaphore was negative (== somebody was waiting on it).
130 extern __inline__
void up(struct semaphore
* sem
)
133 CHECK_MAGIC(sem
->__magic
);
135 if (atomic_inc_return(&sem
->count
) <= 0)
139 /* rw mutexes (should that be mutices? =) -- throw rw
140 * spinlocks and semaphores together, and this is what we
143 * SuperH version by Niibe Yutaka
145 struct rw_semaphore
{
147 volatile unsigned char write_bias_granted
;
148 volatile unsigned char read_bias_granted
;
149 volatile unsigned char pad1
;
150 volatile unsigned char pad2
;
151 wait_queue_head_t wait
;
152 wait_queue_head_t write_bias_wait
;
160 #define RW_LOCK_BIAS 0x01000000
163 #define __RWSEM_DEBUG_INIT , ATOMIC_INIT(0), ATOMIC_INIT(0)
165 #define __RWSEM_DEBUG_INIT /* */
168 #define __RWSEM_INITIALIZER(name,count) \
169 { ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
170 __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
171 __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
173 #define __DECLARE_RWSEM_GENERIC(name,count) \
174 struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
176 #define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
177 #define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
178 #define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
180 extern inline void init_rwsem(struct rw_semaphore
*sem
)
182 atomic_set(&sem
->count
, RW_LOCK_BIAS
);
183 sem
->read_bias_granted
= 0;
184 sem
->write_bias_granted
= 0;
185 init_waitqueue_head(&sem
->wait
);
186 init_waitqueue_head(&sem
->write_bias_wait
);
188 sem
->__magic
= (long)&sem
->__magic
;
189 atomic_set(&sem
->readers
, 0);
190 atomic_set(&sem
->writers
, 0);
194 extern inline void down_read(struct rw_semaphore
*sem
)
196 int saved
= atomic_read(&sem
->count
), new;
198 if (sem
->__magic
!= (long)&sem
->__magic
)
201 if ((new = atomic_dec_return(&sem
->count
)) < 0)
202 __down_read(sem
, (new < 0 && saved
>=0));
204 if (sem
->write_bias_granted
)
206 if (atomic_read(&sem
->writers
))
208 atomic_inc(&sem
->readers
);
212 extern inline void down_write(struct rw_semaphore
*sem
)
214 int saved
= atomic_read(&sem
->count
), new;
216 if (sem
->__magic
!= (long)&sem
->__magic
)
219 if ((new = atomic_sub_return(RW_LOCK_BIAS
, &sem
->count
)) != 0)
220 __down_write(sem
, (new < 0 && saved
>=0));
222 if (atomic_read(&sem
->writers
))
224 if (atomic_read(&sem
->readers
))
226 if (sem
->read_bias_granted
)
228 if (sem
->write_bias_granted
)
230 atomic_inc(&sem
->writers
);
234 /* When a reader does a release, the only significant
235 * case is when there was a writer waiting, and we've
236 * bumped the count to 0: we must wake the writer up.
238 extern inline void __up_read(struct rw_semaphore
*sem
)
240 if (atomic_inc_return(&sem
->count
) == 0)
244 /* releasing the writer is easy -- just release it and
245 * wake up any sleepers.
247 extern inline void __up_write(struct rw_semaphore
*sem
)
249 int saved
= atomic_read(&sem
->count
), new;
251 new = atomic_add_return(RW_LOCK_BIAS
, &sem
->count
);
252 if (saved
< 0 && new >= 0)
256 extern inline void up_read(struct rw_semaphore
*sem
)
259 if (sem
->write_bias_granted
)
261 if (atomic_read(&sem
->writers
))
263 atomic_dec(&sem
->readers
);
268 extern inline void up_write(struct rw_semaphore
*sem
)
271 if (sem
->read_bias_granted
)
273 if (sem
->write_bias_granted
)
275 if (atomic_read(&sem
->readers
))
277 if (atomic_read(&sem
->writers
) != 1)
279 atomic_dec(&sem
->writers
);
284 #endif /* __ASM_SH_SEMAPHORE_H */