[PATCH][RFC] Lightweight user-level semaphores

From: Matthew Kirkwood (matthew@hairy.beasts.org)
Date: Mon Jan 07 2002 - 15:05:41 EST


Linus,

The patch below implements some of your design for a really
quick user-level locking primitive, as explained here:

    http://lwn.net/2001/0419/a/lt-semaphores.php3

There's a user-level API and a couple of test programs in
the attached tarball. I haven't bothered wih the vital
security hash/signature thing yet.

It all seems to work (i686 UP and SMP), but isn't without
issues:

 * It leaks. How were you going to refcount the kernel
   portions? Could they be attached to the VM mapping?
   Would a lockfs be too expensive?

 * It doesn't have a timeout. Is there something like a
   down_timeout() available?

 * I don't do the:

        if (kfs->user_address != fs)
                goto bad_sem;

   because it doesn't seem to add anything, and prevents
   putting these locks in a non-fixed file or SysV SHM
   map.

   Is that a problem?

Any comments?

Matthew.

diff -ruN linux-2.4.17/arch/i386/kernel/entry.S linux-2.4.17-usersem/arch/i386/kernel/entry.S
--- linux-2.4.17/arch/i386/kernel/entry.S Sat Jan 5 14:00:37 2002
+++ linux-2.4.17-usersem/arch/i386/kernel/entry.S Sun Jan 6 13:52:50 2002
@@ -622,6 +622,9 @@
         .long SYMBOL_NAME(sys_ni_syscall) /* Reserved for Security */
         .long SYMBOL_NAME(sys_gettid)
         .long SYMBOL_NAME(sys_readahead) /* 225 */
+ .long SYMBOL_NAME(sys_FS_create)
+ .long SYMBOL_NAME(sys_FS_down)
+ .long SYMBOL_NAME(sys_FS_up)

         .rept NR_syscalls-(.-sys_call_table)/4
                 .long SYMBOL_NAME(sys_ni_syscall)
diff -ruN linux-2.4.17/include/asm-i386/unistd.h linux-2.4.17-usersem/include/asm-i386/unistd.h
--- linux-2.4.17/include/asm-i386/unistd.h Wed Oct 17 18:03:03 2001
+++ linux-2.4.17-usersem/include/asm-i386/unistd.h Sun Jan 6 13:49:54 2002
@@ -230,6 +230,9 @@
 #define __NR_security 223 /* syscall for security modules */
 #define __NR_gettid 224
 #define __NR_readahead 225
+#define __NR_FS_create 226
+#define __NR_FS_down 227
+#define __NR_FS_up 228

 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */

diff -ruN linux-2.4.17/include/linux/usersem.h linux-2.4.17-usersem/include/linux/usersem.h
--- linux-2.4.17/include/linux/usersem.h Thu Jan 1 01:00:00 1970
+++ linux-2.4.17-usersem/include/linux/usersem.h Sun Jan 6 17:50:04 2002
@@ -0,0 +1,9 @@
+#ifndef __LINUX_USERSEM_H
+#define __LINUX_USERSEM_H
+
+struct fast_sem {
+ int count;
+ void *__opaque_ksem;
+};
+
+#endif /* __LINUX_USERSEM_H */
diff -ruN linux-2.4.17/kernel/Makefile linux-2.4.17-usersem/kernel/Makefile
--- linux-2.4.17/kernel/Makefile Mon Sep 17 05:22:40 2001
+++ linux-2.4.17-usersem/kernel/Makefile Sat Jan 5 14:36:39 2002
@@ -9,12 +9,12 @@

 O_TARGET := kernel.o

-export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
+export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o usersem.o

 obj-y = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
             module.o exit.o itimer.o info.o time.o softirq.o resource.o \
             sysctl.o acct.o capability.o ptrace.o timer.o user.o \
- signal.o sys.o kmod.o context.o
+ signal.o sys.o kmod.o context.o usersem.o

 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
diff -ruN linux-2.4.17/kernel/usersem.c linux-2.4.17-usersem/kernel/usersem.c
--- linux-2.4.17/kernel/usersem.c Thu Jan 1 01:00:00 1970
+++ linux-2.4.17-usersem/kernel/usersem.c Sun Jan 6 17:50:20 2002
@@ -0,0 +1,82 @@
+/*
+ * Lightweight user-level semaphores
+ */
+
+#include <linux/slab.h>
+#include <linux/usersem.h>
+
+#include <linux/spinlock.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+/* Don't be messin' with my van^H^H^Hopaque data, sucka */
+#define FS_SIG_MAGIC 0xf001f001
+
+struct ksem {
+ unsigned magic;
+ spinlock_t spin;
+ struct semaphore sem;
+};
+
+
+/* XXX - _from_user */
+static inline struct ksem *get_ksem(struct fast_sem *s)
+{
+ struct ksem *r = (struct ksem*)s->__opaque_ksem;
+ if(!r) return NULL;
+ if(r->magic != FS_SIG_MAGIC) return NULL;
+ return r;
+}
+
+/* XXX - _to_user */
+static inline int store_ksem(struct fast_sem *s, struct ksem *k)
+{
+ s->count = 0;
+ s->__opaque_ksem = (void*)k;
+ return 0;
+}
+
+static struct ksem *ksem_new(void)
+{
+ struct ksem *s;
+ s = kmalloc(sizeof(*s), GFP_KERNEL);
+ s->magic = FS_SIG_MAGIC;
+ spin_lock_init(&s->spin);
+ sema_init(&s->sem, 1);
+ return s;
+}
+
+
+asmlinkage long sys_FS_create(struct fast_sem *sem)
+{
+ struct ksem *ksem;
+ if(!(ksem = ksem_new()))
+ return -ENOMEM;
+ if(store_ksem(sem, ksem)) {
+ //ksem_free(ksem);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+
+asmlinkage long sys_FS_down(struct fast_sem *sem)
+{
+ struct ksem *ksem;
+
+ if(!(ksem = get_ksem(sem)))
+ return -ENOENT;
+
+ down_interruptible(&ksem->sem);
+ return 0;
+}
+
+asmlinkage long sys_FS_up(struct fast_sem *sem)
+{
+ struct ksem *ksem;
+ if(!(ksem = get_ksem(sem)))
+ return -ENOENT;
+
+ up(&ksem->sem);
+ return 0;
+}



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Jan 07 2002 - 21:00:36 EST