diff -urN -X dontdiff linux/Makefile 2327-p5-modsem/Makefile
--- linux/Makefile      Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/Makefile     Wed Nov 10 13:26:15 1999
@@ -86,7 +86,7 @@
# standard CFLAGS
#

-CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
+CFLAGS = -g -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer

# use '-fno-strict-aliasing', but only if the compiler can take it
CFLAGS += $(shell if $(CC) -fno-strict-aliasing -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-fno-strict-aliasing"; fi)
diff -urN -X dontdiff linux/arch/alpha/mm/extable.c 2327-p5-modsem/arch/alpha/mm/extable.c
--- linux/arch/alpha/mm/extable.c       Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/alpha/mm/extable.c      Wed Nov 10 13:16:56 1999
@@ -49,18 +49,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special. */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp ; mp = mp->next) {
               if (!mp->ex_table_start)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end - 1, addr - mp->gp);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/arm/mm/extable.c 2327-p5-modsem/arch/arm/mm/extable.c
--- linux/arch/arm/mm/extable.c Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/arm/mm/extable.c        Wed Nov 10 13:17:23 1999
@@ -42,18 +42,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end - 1, addr);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/i386/mm/extable.c 2327-p5-modsem/arch/i386/mm/extable.c
--- linux/arch/i386/mm/extable.c        Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/i386/mm/extable.c       Wed Nov 10 13:17:53 1999
@@ -42,18 +42,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end - 1, addr);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/m68k/mm/extable.c 2327-p5-modsem/arch/m68k/mm/extable.c
--- linux/arch/m68k/mm/extable.c        Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/m68k/mm/extable.c       Wed Nov 10 13:18:19 1999
@@ -42,18 +42,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end-1, addr);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/mips/mm/extable.c 2327-p5-modsem/arch/mips/mm/extable.c
--- linux/arch/mips/mm/extable.c        Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/mips/mm/extable.c       Wed Nov 10 13:18:48 1999
@@ -41,18 +41,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end - 1, addr);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/ppc/mm/extable.c 2327-p5-modsem/arch/ppc/mm/extable.c
--- linux/arch/ppc/mm/extable.c Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/ppc/mm/extable.c        Wed Nov 10 13:19:13 1999
@@ -43,18 +43,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end - 1, addr);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/sh/mm/extable.c 2327-p5-modsem/arch/sh/mm/extable.c
--- linux/arch/sh/mm/extable.c  Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/sh/mm/extable.c Wed Nov 10 13:19:36 1999
@@ -45,18 +45,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end - 1, addr);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/sparc/mm/extable.c 2327-p5-modsem/arch/sparc/mm/extable.c
--- linux/arch/sparc/mm/extable.c       Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/sparc/mm/extable.c      Wed Nov 10 13:20:01 1999
@@ -56,18 +56,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end-1, addr, g2);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/arch/sparc64/kernel/sys_sparc32.c 2327-p5-modsem/arch/sparc64/kernel/sys_sparc32.c
--- linux/arch/sparc64/kernel/sys_sparc32.c     Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/sparc64/kernel/sys_sparc32.c    Wed Nov 10 13:20:36 1999
@@ -2932,7 +2932,7 @@
       free_page((unsigned long)buf);
}

-/* caller must hold modlist_lock at least in read mode */
+/* caller must hold down(&modlist_sem) */
static __inline__ struct module *find_module(const char *name)
{
       struct module *mod;
@@ -3162,7 +3162,7 @@
       struct module *mod;
       int err;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       if (name_user == 0) {
               /* This finds "kernel_module" which is not exported. */
               for(mod = module_list; mod->next != NULL; mod = mod->next)
@@ -3212,7 +3212,7 @@
               break;
       }
out:
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return err;
}

diff -urN -X dontdiff linux/arch/sparc64/mm/extable.c 2327-p5-modsem/arch/sparc64/mm/extable.c
--- linux/arch/sparc64/mm/extable.c     Wed Nov 10 08:49:02 1999
+++ 2327-p5-modsem/arch/sparc64/mm/extable.c    Wed Nov 10 13:21:05 1999
@@ -56,18 +56,18 @@
#else
       /* The kernel is the last "module" -- no need to treat it special.  */
       struct module *mp;
