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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * asm-ia64/rwsem.h: R/W semaphores for ia64
3
 *
4
 * Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com>
5
 * Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com>
6
 *
7
 * Based on asm-i386/rwsem.h and other architecture implementation.
8
 *
9
 * The MSW of the count is the negated number of active writers and
10
 * waiting lockers, and the LSW is the total number of active locks.
11
 *
12
 * The lock count is initialized to 0 (no active and no waiting lockers).
13
 *
14
 * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case
15
 * of an uncontended lock. Readers increment by 1 and see a positive value
16
 * when uncontended, negative if there are writers (and maybe) readers
17
 * waiting (in which case it goes to sleep).
18
 */
19
 
20
#ifndef _ASM_IA64_RWSEM_H
21
#define _ASM_IA64_RWSEM_H
22
 
23
#include <linux/list.h>
24
#include <linux/spinlock.h>
25
 
26
/*
27
 * the semaphore definition
28
 */
29
struct rw_semaphore {
30
        signed int              count;
31
        spinlock_t              wait_lock;
32
        struct list_head        wait_list;
33
#if RWSEM_DEBUG
34
        int                     debug;
35
#endif
36
};
37
 
38
#define RWSEM_UNLOCKED_VALUE            0x00000000
39
#define RWSEM_ACTIVE_BIAS               0x00000001
40
#define RWSEM_ACTIVE_MASK               0x0000ffff
41
#define RWSEM_WAITING_BIAS              (-0x00010000)
42
#define RWSEM_ACTIVE_READ_BIAS          RWSEM_ACTIVE_BIAS
43
#define RWSEM_ACTIVE_WRITE_BIAS         (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
44
 
45
/*
46
 * initialization
47
 */
48
#if RWSEM_DEBUG
49
#define __RWSEM_DEBUG_INIT      , 0
50
#else
51
#define __RWSEM_DEBUG_INIT      /* */
52
#endif
53
 
54
#define __RWSEM_INITIALIZER(name) \
55
        { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
56
          LIST_HEAD_INIT((name).wait_list) \
57
          __RWSEM_DEBUG_INIT }
58
 
59
#define DECLARE_RWSEM(name) \
60
        struct rw_semaphore name = __RWSEM_INITIALIZER(name)
61
 
62
extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
63
extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
64
extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
65
extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
66
 
67
static inline void
68
init_rwsem (struct rw_semaphore *sem)
69
{
70
        sem->count = RWSEM_UNLOCKED_VALUE;
71
        spin_lock_init(&sem->wait_lock);
72
        INIT_LIST_HEAD(&sem->wait_list);
73
#if RWSEM_DEBUG
74
        sem->debug = 0;
75
#endif
76
}
77
 
78
/*
79
 * lock for reading
80
 */
81
static inline void
82
__down_read (struct rw_semaphore *sem)
83
{
84
        int result;
85
        __asm__ __volatile__ ("fetchadd4.acq %0=[%1],1" :
86
                              "=r"(result) : "r"(&sem->count) : "memory");
87
        if (result < 0)
88
                rwsem_down_read_failed(sem);
89
}
90
 
91
/*
92
 * lock for writing
93
 */
94
static inline void
95
__down_write (struct rw_semaphore *sem)
96
{
97
        int old, new;
98
 
99
        do {
100
                old = sem->count;
101
                new = old + RWSEM_ACTIVE_WRITE_BIAS;
102
        } while (cmpxchg_acq(&sem->count, old, new) != old);
103
 
104
        if (old != 0)
105
                rwsem_down_write_failed(sem);
106
}
107
 
108
/*
109
 * unlock after reading
110
 */
111
static inline void
112
__up_read (struct rw_semaphore *sem)
113
{
114
        int result;
115
        __asm__ __volatile__ ("fetchadd4.rel %0=[%1],-1" :
116
                              "=r"(result) : "r"(&sem->count) : "memory");
117
        if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0)
118
                rwsem_wake(sem);
119
}
120
 
121
/*
122
 * unlock after writing
123
 */
124
static inline void
125
__up_write (struct rw_semaphore *sem)
126
{
127
        int old, new;
128
 
129
        do {
130
                old = sem->count;
131
                new = old - RWSEM_ACTIVE_WRITE_BIAS;
132
        } while (cmpxchg_rel(&sem->count, old, new) != old);
133
 
134
        if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0)
135
                rwsem_wake(sem);
136
}
137
 
138
/*
139
 * trylock for reading -- returns 1 if successful, 0 if contention
140
 */
141
static inline int
142
__down_read_trylock (struct rw_semaphore *sem)
143
{
144
        int tmp;
145
        while ((tmp = sem->count) >= 0) {
146
                if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) {
147
                        return 1;
148
                }
149
        }
150
        return 0;
151
}
152
 
153
/*
154
 * trylock for writing -- returns 1 if successful, 0 if contention
155
 */
156
static inline int
157
__down_write_trylock (struct rw_semaphore *sem)
158
{
159
        int tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE,
160
                              RWSEM_ACTIVE_WRITE_BIAS);
161
        return tmp == RWSEM_UNLOCKED_VALUE;
162
}
163
 
164
/*
165
 * downgrade write lock to read lock
166
 */
167
static inline void
168
__downgrade_write (struct rw_semaphore *sem)
169
{
170
        int old, new;
171
 
172
        do {
173
                old = sem->count;
174
                new = old - RWSEM_WAITING_BIAS;
175
        } while (cmpxchg_rel(&sem->count, old, new) != old);
176
 
177
        if (old < 0)
178
                rwsem_downgrade_wake(sem);
179
}
180
 
181
/*
182
 * Implement atomic add functionality.  These used to be "inline" functions, but GCC v3.1
183
 * doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd.
184
 */
185
#define rwsem_atomic_add(delta, sem)    atomic_add(delta, (atomic_t *)(&(sem)->count))
186
#define rwsem_atomic_update(delta, sem) atomic_add_return(delta, (atomic_t *)(&(sem)->count))
187
 
188
#endif /* _ASM_IA64_RWSEM_H */

powered by: WebSVN 2.1.0

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