1#ifndef __ASM_SH_SEMAPHORE_HELPER_H
2#define __ASM_SH_SEMAPHORE_HELPER_H
3
4/*
5 * SMP- and interrupt-safe semaphores helper functions.
6 *
7 * (C) Copyright 1996 Linus Torvalds
8 * (C) Copyright 1999 Andrea Arcangeli
9 */
10
11/*
12 * These two _must_ execute atomically wrt each other.
13 *
14 * This is trivially done with load_locked/store_cond,
15 * which we have.  Let the rest of the losers suck eggs.
16 */
17static __inline__ void wake_one_more(struct semaphore * sem)
18{
19	atomic_inc((atomic_t *)&sem->sleepers);
20}
21
22static __inline__ int waking_non_zero(struct semaphore *sem)
23{
24	unsigned long flags;
25	int ret = 0;
26
27	spin_lock_irqsave(&semaphore_wake_lock, flags);
28	if (sem->sleepers > 0) {
29		sem->sleepers--;
30		ret = 1;
31	}
32	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
33	return ret;
34}
35
36/*
37 * waking_non_zero_interruptible:
38 *	1	got the lock
39 *	0	go to sleep
40 *	-EINTR	interrupted
41 *
42 * We must undo the sem->count down_interruptible() increment while we are
43 * protected by the spinlock in order to make atomic this atomic_inc() with the
44 * atomic_read() in wake_one_more(), otherwise we can race. -arca
45 */
46static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
47						struct task_struct *tsk)
48{
49	unsigned long flags;
50	int ret = 0;
51
52	spin_lock_irqsave(&semaphore_wake_lock, flags);
53	if (sem->sleepers > 0) {
54		sem->sleepers--;
55		ret = 1;
56	} else if (signal_pending(tsk)) {
57		atomic_inc(&sem->count);
58		ret = -EINTR;
59	}
60	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
61	return ret;
62}
63
64/*
65 * waking_non_zero_trylock:
66 *	1	failed to lock
67 *	0	got the lock
68 *
69 * We must undo the sem->count down_trylock() increment while we are
70 * protected by the spinlock in order to make atomic this atomic_inc() with the
71 * atomic_read() in wake_one_more(), otherwise we can race. -arca
72 */
73static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
74{
75	unsigned long flags;
76	int ret = 1;
77
78	spin_lock_irqsave(&semaphore_wake_lock, flags);
79	if (sem->sleepers <= 0)
80		atomic_inc(&sem->count);
81	else {
82		sem->sleepers--;
83		ret = 0;
84	}
85	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
86	return ret;
87}
88
89#endif /* __ASM_SH_SEMAPHORE_HELPER_H */
90