-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp != NULL; mp = mp->next) {
               if (mp->ex_table_start == NULL)
                       continue;
               ret = search_one_table(mp->ex_table_start,
                                      mp->ex_table_end-1, addr, g2);
               if (ret) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return ret;
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
#endif

       return 0;
diff -urN -X dontdiff linux/fs/proc/kcore.c 2327-p5-modsem/fs/proc/kcore.c
--- linux/fs/proc/kcore.c       Wed Nov 10 08:49:06 1999
+++ 2327-p5-modsem/fs/proc/kcore.c      Wed Nov 10 13:21:26 1999
@@ -211,7 +211,7 @@
#ifdef CONFIG_MODULES
       {
               struct module *m;
-               read_lock(&modlist_lock);
+               down(&modlist_sem);
               for (m=module_list; m; m=m->next) {
                       dhdr = (struct elf_phdr *) bufp;
                       bufp += sizeof(struct elf_phdr);
@@ -227,7 +227,7 @@
                       dhdr->p_align   = 0;
                       elf->e_phnum++;
               }
-               read_unlock(&modlist_lock);
+               up(&modlist_sem);
       }
#endif

diff -urN -X dontdiff linux/include/linux/module.h 2327-p5-modsem/include/linux/module.h
--- linux/include/linux/module.h        Wed Nov 10 08:49:07 1999
+++ 2327-p5-modsem/include/linux/module.h       Wed Nov 10 13:27:06 1999
@@ -8,7 +8,6 @@
#define _LINUX_MODULE_H

#include <linux/config.h>
-#include <linux/spinlock.h>

#ifdef __GENKSYMS__
#  define _set_ver(sym) sym
@@ -287,6 +286,6 @@
#define EXPORT_NO_SYMBOLS
#endif /* MODULE */

-extern rwlock_t modlist_lock;
+extern struct semaphore modlist_sem;
extern unsigned long get_kcore_size(void);
#endif /* _LINUX_MODULE_H */
diff -urN -X dontdiff linux/kernel/module.c 2327-p5-modsem/kernel/module.c
--- linux/kernel/module.c       Wed Nov 10 08:49:07 1999
+++ 2327-p5-modsem/kernel/module.c      Wed Nov 10 13:14:11 1999
@@ -13,7 +13,7 @@
 * 0.99.14 version by Jon Tombs <[email protected]>,
 * Heavily modified by Bjorn Ekwall <[email protected]> May 1994 (C)
 * Rewritten by Richard Henderson <[email protected]> Dec 1996
- * Use rw spinlock instead of global kernel lock for module_list, by TA <[email protected]>
+ * Use semaphore instead of "Big" lock for module_list, by TA <[email protected]>
 *
 * This source is covered by the GNU GPL, the same as all kernel sources.
 */
@@ -53,7 +53,7 @@
static struct module *find_module(const char *name);
static void free_module(struct module *, int tag_freed);

-rwlock_t modlist_lock = RW_LOCK_UNLOCKED;
+DECLARE_MUTEX(modlist_sem);


/* needed for /proc/kcore, here because kernel_module is static (TA) */
@@ -65,13 +65,13 @@
       if (module_list == &kernel_module)
               return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE);

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (m=module_list; m; m=m->next) {
               try = (unsigned long)m + m->size;
               if (try > size)
                       size = try;
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return (size - PAGE_OFFSET + PAGE_SIZE);
}

@@ -133,11 +133,11 @@
       long namelen, error;
       struct module *mod;

-       write_lock(&modlist_lock);
       if (!capable(CAP_SYS_MODULE)) {
               error = -EPERM;
               goto err0;
       }
+       down(&modlist_sem);
       if ((namelen = get_mod_name(name_user, &name)) < 0) {
               error = namelen;
               goto err0;
@@ -171,7 +171,7 @@
err1:
       put_mod_name(name);
err0:
-       write_unlock(&modlist_lock);
+       up(&modlist_sem);
       return error;
}

