drivers/parisc/: Spelling fixes
[sfrench/cifs-2.6.git] / arch / sparc64 / kernel / semaphore.c
1 /* semaphore.c: Sparc64 semaphore implementation.
2  *
3  * This is basically the PPC semaphore scheme ported to use
4  * the sparc64 atomic instructions, so see the PPC code for
5  * credits.
6  */
7
8 #include <linux/sched.h>
9 #include <linux/errno.h>
10 #include <linux/init.h>
11
12 /*
13  * Atomically update sem->count.
14  * This does the equivalent of the following:
15  *
16  *      old_count = sem->count;
17  *      tmp = MAX(old_count, 0) + incr;
18  *      sem->count = tmp;
19  *      return old_count;
20  */
21 static inline int __sem_update_count(struct semaphore *sem, int incr)
22 {
23         int old_count, tmp;
24
25         __asm__ __volatile__("\n"
26 "       ! __sem_update_count old_count(%0) tmp(%1) incr(%4) &sem->count(%3)\n"
27 "1:     ldsw    [%3], %0\n"
28 "       mov     %0, %1\n"
29 "       cmp     %0, 0\n"
30 "       movl    %%icc, 0, %1\n"
31 "       add     %1, %4, %1\n"
32 "       cas     [%3], %0, %1\n"
33 "       cmp     %0, %1\n"
34 "       membar  #StoreLoad | #StoreStore\n"
35 "       bne,pn  %%icc, 1b\n"
36 "        nop\n"
37         : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
38         : "r" (&sem->count), "r" (incr), "m" (sem->count)
39         : "cc");
40
41         return old_count;
42 }
43
44 static void __up(struct semaphore *sem)
45 {
46         __sem_update_count(sem, 1);
47         wake_up(&sem->wait);
48 }
49
50 void up(struct semaphore *sem)
51 {
52         /* This atomically does:
53          *      old_val = sem->count;
54          *      new_val = sem->count + 1;
55          *      sem->count = new_val;
56          *      if (old_val < 0)
57          *              __up(sem);
58          *
59          * The (old_val < 0) test is equivalent to
60          * the more straightforward (new_val <= 0),
61          * but it is easier to test the former because
62          * of how the CAS instruction works.
63          */
64
65         __asm__ __volatile__("\n"
66 "       ! up sem(%0)\n"
67 "       membar  #StoreLoad | #LoadLoad\n"
68 "1:     lduw    [%0], %%g1\n"
69 "       add     %%g1, 1, %%g7\n"
70 "       cas     [%0], %%g1, %%g7\n"
71 "       cmp     %%g1, %%g7\n"
72 "       bne,pn  %%icc, 1b\n"
73 "        addcc  %%g7, 1, %%g0\n"
74 "       membar  #StoreLoad | #StoreStore\n"
75 "       ble,pn  %%icc, 3f\n"
76 "        nop\n"
77 "2:\n"
78 "       .subsection 2\n"
79 "3:     mov     %0, %%g1\n"
80 "       save    %%sp, -160, %%sp\n"
81 "       call    %1\n"
82 "        mov    %%g1, %%o0\n"
83 "       ba,pt   %%xcc, 2b\n"
84 "        restore\n"
85 "       .previous\n"
86         : : "r" (sem), "i" (__up)
87         : "g1", "g2", "g3", "g7", "memory", "cc");
88 }
89
90 static void __sched __down(struct semaphore * sem)
91 {
92         struct task_struct *tsk = current;
93         DECLARE_WAITQUEUE(wait, tsk);
94
95         tsk->state = TASK_UNINTERRUPTIBLE;
96         add_wait_queue_exclusive(&sem->wait, &wait);
97
98         while (__sem_update_count(sem, -1) <= 0) {
99                 schedule();
100                 tsk->state = TASK_UNINTERRUPTIBLE;
101         }
102         remove_wait_queue(&sem->wait, &wait);
103         tsk->state = TASK_RUNNING;
104
105         wake_up(&sem->wait);
106 }
107
108 void __sched down(struct semaphore *sem)
109 {
110         might_sleep();
111         /* This atomically does:
112          *      old_val = sem->count;
113          *      new_val = sem->count - 1;
114          *      sem->count = new_val;
115          *      if (old_val < 1)
116          *              __down(sem);
117          *
118          * The (old_val < 1) test is equivalent to
119          * the more straightforward (new_val < 0),
120          * but it is easier to test the former because
121          * of how the CAS instruction works.
122          */
123
124         __asm__ __volatile__("\n"
125 "       ! down sem(%0)\n"
126 "1:     lduw    [%0], %%g1\n"
127 "       sub     %%g1, 1, %%g7\n"
128 "       cas     [%0], %%g1, %%g7\n"
129 "       cmp     %%g1, %%g7\n"
130 "       bne,pn  %%icc, 1b\n"
131 "        cmp    %%g7, 1\n"
132 "       membar  #StoreLoad | #StoreStore\n"
133 "       bl,pn   %%icc, 3f\n"
134 "        nop\n"
135 "2:\n"
136 "       .subsection 2\n"
137 "3:     mov     %0, %%g1\n"
138 "       save    %%sp, -160, %%sp\n"
139 "       call    %1\n"
140 "        mov    %%g1, %%o0\n"
141 "       ba,pt   %%xcc, 2b\n"
142 "        restore\n"
143 "       .previous\n"
144         : : "r" (sem), "i" (__down)
145         : "g1", "g2", "g3", "g7", "memory", "cc");
146 }
147
148 int down_trylock(struct semaphore *sem)
149 {
150         int ret;
151
152         /* This atomically does:
153          *      old_val = sem->count;
154          *      new_val = sem->count - 1;
155          *      if (old_val < 1) {
156          *              ret = 1;
157          *      } else {
158          *              sem->count = new_val;
159          *              ret = 0;
160          *      }
161          *
162          * The (old_val < 1) test is equivalent to
163          * the more straightforward (new_val < 0),
164          * but it is easier to test the former because
165          * of how the CAS instruction works.
166          */
167
168         __asm__ __volatile__("\n"
169 "       ! down_trylock sem(%1) ret(%0)\n"
170 "1:     lduw    [%1], %%g1\n"
171 "       sub     %%g1, 1, %%g7\n"
172 "       cmp     %%g1, 1\n"
173 "       bl,pn   %%icc, 2f\n"
174 "        mov    1, %0\n"
175 "       cas     [%1], %%g1, %%g7\n"
176 "       cmp     %%g1, %%g7\n"
177 "       bne,pn  %%icc, 1b\n"
178 "        mov    0, %0\n"
179 "       membar  #StoreLoad | #StoreStore\n"
180 "2:\n"
181         : "=&r" (ret)
182         : "r" (sem)
183         : "g1", "g7", "memory", "cc");
184
185         return ret;
186 }
187
188 static int __sched __down_interruptible(struct semaphore * sem)
189 {
190         int retval = 0;
191         struct task_struct *tsk = current;
192         DECLARE_WAITQUEUE(wait, tsk);
193
194         tsk->state = TASK_INTERRUPTIBLE;
195         add_wait_queue_exclusive(&sem->wait, &wait);
196
197         while (__sem_update_count(sem, -1) <= 0) {
198                 if (signal_pending(current)) {
199                         __sem_update_count(sem, 0);
200                         retval = -EINTR;
201                         break;
202                 }
203                 schedule();
204                 tsk->state = TASK_INTERRUPTIBLE;
205         }
206         tsk->state = TASK_RUNNING;
207         remove_wait_queue(&sem->wait, &wait);
208         wake_up(&sem->wait);
209         return retval;
210 }
211
212 int __sched down_interruptible(struct semaphore *sem)
213 {
214         int ret = 0;
215         
216         might_sleep();
217         /* This atomically does:
218          *      old_val = sem->count;
219          *      new_val = sem->count - 1;
220          *      sem->count = new_val;
221          *      if (old_val < 1)
222          *              ret = __down_interruptible(sem);
223          *
224          * The (old_val < 1) test is equivalent to
225          * the more straightforward (new_val < 0),
226          * but it is easier to test the former because
227          * of how the CAS instruction works.
228          */
229
230         __asm__ __volatile__("\n"
231 "       ! down_interruptible sem(%2) ret(%0)\n"
232 "1:     lduw    [%2], %%g1\n"
233 "       sub     %%g1, 1, %%g7\n"
234 "       cas     [%2], %%g1, %%g7\n"
235 "       cmp     %%g1, %%g7\n"
236 "       bne,pn  %%icc, 1b\n"
237 "        cmp    %%g7, 1\n"
238 "       membar  #StoreLoad | #StoreStore\n"
239 "       bl,pn   %%icc, 3f\n"
240 "        nop\n"
241 "2:\n"
242 "       .subsection 2\n"
243 "3:     mov     %2, %%g1\n"
244 "       save    %%sp, -160, %%sp\n"
245 "       call    %3\n"
246 "        mov    %%g1, %%o0\n"
247 "       ba,pt   %%xcc, 2b\n"
248 "        restore\n"
249 "       .previous\n"
250         : "=r" (ret)
251         : "0" (ret), "r" (sem), "i" (__down_interruptible)
252         : "g1", "g2", "g3", "g7", "memory", "cc");
253         return ret;
254 }