clean
[linux-2.4.21-pre4.git] / include / asm-ppc / semaphore.h
1 /*
2  * BK Id: SCCS/s.semaphore.h 1.19 12/19/02 16:32:51 paulus
3  */
4 #ifndef _PPC_SEMAPHORE_H
5 #define _PPC_SEMAPHORE_H
6
7 /*
8  * Swiped from asm-sparc/semaphore.h and modified
9  * -- Cort (cort@cs.nmt.edu)
10  *
11  * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
12  * -- Ani Joshi (ajoshi@unixbox.com)
13  *
14  * Remove spinlock-based RW semaphores; RW semaphore definitions are
15  * now in rwsem.h and we use the generic lib/rwsem.c implementation.
16  * Rework semaphores to use atomic_dec_if_positive.
17  * -- Paul Mackerras (paulus@samba.org)
18  */
19
20 #ifdef __KERNEL__
21
22 #include <asm/atomic.h>
23 #include <asm/system.h>
24 #include <linux/wait.h>
25 #include <linux/rwsem.h>
26
27 struct semaphore {
28         /*
29          * Note that any negative value of count is equivalent to 0,
30          * but additionally indicates that some process(es) might be
31          * sleeping on `wait'.
32          */
33         atomic_t count;
34         wait_queue_head_t wait;
35 #if WAITQUEUE_DEBUG
36         long __magic;
37 #endif
38 };
39
40 #if WAITQUEUE_DEBUG
41 # define __SEM_DEBUG_INIT(name) \
42                 , (long)&(name).__magic
43 #else
44 # define __SEM_DEBUG_INIT(name)
45 #endif
46
47 #define __SEMAPHORE_INITIALIZER(name, count) \
48         { ATOMIC_INIT(count), \
49           __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
50           __SEM_DEBUG_INIT(name) }
51
52 #define __MUTEX_INITIALIZER(name) \
53         __SEMAPHORE_INITIALIZER(name, 1)
54
55 #define __DECLARE_SEMAPHORE_GENERIC(name, count) \
56         struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
57
58 #define DECLARE_MUTEX(name)             __DECLARE_SEMAPHORE_GENERIC(name, 1)
59 #define DECLARE_MUTEX_LOCKED(name)      __DECLARE_SEMAPHORE_GENERIC(name, 0)
60
61 static inline void sema_init (struct semaphore *sem, int val)
62 {
63         atomic_set(&sem->count, val);
64         init_waitqueue_head(&sem->wait);
65 #if WAITQUEUE_DEBUG
66         sem->__magic = (long)&sem->__magic;
67 #endif
68 }
69
70 static inline void init_MUTEX (struct semaphore *sem)
71 {
72         sema_init(sem, 1);
73 }
74
75 static inline void init_MUTEX_LOCKED (struct semaphore *sem)
76 {
77         sema_init(sem, 0);
78 }
79
80 extern void __down(struct semaphore * sem);
81 extern int  __down_interruptible(struct semaphore * sem);
82 extern void __up(struct semaphore * sem);
83
84 extern inline void down(struct semaphore * sem)
85 {
86 #if WAITQUEUE_DEBUG
87         CHECK_MAGIC(sem->__magic);
88 #endif
89
90         /*
91          * Try to get the semaphore, take the slow path if we fail.
92          */
93         if (atomic_dec_return(&sem->count) < 0)
94                 __down(sem);
95         smp_wmb();
96 }
97
98 extern inline int down_interruptible(struct semaphore * sem)
99 {
100         int ret = 0;
101
102 #if WAITQUEUE_DEBUG
103         CHECK_MAGIC(sem->__magic);
104 #endif
105
106         if (atomic_dec_return(&sem->count) < 0)
107                 ret = __down_interruptible(sem);
108         smp_wmb();
109         return ret;
110 }
111
112 extern inline int down_trylock(struct semaphore * sem)
113 {
114         int ret;
115
116 #if WAITQUEUE_DEBUG
117         CHECK_MAGIC(sem->__magic);
118 #endif
119
120         ret = atomic_dec_if_positive(&sem->count) < 0;
121         smp_wmb();
122         return ret;
123 }
124
125 extern inline void up(struct semaphore * sem)
126 {
127 #if WAITQUEUE_DEBUG
128         CHECK_MAGIC(sem->__magic);
129 #endif
130
131         smp_wmb();
132         if (atomic_inc_return(&sem->count) <= 0)
133                 __up(sem);
134 }
135
136 static inline int sem_getcount(struct semaphore *sem)
137 {
138         return atomic_read(&sem->count);
139 }
140
141 #endif /* __KERNEL__ */
142
143 #endif /* !(_PPC_SEMAPHORE_H) */