OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [include/] [asm-s390/] [rwsem.h] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1276 phoenix
#ifndef _S390_RWSEM_H
2
#define _S390_RWSEM_H
3
 
4
/*
5
 *  include/asm-s390/rwsem.h
6
 *
7
 *  S390 version
8
 *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
9
 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
10
 *
11
 *  Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
12
 */
13
 
14
/*
15
 *
16
 * The MSW of the count is the negated number of active writers and waiting
17
 * lockers, and the LSW is the total number of active locks
18
 *
19
 * The lock count is initialized to 0 (no active and no waiting lockers).
20
 *
21
 * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case of an
22
 * uncontended lock. This can be determined because XADD returns the old value.
23
 * Readers increment by 1 and see a positive value when uncontended, negative
24
 * if there are writers (and maybe) readers waiting (in which case it goes to
25
 * sleep).
26
 *
27
 * The value of WAITING_BIAS supports up to 32766 waiting processes. This can
28
 * be extended to 65534 by manually checking the whole MSW rather than relying
29
 * on the S flag.
30
 *
31
 * The value of ACTIVE_BIAS supports up to 65535 active processes.
32
 *
33
 * This should be totally fair - if anything is waiting, a process that wants a
34
 * lock will go to the back of the queue. When the currently active lock is
35
 * released, if there's a writer at the front of the queue, then that and only
36
 * that will be woken up; if there's a bunch of consequtive readers at the
37
 * front, then they'll all be woken up, but no other readers will be.
38
 */
39
 
40
#ifndef _LINUX_RWSEM_H
41
#error please dont include asm/rwsem.h directly, use linux/rwsem.h instead
42
#endif
43
 
44
#ifdef __KERNEL__
45
 
46
#include <linux/list.h>
47
#include <linux/spinlock.h>
48
 
49
struct rwsem_waiter;
50
 
51
extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
52
extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
53
extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
54
 
55
/*
56
 * the semaphore definition
57
 */
58
struct rw_semaphore {
59
        signed long             count;
60
        spinlock_t              wait_lock;
61
        struct list_head        wait_list;
62
};
63
 
64
#define RWSEM_UNLOCKED_VALUE    0x00000000
65
#define RWSEM_ACTIVE_BIAS       0x00000001
66
#define RWSEM_ACTIVE_MASK       0x0000ffff
67
#define RWSEM_WAITING_BIAS      (-0x00010000)
68
#define RWSEM_ACTIVE_READ_BIAS  RWSEM_ACTIVE_BIAS
69
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
70
 
71
/*
72
 * initialisation
73
 */
74
#define __RWSEM_INITIALIZER(name) \
75
{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, LIST_HEAD_INIT((name).wait_list) }
76
 
77
#define DECLARE_RWSEM(name) \
78
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
79
 
80
static inline void init_rwsem(struct rw_semaphore *sem)
81
{
82
        sem->count = RWSEM_UNLOCKED_VALUE;
83
        spin_lock_init(&sem->wait_lock);
84
        INIT_LIST_HEAD(&sem->wait_list);
85
}
86
 
87
/*
88
 * lock for reading
89
 */
90
static inline void __down_read(struct rw_semaphore *sem)
91
{
92
        signed long old, new;
93
 
94
        __asm__ __volatile__(
95
                "   l    %0,0(%2)\n"
96
                "0: lr   %1,%0\n"
97
                "   ahi  %1,%3\n"
98
                "   cs   %0,%1,0(%2)\n"
99
                "   jl   0b"
100
                : "=&d" (old), "=&d" (new)
101
                : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
102
                : "cc", "memory" );
103
        if (old < 0)
104
                rwsem_down_read_failed(sem);
105
}
106
 
107
/*
108
 * trylock for reading -- returns 1 if successful, 0 if contention
109
 */
110
static inline int __down_read_trylock(struct rw_semaphore *sem)
111
{
112
        signed long old, new;
113
 
114
        __asm__ __volatile__(
115
                "   l    %0,0(%2)\n"
116
                "0: ltr  %1,%0\n"
117
                "   jm   1f\n"
118
                "   ahi  %1,%3\n"
119
                "   cs   %0,%1,0(%2)\n"
120
                "   jl   0b\n"
121
                "1:"
122
                : "=&d" (old), "=&d" (new)
123
                : "a" (&sem->count), "i" (RWSEM_ACTIVE_READ_BIAS)
124
                : "cc", "memory" );
125
        return old >= 0 ? 1 : 0;
126
}
127
 
