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