ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / include / asm-m68k / semaphore-helper.h
1 #ifndef _M68K_SEMAPHORE_HELPER_H
2 #define _M68K_SEMAPHORE_HELPER_H
3
4 /*
5  * SMP- and interrupt-safe semaphores helper functions.
6  *
7  * (C) Copyright 1996 Linus Torvalds
8  *
9  * m68k version by Andreas Schwab
10  */
11
12 #include <linux/config.h>
13 #include <linux/errno.h>
14
15 /*
16  * These two _must_ execute atomically wrt each other.
17  */
18 static inline void wake_one_more(struct semaphore * sem)
19 {
20         atomic_inc(&sem->waking);
21 }
22
23 #ifndef CONFIG_RMW_INSNS
24 extern spinlock_t semaphore_wake_lock;
25 #endif
26
27 static inline int waking_non_zero(struct semaphore *sem)
28 {
29         int ret;
30 #ifndef CONFIG_RMW_INSNS
31         unsigned long flags;
32
33         spin_lock_irqsave(&semaphore_wake_lock, flags);
34         ret = 0;
35         if (atomic_read(&sem->waking) > 0) {
36                 atomic_dec(&sem->waking);
37                 ret = 1;
38         }
39         spin_unlock_irqrestore(&semaphore_wake_lock, flags);
40 #else
41         int tmp1, tmp2;
42
43         __asm__ __volatile__
44           ("1:  movel   %1,%2\n"
45            "    jle     2f\n"
46            "    subql   #1,%2\n"
47            "    casl    %1,%2,%3\n"
48            "    jne     1b\n"
49            "    moveq   #1,%0\n"
50            "2:"
51            : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
52            : "m" (sem->waking), "0" (0), "1" (sem->waking));
53 #endif
54
55         return ret;
56 }
57
58 /*
59  * waking_non_zero_interruptible:
60  *      1       got the lock
61  *      0       go to sleep
62  *      -EINTR  interrupted
63  */
64 static inline int waking_non_zero_interruptible(struct semaphore *sem,
65                                                 struct task_struct *tsk)
66 {
67         int ret;
68 #ifndef CONFIG_RMW_INSNS
69         unsigned long flags;
70
71         spin_lock_irqsave(&semaphore_wake_lock, flags);
72         ret = 0;
73         if (atomic_read(&sem->waking) > 0) {
74                 atomic_dec(&sem->waking);
75                 ret = 1;
76         } else if (signal_pending(tsk)) {
77                 atomic_inc(&sem->count);
78                 ret = -EINTR;
79         }
80         spin_unlock_irqrestore(&semaphore_wake_lock, flags);
81 #else
82         int tmp1, tmp2;
83
84         __asm__ __volatile__
85           ("1:  movel   %1,%2\n"
86            "    jle     2f\n"
87            "    subql   #1,%2\n"
88            "    casl    %1,%2,%3\n"
89            "    jne     1b\n"
90            "    moveq   #1,%0\n"
91            "    jra     %a4\n"
92            "2:"
93            : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
94            : "m" (sem->waking), "i" (&&next), "0" (0), "1" (sem->waking));
95         if (signal_pending(tsk)) {
96                 atomic_inc(&sem->count);
97                 ret = -EINTR;
98         }
99 next:
100 #endif
101
102         return ret;
103 }
104
105 /*
106  * waking_non_zero_trylock:
107  *      1       failed to lock
108  *      0       got the lock
109  */
110 static inline int waking_non_zero_trylock(struct semaphore *sem)
111 {
112         int ret;
113 #ifndef CONFIG_RMW_INSNS
114         unsigned long flags;
115
116         spin_lock_irqsave(&semaphore_wake_lock, flags);
117         ret = 1;
118         if (atomic_read(&sem->waking) > 0) {
119                 atomic_dec(&sem->waking);
120                 ret = 0;
121         } else
122                 atomic_inc(&sem->count);
123         spin_unlock_irqrestore(&semaphore_wake_lock, flags);
124 #else
125         int tmp1, tmp2;
126
127         __asm__ __volatile__
128           ("1:  movel   %1,%2\n"
129            "    jle     2f\n"
130            "    subql   #1,%2\n"
131            "    casl    %1,%2,%3\n"
132            "    jne     1b\n"
133            "    moveq   #0,%0\n"
134            "2:"
135            : "=d" (ret), "=d" (tmp1), "=d" (tmp2)
136            : "m" (sem->waking), "0" (1), "1" (sem->waking));
137         if (ret)
138                 atomic_inc(&sem->count);
139 #endif
140         return ret;
141 }
142
143 #endif