lkml.org 
[lkml]   [2002]   [Jan]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH][RFC] Lightweight user-level semaphores
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;
+}[unhandled content-type:application/octet-stream]
\
 
 \ /
  Last update: 2005-03-22 13:15    [W:0.049 / U:0.068 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site