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/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
143