diff -purN v2.6.12-rc2-01_i_sem/include/linux/mutex.h v2.6.12-rc2-10_new_mutex/include/linux/mutex.h --- v2.6.12-rc2-01_i_sem/include/linux/mutex.h 2005-04-07 15:38:22.000000000 -0400 +++ v2.6.12-rc2-10_new_mutex/include/linux/mutex.h 2005-04-08 11:35:00.000000000 -0400 @@ -1,40 +1,43 @@ +/* + * include/linux/mutex.h + * + * Copyright (C) 2005 Trond Myklebust + * + * Definitions for mutex. These can act as mutexes, but unlike + * semaphores, their code is 100% arch-independent, and can therefore + * easily be expanded in order to provide for things like + * asynchronous I/O. + */ #ifndef _LINUX_MUTEX_H #define _LINUX_MUTEX_H -#include +#ifdef __KERNEL__ +#include +#include struct mutex { - struct semaphore sem; + wait_queue_head_t wait; + void *owner; }; -static inline void mutex_lock(struct mutex *mut) -{ - down(&mut->sem); -} - -static inline int mutex_lock_interruptible(struct mutex *mut) -{ - return down_interruptible(&mut->sem); -} +#define IOSEM_LOCK_EXCLUSIVE (24) +/* #define IOSEM_LOCK_SHARED (25) */ -static inline void mutex_unlock(struct mutex *mut) -{ - up(&mut->sem); -} - -static inline int mutex_trylock(struct mutex *mut) -{ - return down_trylock(&mut->sem); -} +extern int FASTCALL(mutex_lock_interruptible(struct mutex *lk)); +extern void FASTCALL(mutex_lock(struct mutex *lk)); +extern void FASTCALL(mutex_unlock(struct mutex *lk)); -static inline void mutex_init(struct mutex *mut) +static inline void mutex_init(struct mutex *lk) { - sema_init(&mut->sem, 1); + init_waitqueue_head(&lk->wait); + lk->owner = NULL; } -static inline void mutex_init_LOCKED(struct mutex *mut) +static inline void mutex_init_LOCKED(struct mutex *lk) { - sema_init(&mut->sem, 0); + init_waitqueue_head(&lk->wait); + lk->owner = lk; } +#endif /* __KERNEL__ */ #endif /* _LINUX_MUTEX_H */ diff -purN v2.6.12-rc2-01_i_sem/kernel/Makefile v2.6.12-rc2-10_new_mutex/kernel/Makefile --- v2.6.12-rc2-01_i_sem/kernel/Makefile 2005-04-07 14:03:28.000000000 -0400 +++ v2.6.12-rc2-10_new_mutex/kernel/Makefile 2005-04-08 10:58:22.000000000 -0400 @@ -7,7 +7,8 @@ obj-y = sched.o fork.o exec_domain.o sysctl.o capability.o ptrace.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ rcupdate.o intermodule.o extable.o params.o posix-timers.o \ - kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o + kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o \ + mutex.o obj-m += sem-test.o diff -purN v2.6.12-rc2-01_i_sem/kernel/mutex.c v2.6.12-rc2-10_new_mutex/kernel/mutex.c --- v2.6.12-rc2-01_i_sem/kernel/mutex.c 1969-12-31 19:00:00.000000000 -0500 +++ v2.6.12-rc2-10_new_mutex/kernel/mutex.c 2005-04-08 16:53:04.000000000 -0400 @@ -0,0 +1,116 @@ +/* + * linux/kernel/mutex.c + * + * Copyright (C) 2005 Trond Myklebust + * + * A set of primitives for mutex locks that also support aiocb waits. + */ +#include +#include +#include +#include +#include + +struct mutex_wait { + struct mutex *lock; + wait_queue_t wait; +}; + +static inline void init_mutex_waiter(struct mutex_wait *waiter) +{ + waiter->lock = NULL; + init_waitqueue_entry(&waiter->wait, current); + INIT_LIST_HEAD(&waiter->wait.task_list); +} + +static int fastcall __mutex_lock(struct mutex *lk, struct mutex_wait *waiter) +{ + long flags; + int ret; + + spin_lock_irqsave(&lk->wait.lock, flags); + if (lk->owner != NULL) { + waiter->lock = lk; + add_wait_queue_exclusive_locked(&lk->wait, &waiter->wait); + ret = -EINPROGRESS; + } else { + lk->owner = waiter; + ret = 0; + } + spin_unlock_irqrestore(&lk->wait.lock, flags); + return ret; +} + +void fastcall mutex_unlock(struct mutex *lk) +{ + unsigned long flags; + BUG_ON(lk->owner == NULL); + spin_lock_irqsave(&lk->wait.lock, flags); + lk->owner = NULL; + wake_up_locked(&lk->wait); + spin_unlock_irqrestore(&lk->wait.lock, flags); +} +EXPORT_SYMBOL(mutex_unlock); + +int mutex_lock_wake_function(wait_queue_t *wait, unsigned mode, int sync, + void *key) +{ + struct mutex_wait *waiter = container_of(wait, struct mutex_wait, wait); + void **lk_owner = &waiter->lock->owner; + int ret = 0; + + if (*lk_owner == NULL) { + default_wake_function(wait, mode, sync, key); + *lk_owner = waiter; + list_del_init(&wait->task_list); + return 1; /* we made progress */ + } + return 0; +} + +void fastcall mutex_lock(struct mutex *lk) +{ + struct mutex_wait waiter; + + might_sleep(); + + init_mutex_waiter(&waiter); + waiter.wait.func = mutex_lock_wake_function; + + set_current_state(TASK_UNINTERRUPTIBLE); + if (__mutex_lock(lk, &waiter)) { + schedule(); + finish_wait(&lk->wait, &waiter.wait); + } + BUG_ON(lk->owner != &waiter); + __set_current_state(TASK_RUNNING); + + BUG_ON(!list_empty(&waiter.wait.task_list)); +} +EXPORT_SYMBOL(mutex_lock); + +int fastcall mutex_lock_interruptible(struct mutex *lk) +{ + struct mutex_wait waiter; + int ret = 0; + + might_sleep(); + + init_mutex_waiter(&waiter); + waiter.wait.func = mutex_lock_wake_function; + + set_current_state(TASK_INTERRUPTIBLE); + if (__mutex_lock(lk, &waiter)) { + schedule(); + if (signal_pending(current)) + ret = -EINTR; + finish_wait(&lk->wait, &waiter.wait); + if (lk->owner == &waiter) + ret = 0; + } + __set_current_state(TASK_RUNNING); + + BUG_ON(!list_empty(&waiter.wait.task_list)); + return ret; +} +EXPORT_SYMBOL(mutex_lock_interruptible); diff -purN v2.6.12-rc2-01_i_sem/Makefile v2.6.12-rc2-10_new_mutex/Makefile --- v2.6.12-rc2-01_i_sem/Makefile 2005-04-07 15:47:32.000000000 -0400 +++ v2.6.12-rc2-10_new_mutex/Makefile 2005-04-08 13:21:29.000000000 -0400 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 12 -EXTRAVERSION =-rc2-fs-mutex +EXTRAVERSION =-rc2-mutex-10 NAME=Woozy Numbat # *DOCUMENTATION*