]>
git.proxmox.com Git - mirror_spl-debian.git/blob - include/sys/rwlock.h
4 #include <linux/module.h>
5 #include <linux/slab.h>
6 #include <linux/rwsem.h>
7 #include <asm/current.h>
15 RW_DRIVER
= 2, /* driver (DDI) rwlock */
16 RW_DEFAULT
= 4 /* kernel default rwlock */
24 #define RW_READ_HELD(x) (__rw_read_held((x)))
25 #define RW_WRITE_HELD(x) (__rw_write_held((x)))
26 #define RW_LOCK_HELD(x) (__rw_lock_held((x)))
27 #define RW_ISWRITER(x) (__rw_iswriter(x))
29 #define RW_MAGIC 0x3423645a
30 #define RW_POISON 0xa6
35 struct rw_semaphore rw_sem
;
36 struct task_struct
*rw_owner
; /* holder of the write lock */
39 #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
41 struct list_head list
;
42 struct task_struct
*task
;
44 #define RWSEM_WAITING_FOR_READ 0x00000001
45 #define RWSEM_WAITING_FOR_WRITE 0x00000002
49 * wake a single writer
51 static inline struct rw_semaphore
*
52 __rwsem_wake_one_writer_locked(struct rw_semaphore
*sem
)
54 struct rwsem_waiter
*waiter
;
55 struct task_struct
*tsk
;
59 waiter
= list_entry(sem
->wait_list
.next
, struct rwsem_waiter
, list
);
60 list_del(&waiter
->list
);
71 * release a read lock on the semaphore
74 __up_read_locked(struct rw_semaphore
*sem
)
76 if (--sem
->activity
== 0 && !list_empty(&sem
->wait_list
))
77 sem
= __rwsem_wake_one_writer_locked(sem
);
81 * trylock for writing -- returns 1 if successful, 0 if contention
84 __down_write_trylock_locked(struct rw_semaphore
*sem
)
88 if (sem
->activity
== 0 && list_empty(&sem
->wait_list
)) {
98 extern int __rw_read_held(krwlock_t
*rwlp
);
99 extern int __rw_write_held(krwlock_t
*rwlp
);
100 extern int __rw_lock_held(krwlock_t
*rwlp
);
102 static __inline__
void
103 rw_init(krwlock_t
*rwlp
, char *name
, krw_type_t type
, void *arg
)
105 BUG_ON(type
!= RW_DEFAULT
); /* XXX no irq handler use */
106 BUG_ON(arg
!= NULL
); /* XXX no irq handler use */
107 rwlp
->rw_magic
= RW_MAGIC
;
108 rwlp
->rw_owner
= NULL
; /* no one holds the write lock yet */
109 init_rwsem(&rwlp
->rw_sem
);
110 rwlp
->rw_name
= NULL
;
113 rwlp
->rw_name
= kmalloc(strlen(name
) + 1, GFP_KERNEL
);
115 strcpy(rwlp
->rw_name
, name
);
119 static __inline__
void
120 rw_destroy(krwlock_t
*rwlp
)
122 BUG_ON(rwlp
== NULL
);
123 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
124 BUG_ON(rwlp
->rw_owner
!= NULL
);
125 spin_lock(&rwlp
->rw_sem
.wait_lock
);
126 BUG_ON(!list_empty(&rwlp
->rw_sem
.wait_list
));
127 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
130 kfree(rwlp
->rw_name
);
132 memset(rwlp
, RW_POISON
, sizeof(krwlock_t
));
135 /* Return 0 if the lock could not be obtained without blocking.
137 static __inline__
int
138 rw_tryenter(krwlock_t
*rwlp
, krw_t rw
)
142 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
144 /* these functions return 1 if success, 0 if contention */
146 /* Here the Solaris code would return 0
147 * if there were any write waiters. Specifically
148 * thinking about the case where readers may have
149 * the lock and we would also allow this thread
150 * to grab the read lock with a writer waiting in the
151 * queue. This doesn't seem like a correctness
152 * issue, so just call down_read_trylock()
153 * for the test. We may have to revisit this if
154 * it becomes an issue */
155 result
= down_read_trylock(&rwlp
->rw_sem
);
158 result
= down_write_trylock(&rwlp
->rw_sem
);
160 /* there better not be anyone else
161 * holding the write lock here */
162 BUG_ON(rwlp
->rw_owner
!= NULL
);
163 rwlp
->rw_owner
= current
;
173 static __inline__
void
174 rw_enter(krwlock_t
*rwlp
, krw_t rw
)
176 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
179 /* Here the Solaris code would block
180 * if there were any write waiters. Specifically
181 * thinking about the case where readers may have
182 * the lock and we would also allow this thread
183 * to grab the read lock with a writer waiting in the
184 * queue. This doesn't seem like a correctness
185 * issue, so just call down_read()
186 * for the test. We may have to revisit this if
187 * it becomes an issue */
188 down_read(&rwlp
->rw_sem
);
191 down_write(&rwlp
->rw_sem
);
193 /* there better not be anyone else
194 * holding the write lock here */
195 BUG_ON(rwlp
->rw_owner
!= NULL
);
196 rwlp
->rw_owner
= current
;
203 static __inline__
void
204 rw_exit(krwlock_t
*rwlp
)
206 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
208 /* rw_owner is held by current
209 * thread iff it is a writer */
210 if (rwlp
->rw_owner
== current
) {
211 rwlp
->rw_owner
= NULL
;
212 up_write(&rwlp
->rw_sem
);
214 up_read(&rwlp
->rw_sem
);
218 static __inline__
void
219 rw_downgrade(krwlock_t
*rwlp
)
221 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
222 BUG_ON(rwlp
->rw_owner
!= current
);
223 rwlp
->rw_owner
= NULL
;
224 downgrade_write(&rwlp
->rw_sem
);
227 /* Return 0 if unable to perform the upgrade.
228 * Might be wise to fix the caller
229 * to acquire the write lock first?
231 static __inline__
int
232 rw_tryupgrade(krwlock_t
*rwlp
)
235 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
237 spin_lock(&rwlp
->rw_sem
.wait_lock
);
239 /* Check if there is anyone waiting for the
240 * lock. If there is, then we know we should
241 * not try to upgrade the lock */
242 if (!list_empty(&rwlp
->rw_sem
.wait_list
)) {
243 printk("spl: Warning There are threads waiting\n");
244 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
247 #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
248 /* Note that activity is protected by
249 * the wait_lock. Don't try to upgrade
250 * if there are multiple readers currently
251 * holding the lock */
252 if (rwlp
->rw_sem
.activity
> 1) {
254 /* Don't try to upgrade
255 * if there are multiple readers currently
256 * holding the lock */
257 if ((rwlp
->rw_sem
.count
& RWSEM_ACTIVE_MASK
) > 1) {
259 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
263 #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
264 /* Here it should be safe to drop the
265 * read lock and reacquire it for writing since
266 * we know there are no waiters */
267 __up_read_locked(&rwlp
->rw_sem
);
269 /* returns 1 if success, 0 if contention */
270 result
= __down_write_trylock_locked(&rwlp
->rw_sem
);
272 /* Here it should be safe to drop the
273 * read lock and reacquire it for writing since
274 * we know there are no waiters */
275 up_read(&rwlp
->rw_sem
);
277 /* returns 1 if success, 0 if contention */
278 result
= down_write_trylock(&rwlp
->rw_sem
);
281 /* Check if upgrade failed. Should not ever happen
282 * if we got to this point */
284 BUG_ON(rwlp
->rw_owner
!= NULL
);
285 rwlp
->rw_owner
= current
;
286 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
290 static __inline__ kthread_t
*
291 rw_owner(krwlock_t
*rwlp
)
293 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
294 return rwlp
->rw_owner
;
301 #endif /* _SPL_RWLOCK_H */