1/* $Id: semaphore-helper.h,v 1.1.1.1 2007/08/03 18:53:22 Exp $
2 *
3 * SMP- and interrupt-safe semaphores helper functions. Generic versions, no
4 * optimizations whatsoever...
5 *
6 */
7
8#ifndef _ASM_SEMAPHORE_HELPER_H
9#define _ASM_SEMAPHORE_HELPER_H
10
11#include <asm/atomic.h>
12#include <linux/errno.h>
13
14#define read(a) ((a)->counter)
15#define inc(a) (((a)->counter)++)
16#define dec(a) (((a)->counter)--)
17
18#define count_inc(a) ((*(a))++)
19
20/*
21 * These two _must_ execute atomically wrt each other.
22 */
23static inline void wake_one_more(struct semaphore * sem)
24{
25	atomic_inc(&sem->waking);
26}
27
28static inline int waking_non_zero(struct semaphore *sem)
29{
30	unsigned long flags;
31	int ret = 0;
32
33	local_irq_save(flags);
34	if (read(&sem->waking) > 0) {
35		dec(&sem->waking);
36		ret = 1;
37	}
38	local_irq_restore(flags);
39	return ret;
40}
41
42static inline int waking_non_zero_interruptible(struct semaphore *sem,
43						struct task_struct *tsk)
44{
45	int ret = 0;
46	unsigned long flags;
47
48	local_irq_save(flags);
49	if (read(&sem->waking) > 0) {
50		dec(&sem->waking);
51		ret = 1;
52	} else if (signal_pending(tsk)) {
53		inc(&sem->count);
54		ret = -EINTR;
55	}
56	local_irq_restore(flags);
57	return ret;
58}
59
60static inline int waking_non_zero_trylock(struct semaphore *sem)
61{
62        int ret = 1;
63	unsigned long flags;
64
65	local_irq_save(flags);
66	if (read(&sem->waking) <= 0)
67		inc(&sem->count);
68	else {
69		dec(&sem->waking);
70		ret = 0;
71	}
72	local_irq_restore(flags);
73	return ret;
74}
75
76#endif /* _ASM_SEMAPHORE_HELPER_H */
77