1/*
2 * BK Id: SCCS/s.semaphore.h 1.15 05/17/01 18:14:25 cort
3 */
4#ifndef _PPC_SEMAPHORE_H
5#define _PPC_SEMAPHORE_H
6
7/*
8 * Swiped from asm-sparc/semaphore.h and modified
9 * -- Cort (cort@cs.nmt.edu)
10 *
11 * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
12 * -- Ani Joshi (ajoshi@unixbox.com)
13 *
14 * Remove spinlock-based RW semaphores; RW semaphore definitions are
15 * now in rwsem.h and we use the the generic lib/rwsem.c implementation.
16 * Rework semaphores to use atomic_dec_if_positive.
17 * -- Paul Mackerras (paulus@samba.org)
18 */
19
20#ifdef __KERNEL__
21
22#include <asm/atomic.h>
23#include <asm/system.h>
24#include <linux/wait.h>
25#include <linux/rwsem.h>
26
27struct semaphore {
28	/*
29	 * Note that any negative value of count is equivalent to 0,
30	 * but additionally indicates that some process(es) might be
31	 * sleeping on `wait'.
32	 */
33	atomic_t count;
34	wait_queue_head_t wait;
35#if WAITQUEUE_DEBUG
36	long __magic;
37#endif
38};
39
40#if WAITQUEUE_DEBUG
41# define __SEM_DEBUG_INIT(name) \
42		, (long)&(name).__magic
43#else
44# define __SEM_DEBUG_INIT(name)
45#endif
46
47#define __SEMAPHORE_INITIALIZER(name, count) \
48	{ ATOMIC_INIT(count), \
49	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
50	  __SEM_DEBUG_INIT(name) }
51
52#define __MUTEX_INITIALIZER(name) \
53	__SEMAPHORE_INITIALIZER(name, 1)
54
55#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
56	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
57
58#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
59#define DECLARE_MUTEX_LOCKED(name)	__DECLARE_SEMAPHORE_GENERIC(name, 0)
60
61static inline void sema_init (struct semaphore *sem, int val)
62{
63	atomic_set(&sem->count, val);
64	init_waitqueue_head(&sem->wait);
65#if WAITQUEUE_DEBUG
66	sem->__magic = (long)&sem->__magic;
67#endif
68}
69
70static inline void init_MUTEX (struct semaphore *sem)
71{
72	sema_init(sem, 1);
73}
74
75static inline void init_MUTEX_LOCKED (struct semaphore *sem)
76{
77	sema_init(sem, 0);
78}
79
80extern void __down(struct semaphore * sem);
81extern int  __down_interruptible(struct semaphore * sem);
82extern void __up(struct semaphore * sem);
83
84extern inline void down(struct semaphore * sem)
85{
86#if WAITQUEUE_DEBUG
87	CHECK_MAGIC(sem->__magic);
88#endif
89
90	/*
91	 * Try to get the semaphore, take the slow path if we fail.
92	 */
93	if (atomic_dec_return(&sem->count) < 0)
94		__down(sem);
95	smp_wmb();
96}
97
98extern inline int down_interruptible(struct semaphore * sem)
99{
100	int ret = 0;
101
102#if WAITQUEUE_DEBUG
103	CHECK_MAGIC(sem->__magic);
104#endif
105
106	if (atomic_dec_return(&sem->count) < 0)
107		ret = __down_interruptible(sem);
108	smp_wmb();
109	return ret;
110}
111
112extern inline int down_trylock(struct semaphore * sem)
113{
114	int ret;
115
116#if WAITQUEUE_DEBUG
117	CHECK_MAGIC(sem->__magic);
118#endif
119
120	ret = atomic_dec_if_positive(&sem->count) < 0;
121	smp_wmb();
122	return ret;
123}
124
125extern inline void up(struct semaphore * sem)
126{
127#if WAITQUEUE_DEBUG
128	CHECK_MAGIC(sem->__magic);
129#endif
130
131	smp_wmb();
132	if (atomic_inc_return(&sem->count) <= 0)
133		__up(sem);
134}
135
136static inline int sem_getcount(struct semaphore *sem)
137{
138	return atomic_read(&sem->count);
139}
140
141#endif /* __KERNEL__ */
142
143#endif /* !(_PPC_SEMAPHORE_H) */
144