1 include/linux/dynlocks.h | 33 ++++++++++
3 lib/dynlocks.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++
4 3 files changed, 187 insertions(+), 2 deletions(-)
6 Index: linux-2.4.21-suse2/include/linux/dynlocks.h
7 ===================================================================
8 --- linux-2.4.21-suse2.orig/include/linux/dynlocks.h 2003-01-30 13:24:37.000000000 +0300
9 +++ linux-2.4.21-suse2/include/linux/dynlocks.h 2004-08-19 13:11:02.000000000 +0400
11 +#ifndef _LINUX_DYNLOCKS_H
12 +#define _LINUX_DYNLOCKS_H
14 +#include <linux/list.h>
15 +#include <linux/wait.h>
17 +#define DYNLOCK_MAGIC 0xd19a10c
18 +#define DYNLOCK_MAGIC2 0xd1956ee
22 +struct dynlock_member {
24 + struct list_head dl_list;
25 + unsigned long dl_value; /* lock value */
26 + int dl_refcount; /* number of users */
29 + int dl_pid; /* holder of the lock */
30 + wait_queue_head_t dl_wait;
36 + * - lock to protect this list
39 +#define DYNLOCK_LIST_MAGIC 0x11ee91e6
43 + struct list_head dl_list;
44 + spinlock_t dl_list_lock;
47 +void dynlock_init(struct dynlock *dl);
48 +void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp);
49 +void dynlock_unlock(struct dynlock *dl, void *lock);
54 Index: linux-2.4.21-suse2/lib/dynlocks.c
55 ===================================================================
56 --- linux-2.4.21-suse2.orig/lib/dynlocks.c 2003-01-30 13:24:37.000000000 +0300
57 +++ linux-2.4.21-suse2/lib/dynlocks.c 2004-08-19 13:11:02.000000000 +0400
62 + * struct dynlock is lockspace
63 + * one may request lock (exclusive or shared) for some value
68 +#include <linux/dynlocks.h>
69 +#include <linux/module.h>
70 +#include <linux/slab.h>
71 +#include <linux/sched.h>
73 +static kmem_cache_t * dynlock_cachep = NULL;
75 +void __init dynlock_cache_init(void)
77 + printk(KERN_INFO "init dynlocks cache\n");
78 + dynlock_cachep = kmem_cache_create("dynlock_cache",
79 + sizeof(struct dynlock_member),
83 + if (dynlock_cachep == NULL)
84 + panic("Can't create dynlock cache");
90 + * initialize lockspace
93 +void dynlock_init(struct dynlock *dl)
95 + spin_lock_init(&dl->dl_list_lock);
96 + INIT_LIST_HEAD(&dl->dl_list);
97 + dl->dl_magic = DYNLOCK_LIST_MAGIC;
103 + * acquires lock (exclusive or shared) in specified lockspace
104 + * each lock in lockspace is allocated separately, so user have
105 + * to specify GFP flags.
106 + * routine returns pointer to lock. this pointer is intended to
107 + * be passed to dynlock_unlock
110 +void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp)
112 + struct dynlock_member *nhl = NULL;
113 + struct dynlock_member *hl;
114 + struct list_head *cur;
117 + BUG_ON(dl == NULL);
118 + BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
120 + /* find requested lock in lockspace */
121 + spin_lock(&dl->dl_list_lock);
122 + BUG_ON(dl->dl_list.next == NULL);
123 + BUG_ON(dl->dl_list.prev == NULL);
124 + list_for_each(cur, &dl->dl_list) {
125 + BUG_ON(cur->next == NULL);
126 + BUG_ON(cur->prev == NULL);
127 + hl = list_entry(cur, struct dynlock_member, dl_list);
128 + BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
129 + if (hl->dl_value == value) {
130 + /* lock is found */
132 + /* someone else just allocated
133 + * lock we didn't find and just created
134 + * so, we drop our lock
136 + kmem_cache_free(dynlock_cachep, nhl);
144 + /* lock not found */
146 + /* we already have allocated lock. use it */
149 + list_add(&hl->dl_list, &dl->dl_list);
152 + spin_unlock(&dl->dl_list_lock);
154 + /* lock not found and we haven't allocated lock yet. allocate it */
155 + nhl = kmem_cache_alloc(dynlock_cachep, gfp);
158 + nhl->dl_refcount = 1;
159 + nhl->dl_value = value;
160 + nhl->dl_readers = 0;
161 + nhl->dl_writers = 0;
162 + nhl->dl_magic = DYNLOCK_MAGIC;
163 + init_waitqueue_head(&nhl->dl_wait);
165 + /* while lock is being allocated, someone else may allocate it
166 + * and put onto to list. check this situation
172 + /* exclusive lock: user don't want to share lock at all
173 + * NOTE: one process may take the same lock several times
174 + * this functionaly is useful for rename operations */
175 + while ((hl->dl_writers && hl->dl_pid != current->pid) ||
177 + spin_unlock(&dl->dl_list_lock);
178 + wait_event(hl->dl_wait,
179 + hl->dl_writers == 0 && hl->dl_readers == 0);
180 + spin_lock(&dl->dl_list_lock);
184 + /* shared lock: user do not want to share lock with writer */
185 + while (hl->dl_writers) {
186 + spin_unlock(&dl->dl_list_lock);
187 + wait_event(hl->dl_wait, hl->dl_writers == 0);
188 + spin_lock(&dl->dl_list_lock);
192 + hl->dl_pid = current->pid;
193 + spin_unlock(&dl->dl_list_lock);
202 + * user have to specify lockspace (dl) and pointer to lock structure
203 + * returned by dynlock_lock()
206 +void dynlock_unlock(struct dynlock *dl, void *lock)
208 + struct dynlock_member *hl = lock;
211 + BUG_ON(dl == NULL);
212 + BUG_ON(hl == NULL);
213 + BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
214 + BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
215 + BUG_ON(current->pid != hl->dl_pid);
217 + spin_lock(&dl->dl_list_lock);
218 + if (hl->dl_writers) {
219 + BUG_ON(hl->dl_readers > 0 || hl->dl_readers < 0);
221 + if (hl->dl_writers == 0)
223 + } else if (hl->dl_readers) {
225 + if (hl->dl_readers == 0)
232 + wake_up(&hl->dl_wait);
234 + if (--(hl->dl_refcount) == 0) {
235 + hl->dl_magic = DYNLOCK_MAGIC2;
236 + list_del(&hl->dl_list);
237 + kmem_cache_free(dynlock_cachep, hl);
239 + spin_unlock(&dl->dl_list_lock);
242 +EXPORT_SYMBOL(dynlock_init);
243 +EXPORT_SYMBOL(dynlock_lock);
244 +EXPORT_SYMBOL(dynlock_unlock);
246 Index: linux-2.4.21-suse2/lib/Makefile
247 ===================================================================
248 --- linux-2.4.21-suse2.orig/lib/Makefile 2003-10-28 21:34:24.000000000 +0300
249 +++ linux-2.4.21-suse2/lib/Makefile 2004-08-19 13:11:31.000000000 +0400
253 export-objs := cmdline.o dec_and_lock.o rwsem.o rbtree.o qsort.o \
255 + firmware_class.o dynlocks.o
257 obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
258 - bust_spinlocks.o rbtree.o dump_stack.o rwsem.o md5.o
259 + bust_spinlocks.o rbtree.o dump_stack.o rwsem.o md5.o dynlocks.o
261 obj-$(CONFIG_FW_LOADER) += firmware_class.o
262 obj-$(CONFIG_QSORT) += qsort.o
263 Index: linux-2.4.21-suse2/fs/dcache.c
264 ===================================================================
265 --- linux-2.4.21-suse2.orig/fs/dcache.c 2004-08-19 12:57:06.000000000 +0400
266 +++ linux-2.4.21-suse2/fs/dcache.c 2004-08-19 13:11:02.000000000 +0400
267 @@ -1312,6 +1312,7 @@
268 extern void bdev_cache_init(void);
269 extern void cdev_cache_init(void);
270 extern void iobuf_cache_init(void);
271 +extern void dynlock_cache_init(void);
273 void __init vfs_caches_init(unsigned long mempages)
275 @@ -1348,4 +1349,5 @@
279 + dynlock_cache_init();