1 /*
2 * include/asm-s390/semaphore.h
3 *
4 * S390 version
5 * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 *
7 * Derived from "include/asm-i386/semaphore.h"
8 * (C) Copyright 1996 Linus Torvalds
9 */
10
11 #ifndef _S390_SEMAPHORE_H
12 #define _S390_SEMAPHORE_H
13
14 #include <asm/system.h>
15 #include <asm/atomic.h>
16 #include <linux/wait.h>
17
18 struct semaphore {
19 atomic_t count;
20 int sleepers;
21 wait_queue_head_t wait;
22 };
23
24 #define __SEM_DEBUG_INIT(name)
25
26 #define __SEMAPHORE_INITIALIZER(name,count) \
27 { ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
28 __SEM_DEBUG_INIT(name) }
29
30 #define __MUTEX_INITIALIZER(name) \
31 __SEMAPHORE_INITIALIZER(name,1)
32
33 #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
34 struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
35
36 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
37 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
38
39 extern inline void sema_init (struct semaphore *sem, int val)
40 {
41 *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
42 }
43
44 static inline void init_MUTEX (struct semaphore *sem)
45 {
46 sema_init(sem, 1);
47 }
48
49 static inline void init_MUTEX_LOCKED (struct semaphore *sem)
50 {
51 sema_init(sem, 0);
52 }
53
54 asmlinkage void __down_failed(void /* special register calling convention */);
55 asmlinkage int __down_failed_interruptible(void /* params in registers */);
56 asmlinkage int __down_failed_trylock(void /* params in registers */);
57 asmlinkage void __up_wakeup(void /* special register calling convention */);
58
59 asmlinkage void __down(struct semaphore * sem);
60 asmlinkage int __down_interruptible(struct semaphore * sem);
61 asmlinkage int __down_trylock(struct semaphore * sem);
62 asmlinkage void __up(struct semaphore * sem);
63
64 extern inline void down(struct semaphore * sem)
65 {
66 if (atomic_dec_return(&sem->count) < 0)
67 __down(sem);
68 }
69
70 extern inline int down_interruptible(struct semaphore * sem)
71 {
72 int ret = 0;
73
74 if (atomic_dec_return(&sem->count) < 0)
75 ret = __down_interruptible(sem);
76 return ret;
77 }
78
79 extern inline int down_trylock(struct semaphore * sem)
80 {
81 int ret = 0;
82
83 if (atomic_dec_return(&sem->count) < 0)
84 ret = __down_trylock(sem);
85 return ret;
86 }
87
88 extern inline void up(struct semaphore * sem)
89 {
90 if (atomic_inc_return(&sem->count) <= 0)
91 __up(sem);
92 }
93
94 /* rw mutexes (should that be mutices? =) -- throw rw
95 * spinlocks and semaphores together, and this is what we
96 * end up with...
97 *
98 * The lock is initialized to BIAS. This way, a writer
99 * subtracts BIAS ands gets 0 for the case of an uncontended
100 * lock. Readers decrement by 1 and see a positive value
101 * when uncontended, negative if there are writers waiting
102 * (in which case it goes to sleep).
103 *
104 * The value 0x01000000 supports up to 128 processors and
105 * lots of processes. BIAS must be chosen such that subl'ing
106 * BIAS once per CPU will result in the long remaining
107 * negative.
108 *
109 * In terms of fairness, this should result in the lock
110 * flopping back and forth between readers and writers
111 * under heavy use.
112 *
113 * -ben
114 */
115 struct rw_semaphore {
116 atomic_t count;
117 volatile unsigned int write_bias_granted;
118 volatile unsigned int read_bias_granted;
119 wait_queue_head_t wait;
120 wait_queue_head_t write_bias_wait;
121 };
122
123 #define RW_LOCK_BIAS 0x01000000
124
125 #define __RWSEM_DEBUG_INIT /* */
126
127 #define __RWSEM_INITIALIZER(name,count) \
128 { ATOMIC_INIT(count), 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
129 __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
130 __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
131
132 #define __DECLARE_RWSEM_GENERIC(name,count) \
133 struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
134
135 #define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
136 #define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
137 #define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
138
139 extern inline void init_rwsem(struct rw_semaphore *sem)
140 {
141 atomic_set(&sem->count, RW_LOCK_BIAS);
142 sem->read_bias_granted = 0;
143 sem->write_bias_granted = 0;
144 init_waitqueue_head(&sem->wait);
145 init_waitqueue_head(&sem->write_bias_wait);
146 }
147
148 extern void __down_read_failed(int, struct rw_semaphore *);
149 extern void __down_write_failed(int, struct rw_semaphore *);
150 extern void __rwsem_wake(int, struct rw_semaphore *);
151
152 extern inline void down_read(struct rw_semaphore *sem)
153 {
154 int count;
155 count = atomic_dec_return(&sem->count);
156 if (count < 0)
157 __down_read_failed(count, sem);
158 }
159
160 extern inline void down_write(struct rw_semaphore *sem)
161 {
162 int count;
163 count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
164 if (count < 0)
165 __down_write_failed(count, sem);
166 }
167
168 /* When a reader does a release, the only significant
169 * case is when there was a writer waiting, and we've
170 * bumped the count to 0: we must wake the writer up.
171 */
172 extern inline void up_read(struct rw_semaphore *sem)
173 {
174 int count;
175 count = atomic_inc_return(&sem->count);
176 if (count == 0)
177 __rwsem_wake(count, sem);
178 }
179
180 /* releasing the writer is easy -- just release it and
181 * wake up any sleepers.
182 */
183 extern inline void up_write(struct rw_semaphore *sem)
184 {
185 int count;
186 count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
187 if (count >= 0 && count < RW_LOCK_BIAS)
188 __rwsem_wake(count, sem);
189 }
190
191 #endif
192
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.