@@ -188,9 +188,9 @@
       unsigned long mod_user_size;
       struct module_ref *dep;

-       write_lock(&modlist_lock);
       if (!capable(CAP_SYS_MODULE))
               goto err0;
+       down(&modlist_sem);
       if ((namelen = get_mod_name(name_user, &name)) < 0) {
               error = namelen;
               goto err0;
@@ -367,7 +367,7 @@
err1:
       put_mod_name(name);
err0:
-       write_unlock(&modlist_lock);
+       up(&modlist_sem);
       return error;
}

@@ -379,10 +379,10 @@
       long error = -EPERM;
       int something_changed;

-       write_lock(&modlist_lock);
       if (!capable(CAP_SYS_MODULE))
               goto out;

+       down(&modlist_sem);
       if (name_user) {
               if ((error = get_mod_name(name_user, &name)) < 0)
                       goto out;
@@ -432,7 +432,7 @@
               mod->flags &= ~MOD_JUST_FREED;
       error = 0;
out:
-       write_unlock(&modlist_lock);
+       up(&modlist_sem);
       return error;
}

@@ -446,21 +446,20 @@

       nmod = space = 0;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) {
               len = strlen(mod->name)+1;
               if (len > bufsize)
                       goto calc_space_needed;
               if (copy_to_user(buf, mod->name, len)) {
-                       read_unlock(&modlist_lock);
+                       up(&modlist_sem);
                       return -EFAULT;
               }
               buf += len;
               bufsize -= len;
               space += len;
       }
-
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       if (put_user(nmod, ret))
               return -EFAULT;
       else
@@ -471,7 +470,7 @@
       while ((mod = mod->next) != &kernel_module)
               space += strlen(mod->name)+1;

-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       if (put_user(space, ret))
               return -EFAULT;
       else
@@ -658,7 +657,7 @@
       struct module *mod;
       int err;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       if (name_user == NULL)
               mod = &kernel_module;
       else {
@@ -704,7 +703,7 @@
               break;
       }
out:
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return err;
}

@@ -723,7 +722,7 @@
       int i;
       struct kernel_sym ksym;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mod = module_list, i = 0; mod; mod = mod->next) {
               /* include the count for the module name! */
               i += mod->nsyms + 1;
@@ -766,13 +765,13 @@
               }
       }
out:
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return i;
}

/*
 * Look for a module by name, ignoring modules marked for deletion.
- * Callers must hold modlist_lock at least in read mode.
+ * Callers must down(&modlist_sem)
 */

static struct module *
@@ -792,7 +791,7 @@

/*
 * Free the given module.
- * Callers must hold modlist_lock in exclusive (write) mode.
+ * Callers must down(&modlist_sem)
 */

static void
@@ -849,7 +848,7 @@
       char tmpstr[64];
       struct module_ref *ref;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mod = module_list; mod != &kernel_module; mod = mod->next) {
               long len;
               const char *q;
@@ -915,7 +914,7 @@
       }

fini:
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return PAGE_SIZE - left;
}

@@ -932,7 +931,7 @@
       off_t pos   = 0;
       off_t begin = 0;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mod = module_list; mod; mod = mod->next) {
               unsigned i;
               struct module_symbol *sym;
@@ -967,7 +966,7 @@
       len -= (offset - begin);
       if (len > length)
               len = length;
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return len;
}

@@ -984,7 +983,7 @@
       struct module_symbol *sym;
       int i;

-       read_lock(&modlist_lock);
+       down(&modlist_sem);
       for (mp = module_list; mp; mp = mp->next) {
               if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) &&
                       (mp->flags & (MOD_RUNNING | MOD_DELETED)) == MOD_RUNNING &&
@@ -993,13 +992,13 @@
                               i > 0; --i, ++sym) {

                               if (strcmp(sym->name, symname) == 0) {
-                                       read_unlock(&modlist_lock);
+                                       up(&modlist_sem);
                                       return sym->value;
                               }
                       }
               }
       }
-       read_unlock(&modlist_lock);
+       up(&modlist_sem);
       return 0;
}