blob: 1516a642f9a57da31c0585a9f61eb1c9bc6841ed [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001#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 */
18static inline void wake_one_more(struct semaphore * sem)
19{
20 atomic_inc(&sem->waking);
21}
22
23#ifndef CONFIG_RMW_INSNS
24extern spinlock_t semaphore_wake_lock;
25#endif
26
27static 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 */
64static 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 }
99next:
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 */
110static 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