1 include/linux/dynlocks.h | 33 ++++++++++
3 lib/dynlocks.c | 152 +++++++++++++++++++++++++++++++++++++++++++++++
4 3 files changed, 187 insertions(+), 2 deletions(-)
6 Index: linux-2.4.24/include/linux/dynlocks.h
7 ===================================================================
8 --- linux-2.4.24.orig/include/linux/dynlocks.h 2003-01-30 13:24:37.000000000 +0300
9 +++ linux-2.4.24/include/linux/dynlocks.h 2004-07-15 18:32:18.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
20 +struct dynlock_member {
22 + struct list_head dl_list;
23 + unsigned long dl_value; /* lock value */
24 + int dl_refcount; /* number of users */
27 + int dl_pid; /* holder of the lock */
28 + wait_queue_head_t dl_wait;
34 + * - lock to protect this list
37 +#define DYNLOCK_LIST_MAGIC 0x11ee91e6
41 + struct list_head dl_list;
42 + spinlock_t dl_list_lock;
45 +void dynlock_init(struct dynlock *dl);
46 +void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp);
47 +void dynlock_unlock(struct dynlock *dl, void *lock);
52 Index: linux-2.4.24/lib/dynlocks.c
53 ===================================================================
54 --- linux-2.4.24.orig/lib/dynlocks.c 2003-01-30 13:24:37.000000000 +0300
55 +++ linux-2.4.24/lib/dynlocks.c 2004-07-15 18:42:10.000000000 +0400
60 + * struct dynlock is lockspace
61 + * one may request lock (exclusive or shared) for some value
66 +#include <linux/dynlocks.h>
67 +#include <linux/module.h>
68 +#include <linux/slab.h>
69 +#include <linux/sched.h>
74 + * initialize lockspace
77 +void dynlock_init(struct dynlock *dl)
79 + spin_lock_init(&dl->dl_list_lock);
80 + INIT_LIST_HEAD(&dl->dl_list);
81 + dl->dl_magic = DYNLOCK_LIST_MAGIC;
87 + * acquires lock (exclusive or shared) in specified lockspace
88 + * each lock in lockspace is allocated separately, so user have
89 + * to specify GFP flags.
90 + * routine returns pointer to lock. this pointer is intended to
91 + * be passed to dynlock_unlock
94 +void *dynlock_lock(struct dynlock *dl, unsigned long value, int rw, int gfp)
96 + struct dynlock_member *nhl = NULL;
97 + struct dynlock_member *hl;
98 + struct list_head *cur;
100 + BUG_ON(dl == NULL);
101 + BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
103 + /* find requested lock in lockspace */
104 + spin_lock(&dl->dl_list_lock);
105 + BUG_ON(dl->dl_list.next == NULL);
106 + BUG_ON(dl->dl_list.prev == NULL);
107 + list_for_each(cur, &dl->dl_list) {
108 + BUG_ON(cur->next == NULL);
109 + BUG_ON(cur->prev == NULL);
110 + hl = list_entry(cur, struct dynlock_member, dl_list);
111 + if (hl->dl_magic != DYNLOCK_MAGIC) {
112 + printk("corrupted lock 0x%p: magic 0x%x (!=0x%x)\n",
113 + hl, hl->dl_magic, DYNLOCK_MAGIC);
114 + printk(" value 0x%lx, %d readers, %d writers, pid %d, %d refs\n",
115 + hl->dl_value, hl->dl_readers, hl->dl_writers,
116 + hl->dl_pid, hl->dl_refcount);
119 + if (hl->dl_value == value) {
120 + /* lock is found */
122 + /* someone else just allocated
123 + * lock we didn't find and just created
124 + * so, we drop our lock
133 + /* lock not found */
135 + /* we already have allocated lock. use it */
138 + list_add(&hl->dl_list, &dl->dl_list);
141 + spin_unlock(&dl->dl_list_lock);
143 + /* lock not found and we haven't allocated lock yet. allocate it */
144 + nhl = kmalloc(sizeof(struct dynlock_member), gfp);
147 + nhl->dl_refcount = 1;
148 + nhl->dl_value = value;
149 + nhl->dl_readers = 0;
150 + nhl->dl_writers = 0;
151 + nhl->dl_magic = DYNLOCK_MAGIC;
152 + init_waitqueue_head(&nhl->dl_wait);
154 + /* while lock is being allocated, someone else may allocate it
155 + * and put onto to list. check this situation
161 + /* exclusive lock: user don't want to share lock at all
162 + * NOTE: one process may take the same lock several times
163 + * this functionaly is useful for rename operations */
164 + while ((hl->dl_writers && hl->dl_pid != current->pid) ||
166 + spin_unlock(&dl->dl_list_lock);
167 + wait_event(hl->dl_wait,
168 + hl->dl_writers == 0 && hl->dl_readers == 0);
169 + spin_lock(&dl->dl_list_lock);
173 + /* shared lock: user do not want to share lock with writer */
174 + while (hl->dl_writers) {
175 + spin_unlock(&dl->dl_list_lock);
176 + wait_event(hl->dl_wait, hl->dl_writers == 0);
177 + spin_lock(&dl->dl_list_lock);
181 + hl->dl_pid = current->pid;
182 + spin_unlock(&dl->dl_list_lock);
184 + BUG_ON(hl->dl_magic != DYNLOCK_MAGIC);
192 + * user have to specify lockspace (dl) and pointer to lock structure
193 + * returned by dynlock_lock()
196 +void dynlock_unlock(struct dynlock *dl, void *lock)
198 + struct dynlock_member *hl = lock;
201 + BUG_ON(dl == NULL);
202 + BUG_ON(hl == NULL);
203 + BUG_ON(dl->dl_magic != DYNLOCK_LIST_MAGIC);
204 + if (hl->dl_magic != DYNLOCK_MAGIC) {
205 + printk("corrupted lock 0x%p: magic 0x%x (!=0x%x)\n",
206 + hl, hl->dl_magic, DYNLOCK_MAGIC);
207 + printk(" value 0x%lx, %d readers, %d writers, pid %d, %d refs\n",
208 + hl->dl_value, hl->dl_readers, hl->dl_writers,
209 + hl->dl_pid, hl->dl_refcount);
212 + BUG_ON(current->pid != hl->dl_pid);
214 + spin_lock(&dl->dl_list_lock);
215 + if (hl->dl_writers) {
216 + BUG_ON(hl->dl_readers > 0 || hl->dl_readers < 0);
218 + if (hl->dl_writers == 0)
220 + } else if (hl->dl_readers) {
222 + if (hl->dl_readers == 0)
229 + wake_up(&hl->dl_wait);
231 + if (--(hl->dl_refcount) == 0) {
232 + hl->dl_magic = DYNLOCK_MAGIC2;
233 + list_del(&hl->dl_list);
235 + spin_unlock(&dl->dl_list_lock);
236 + if (hl->dl_refcount == 0)
240 +EXPORT_SYMBOL(dynlock_init);
241 +EXPORT_SYMBOL(dynlock_lock);
242 +EXPORT_SYMBOL(dynlock_unlock);
244 Index: linux-2.4.24/lib/Makefile
245 ===================================================================
246 --- linux-2.4.24.orig/lib/Makefile 2004-06-24 09:06:32.000000000 +0400
247 +++ linux-2.4.24/lib/Makefile 2004-07-14 18:14:28.000000000 +0400
251 export-objs := cmdline.o dec_and_lock.o rwsem-spinlock.o rwsem.o \
252 - rbtree.o crc32.o firmware_class.o
253 + rbtree.o crc32.o firmware_class.o dynlocks.o
255 obj-y := errno.o ctype.o string.o vsprintf.o brlock.o cmdline.o \
256 - bust_spinlocks.o rbtree.o dump_stack.o
257 + bust_spinlocks.o rbtree.o dump_stack.o dynlocks.o
259 obj-$(CONFIG_FW_LOADER) += firmware_class.o
260 obj-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o