]>
git.proxmox.com Git - mirror_spl-debian.git/blob - include/linux-rwlock.h
a6a2787d8af65834b3c18c8babcf7216b473a277
1 #ifndef _SYS_LINUX_RWLOCK_H
2 #define _SYS_LINUX_RWLOCK_H
4 #include <linux/slab.h>
5 #include <linux/rwsem.h>
6 #include <asm/current.h>
7 #include <sys/linux-types.h>
14 RW_DRIVER
= 2, /* driver (DDI) rwlock */
15 RW_DEFAULT
= 4 /* kernel default rwlock */
23 #define RW_READ_HELD(x) (rw_read_held((x)))
24 #define RW_WRITE_HELD(x) (rw_write_held((x)))
25 #define RW_LOCK_HELD(x) (rw_lock_held((x)))
26 #define RW_ISWRITER(x) (rw_iswriter(x))
28 #define RW_MAGIC 0x3423645a
29 #define RW_POISON 0xa6
34 struct rw_semaphore rw_sem
;
35 struct task_struct
*rw_owner
; /* holder of the write lock */
38 static __inline__
void
39 rw_init(krwlock_t
*rwlp
, char *name
, krw_type_t type
, void *arg
)
41 BUG_ON(type
!= RW_DEFAULT
); /* XXX no irq handler use */
42 BUG_ON(arg
!= NULL
); /* XXX no irq handler use */
43 rwlp
->rw_magic
= RW_MAGIC
;
44 rwlp
->rw_owner
= NULL
; /* no one holds the write lock yet */
45 init_rwsem(&rwlp
->rw_sem
);
49 rwlp
->rw_name
= kmalloc(strlen(name
) + 1, GFP_KERNEL
);
51 strcpy(rwlp
->rw_name
, name
);
55 static __inline__
void
56 rw_destroy(krwlock_t
*rwlp
)
59 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
60 BUG_ON(rwlp
->rw_owner
!= NULL
);
61 spin_lock(&rwlp
->rw_sem
.wait_lock
);
62 BUG_ON(!list_empty(&rwlp
->rw_sem
.wait_list
));
63 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
68 memset(rwlp
, RW_POISON
, sizeof(krwlock_t
));
71 /* Return 0 if the lock could not be obtained without blocking.
74 rw_tryenter(krwlock_t
*rwlp
, krw_t rw
)
78 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
80 /* these functions return 1 if success, 0 if contention */
82 /* Here the Solaris code would return 0
83 * if there were any write waiters. Specifically
84 * thinking about the case where readers may have
85 * the lock and we would also allow this thread
86 * to grab the read lock with a writer waiting in the
87 * queue. This doesn't seem like a correctness
88 * issue, so just call down_read_trylock()
89 * for the test. We may have to revisit this if
90 * it becomes an issue */
91 result
= down_read_trylock(&rwlp
->rw_sem
);
94 result
= down_write_trylock(&rwlp
->rw_sem
);
96 /* there better not be anyone else
97 * holding the write lock here */
98 BUG_ON(rwlp
->rw_owner
!= NULL
);
99 rwlp
->rw_owner
= current
;
107 static __inline__
void
108 rw_enter(krwlock_t
*rwlp
, krw_t rw
)
110 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
113 /* Here the Solaris code would block
114 * if there were any write waiters. Specifically
115 * thinking about the case where readers may have
116 * the lock and we would also allow this thread
117 * to grab the read lock with a writer waiting in the
118 * queue. This doesn't seem like a correctness
119 * issue, so just call down_read()
120 * for the test. We may have to revisit this if
121 * it becomes an issue */
122 down_read(&rwlp
->rw_sem
);
125 down_write(&rwlp
->rw_sem
);
127 /* there better not be anyone else
128 * holding the write lock here */
129 BUG_ON(rwlp
->rw_owner
!= NULL
);
130 rwlp
->rw_owner
= current
;
135 static __inline__
void
136 rw_exit(krwlock_t
*rwlp
)
138 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
140 /* rw_owner is held by current
141 * thread iff it is a writer */
142 if (rwlp
->rw_owner
== current
) {
143 rwlp
->rw_owner
= NULL
;
144 up_write(&rwlp
->rw_sem
);
146 up_read(&rwlp
->rw_sem
);
150 static __inline__
void
151 rw_downgrade(krwlock_t
*rwlp
)
153 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
154 BUG_ON(rwlp
->rw_owner
!= current
);
155 rwlp
->rw_owner
= NULL
;
156 downgrade_write(&rwlp
->rw_sem
);
159 /* Return 0 if unable to perform the upgrade.
160 * Might be wise to fix the caller
161 * to acquire the write lock first?
163 static __inline__
int
164 rw_tryupgrade(krwlock_t
*rwlp
)
167 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
169 spin_lock(&rwlp
->rw_sem
.wait_lock
);
171 /* Check if there is anyone waiting for the
172 * lock. If there is, then we know we should
173 * not try to upgrade the lock */
174 if (!list_empty(&rwlp
->rw_sem
.wait_list
)) {
175 printk(KERN_WARNING
"There are threads waiting\n");
176 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
179 #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
180 /* Note that activity is protected by
181 * the wait_lock. Don't try to upgrade
182 * if there are multiple readers currently
183 * holding the lock */
184 if (rwlp
->rw_sem
.activity
> 1) {
186 /* Don't try to upgrade
187 * if there are multiple readers currently
188 * holding the lock */
189 if ((rwlp
->rw_sem
.count
& RWSEM_ACTIVE_MASK
) > 1) {
191 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
195 /* Here it should be safe to drop the
196 * read lock and reacquire it for writing since
197 * we know there are no waiters */
198 up_read(&rwlp
->rw_sem
);
200 /* returns 1 if success, 0 if contention */
201 result
= down_write_trylock(&rwlp
->rw_sem
);
203 /* Check if upgrade failed. Should not ever happen
204 * if we got to this point */
206 BUG_ON(rwlp
->rw_owner
!= NULL
);
207 rwlp
->rw_owner
= current
;
208 spin_unlock(&rwlp
->rw_sem
.wait_lock
);
212 static __inline__ kthread_t
*
213 rw_owner(krwlock_t
*rwlp
)
215 BUG_ON(rwlp
->rw_magic
!= RW_MAGIC
);
216 return rwlp
->rw_owner
;
223 #endif /* _SYS_LINUX_RWLOCK_H */