128
/*
129
 * lock for writing
130
 */
131
static inline void __down_write(struct rw_semaphore *sem)
132
{
133
        signed long old, new, tmp;
134
 
135
        tmp = RWSEM_ACTIVE_WRITE_BIAS;
136
        __asm__ __volatile__(
137
                "   l    %0,0(%2)\n"
138
                "0: lr   %1,%0\n"
139
                "   a    %1,%3\n"
140
                "   cs   %0,%1,0(%2)\n"
141
                "   jl   0b"
142
                : "=&d" (old), "=&d" (new)
143
                : "a" (&sem->count), "m" (tmp)
144
                : "cc", "memory" );
145
        if (old != 0)
146
                rwsem_down_write_failed(sem);
147
}
148
 
149
/*
150
 * trylock for writing -- returns 1 if successful, 0 if contention
151
 */
152
static inline int __down_write_trylock(struct rw_semaphore *sem)
153
{
154
        signed long old;
155
 
156
        __asm__ __volatile__(
157
                "   l    %0,0(%1)\n"
158
                "0: ltr  %0,%0\n"
159
                "   jnz  1f\n"
160
                "   cs   %0,%2,0(%1)\n"
161
                "   jl   0b\n"
162
                "1:"
163
                : "=&d" (old)
164
                : "a" (&sem->count), "d" (RWSEM_ACTIVE_WRITE_BIAS)
165
                : "cc", "memory" );
166
        return (old == RWSEM_UNLOCKED_VALUE) ? 1 : 0;
167
}
168
 
169
/*
170
 * unlock after reading
171
 */
172
static inline void __up_read(struct rw_semaphore *sem)
173
{
174
        signed long old, new;
175
 
176
        __asm__ __volatile__(
177
                "   l    %0,0(%2)\n"
178
                "0: lr   %1,%0\n"
179
                "   ahi  %1,%3\n"
180
                "   cs   %0,%1,0(%2)\n"
181
                "   jl   0b"
182
                : "=&d" (old), "=&d" (new)
183
                : "a" (&sem->count), "i" (-RWSEM_ACTIVE_READ_BIAS)
184
                : "cc", "memory" );
185
        if (new < 0)
186
                if ((new & RWSEM_ACTIVE_MASK) == 0)
187
                        rwsem_wake(sem);
188
}
189
 
190
/*
191
 * unlock after writing
192
 */
193
static inline void __up_write(struct rw_semaphore *sem)
194
{
195
        signed long old, new, tmp;
196
 
197
        tmp = -RWSEM_ACTIVE_WRITE_BIAS;
198
        __asm__ __volatile__(
199
                "   l    %0,0(%2)\n"
200
                "0: lr   %1,%0\n"
201
                "   a    %1,%3\n"
202
                "   cs   %0,%1,0(%2)\n"
203
                "   jl   0b"
204
                : "=&d" (old), "=&d" (new)
205
                : "a" (&sem->count), "m" (tmp)
206
                : "cc", "memory" );
207
        if (new < 0)
208
                if ((new & RWSEM_ACTIVE_MASK) == 0)
209
                        rwsem_wake(sem);
210
}
211
 
212
/*
213
 * implement atomic add functionality
214
 */
215
static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
216
{
217
        signed long old, new;
218
 
219
        __asm__ __volatile__(
220
                "   l    %0,0(%2)\n"
221
                "0: lr   %1,%0\n"
222
                "   ar   %1,%3\n"
223
                "   cs   %0,%1,0(%2)\n"
224
                "   jl   0b"
225
                : "=&d" (old), "=&d" (new)
226
                : "a" (&sem->count), "d" (delta)
227
                : "cc", "memory" );
228
}
229
 
230
/*
231
 * implement exchange and add functionality
232
 */
233
static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
234
{
235
        signed long old, new;
236
 
237
        __asm__ __volatile__(
238
                "   l    %0,0(%2)\n"
239
                "0: lr   %1,%0\n"
240
                "   ar   %1,%3\n"
241
                "   cs   %0,%1,0(%2)\n"
242
                "   jl   0b"
243
                : "=&d" (old), "=&d" (new)
244
                : "a" (&sem->count), "d" (delta)
245
                : "cc", "memory" );
246
        return new;
247
}
248
 
249
#endif /* __KERNEL__ */
250
#endif /* _S390_RWSEM_H */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.