Messages in this thread Patch in this message | | | Date | Mon, 7 Jan 2002 20:05:41 +0000 (GMT) | From | Matthew Kirkwood <> | 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] | |