patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / include / asm-alpha / semaphore.h
1 #ifndef _ALPHA_SEMAPHORE_H
2 #define _ALPHA_SEMAPHORE_H
3
4 /*
5  * SMP- and interrupt-safe semaphores..
6  *
7  * (C) Copyright 1996 Linus Torvalds
8  * (C) Copyright 1996, 2000 Richard Henderson
9  */
10
11 #include <asm/current.h>
12 #include <asm/system.h>
13 #include <asm/atomic.h>
14 #include <linux/compiler.h>
15 #include <linux/wait.h>
16 #include <linux/rwsem.h>
17
18 struct semaphore {
19         atomic_t count;
20         wait_queue_head_t wait;
21 #ifdef WAITQUEUE_DEBUG
22         long __magic;
23 #endif
24 };
25
26 #ifdef WAITQUEUE_DEBUG
27 # define __SEM_DEBUG_INIT(name)         , (long)&(name).__magic
28 #else
29 # define __SEM_DEBUG_INIT(name)
30 #endif
31
32 #define __SEMAPHORE_INITIALIZER(name,count)             \
33         { ATOMIC_INIT(count),                           \
34           __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
35           __SEM_DEBUG_INIT(name) }
36
37 #define __MUTEX_INITIALIZER(name)                       \
38         __SEMAPHORE_INITIALIZER(name,1)
39
40 #define __DECLARE_SEMAPHORE_GENERIC(name,count)         \
41         struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
42
43 #define DECLARE_MUTEX(name)             __DECLARE_SEMAPHORE_GENERIC(name,1)
44 #define DECLARE_MUTEX_LOCKED(name)      __DECLARE_SEMAPHORE_GENERIC(name,0)
45
46 static inline void sema_init(struct semaphore *sem, int val)
47 {
48         /*
49          * Logically, 
50          *   *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
51          * except that gcc produces better initializing by parts yet.
52          */
53
54         atomic_set(&sem->count, val);
55         init_waitqueue_head(&sem->wait);
56 #ifdef WAITQUEUE_DEBUG
57         sem->__magic = (long)&sem->__magic;
58 #endif
59 }
60
61 static inline void init_MUTEX (struct semaphore *sem)
62 {
63         sema_init(sem, 1);
64 }
65
66 static inline void init_MUTEX_LOCKED (struct semaphore *sem)
67 {
68         sema_init(sem, 0);
69 }
70
71 extern void down(struct semaphore *);
72 extern void __down_failed(struct semaphore *);
73 extern int  down_interruptible(struct semaphore *);
74 extern int  __down_failed_interruptible(struct semaphore *);
75 extern int  down_trylock(struct semaphore *);
76 extern void up(struct semaphore *);
77 extern void __up_wakeup(struct semaphore *);
78
79 /*
80  * Hidden out of line code is fun, but extremely messy.  Rely on newer
81  * compilers to do a respectable job with this.  The contention cases
82  * are handled out of line in arch/alpha/kernel/semaphore.c.
83  */
84
85 static inline void __down(struct semaphore *sem)
86 {
87         long count;
88         might_sleep();
89         count = atomic_dec_return(&sem->count);
90         if (unlikely(count < 0))
91                 __down_failed(sem);
92 }
93
94 static inline int __down_interruptible(struct semaphore *sem)
95 {
96         long count;
97         might_sleep();
98         count = atomic_dec_return(&sem->count);
99         if (unlikely(count < 0))
100                 return __down_failed_interruptible(sem);
101         return 0;
102 }
103
104 /*
105  * down_trylock returns 0 on success, 1 if we failed to get the lock.
106  */
107
108 static inline int __down_trylock(struct semaphore *sem)
109 {
110         long ret;
111
112         /* "Equivalent" C:
113
114            do {
115                 ret = ldl_l;
116                 --ret;
117                 if (ret < 0)
118                         break;
119                 ret = stl_c = ret;
120            } while (ret == 0);
121         */
122         __asm__ __volatile__(
123                 "1:     ldl_l   %0,%1\n"
124                 "       subl    %0,1,%0\n"
125                 "       blt     %0,2f\n"
126                 "       stl_c   %0,%1\n"
127                 "       beq     %0,3f\n"
128                 "       mb\n"
129                 "2:\n"
130                 ".subsection 2\n"
131                 "3:     br      1b\n"
132                 ".previous"
133                 : "=&r" (ret), "=m" (sem->count)
134                 : "m" (sem->count));
135
136         return ret < 0;
137 }
138
139 static inline void __up(struct semaphore *sem)
140 {
141         if (unlikely(atomic_inc_return(&sem->count) <= 0))
142                 __up_wakeup(sem);
143 }
144
145 #if !defined(WAITQUEUE_DEBUG) && !defined(CONFIG_DEBUG_SEMAPHORE)
146 extern inline void down(struct semaphore *sem)
147 {
148         __down(sem);
149 }
150 extern inline int down_interruptible(struct semaphore *sem)
151 {
152         return __down_interruptible(sem);
153 }
154 extern inline int down_trylock(struct semaphore *sem)
155 {
156         return __down_trylock(sem);
157 }
158 extern inline void up(struct semaphore *sem)
159 {
160         __up(sem);
161 }
162 #endif
163
164 #endif