mutex subsystem, core
PATCH 7/13 mutex subsystem, core
mutex implementation, core files: just the basic subsystem, no users of it.
Signed-off-by Ingo Molnar <[email protected]>
Signed-off-by Arjan van de Ven <[email protected]>
----
include/linux/mutex.h | 111 ++++++++++++ kernel/Makefile | 2 kernel/mutex.c | 434 ++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/mutex.h | 35 ++++ 4 files changed, 581 insertions(+), 1 deletion(-)
include/linux/mutex.h new file +111 -0
@@ -0,0 +1,111 @@ +/* +* Mutexes: blocking mutual exclusion locks +* +* started by Ingo Molnar: +* +* Copyright (C) 2004, 2005 Red Hat, Inc., Ingo Molnar <[email protected]> +* +* This file contains the main data structure and API definitions. +*/ +#ifndef __LINUX_MUTEX_H +#define __LINUX_MUTEX_H + +#include <linux/list.h> +#include <linux/spinlock_types.h> + +#include <asm/atomic.h> + +/* +* Simple, straightforward mutexes with strict semantics: +* +* - only one task can hold the mutex at a time +* - only the owner can unlock the mutex +* - multiple unlocks are not permitted +* - recursive locking is not permitted +* - a mutex object must be initialized via the API +* - a mutex object must not be initialized via memset or copying +* - task may not exit with mutex held +* - memory areas where held locks reside must not be freed +* - held mutexes must not be reinitialized +* - mutexes may not be used in irq contexts +* +* These semantics are fully enforced when DEBUG_MUTEXES is +* enabled. Furthermore, besides enforcing the above rules, the mutex +* debugging code also implements a number of additional features +* that make lock debugging easier and faster: +* +* - uses symbolic names of mutexes, whenever they are printed in debug output +* - point-of-acquire tracking, symbolic lookup of function names +* - list of all locks held in the system, printout of them +* - owner tracking +* - detects self-recursing locks and prints out all relevant info +* - detects multi-task circular deadlocks and prints out all affected +* locks and tasks (and only those tasks) +*/ +struct mutex { +/* 1: unlocked, 0: locked, negative: locked, possible waiters */ +atomic_t count; +spinlock_t wait_lock; +struct list_head wait_list; +#ifdef CONFIG_DEBUG_MUTEXES +struct thread_info *owner; +struct list_head held_list; +unsigned long acquire_ip; +const char *name; +void *magic; +#endif +}; + +/* +* This is the control structure for tasks blocked on mutex, +* which resides on the blocked task's kernel stack: +*/ +struct mutex_waiter { +struct list_head list; +struct thread_info *ti; +#ifdef CONFIG_DEBUG_MUTEXES +struct mutex *lock; +void *magic; +#endif +}; + +#ifdef CONFIG_DEBUG_MUTEXES +# include <linux/mutex-debug.h> +#else +# define __DEBUG_MUTEX_INITIALIZER (lockname) +# define mutex_init (mutex) __mutex_init(mutex, NULL) +# define mutex_destroy (mutex) do { } while (0) +# define mutex_debug_show_all_locks () do { } while (0) +# define mutex_debug_show_held_locks (p) do { } while (0) +# define mutex_debug_check_no_locks_held (task) do { } while (0) +# define mutex_debug_check_no_locks_freed (from, to) do { } while (0) +#endif + +#define __MUTEX_INITIALIZER (lockname) \ + { .count = ATOMIC_INIT(1) \ + , .wait_lock = SPIN_LOCK_UNLOCKED \ + , .wait_list = LIST_HEAD_INIT(lockname.wait_list) \ + __DEBUG_MUTEX_INITIALIZER(lockname) } + +#define DEFINE_MUTEX (mutexname) \ + struct mutex mutexname = __MUTEX_INITIALIZER(mutexname) + +extern void FASTCALL (__mutex_init (struct mutex *lock,const char *name)); + +/*** +* mutex_is_locked - is the mutex locked +* @lock: the mutex to be queried +* +* Returns 1 if the mutex is locked, 0 if unlocked. +*/ +static inline int fastcall mutex_is_locked(struct mutex *lock) +{ +return atomic_read (&lock->count) !=1 ; +} + +extern void FASTCALL (mutex_lock (struct mutex *lock)); +extern int FASTCALL (mutex_lock_interruptible (struct mutex *lock)); +extern int FASTCALL (mutex_trylock (struct mutex *lock)); +extern void FASTCALL (mutex_unlock (struct mutex *lock)); + +#endif
kernel/Makefile +1 -1
@@ -7,7 +7,7 @@ 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-$(CONFIG_FUTEX) += futex.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
kernel/mutex.c new file +434 -0
434 lines not on this page · raw message
kernel/mutex.h new file +35 -0
@@ -0,0 +1,35 @@ +/* +* Mutexes: blocking mutual exclusion locks +* +* started by Ingo Molnar: +* +* Copyright (C) 2004, 2005 Red Hat, Inc., Ingo Molnar <[email protected]> +* +* This file contains mutex debugging related internal prototypes, for the +* !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs: +*/ + +#define spin_lock_mutex (lock) spin_lock(lock) +#define spin_unlock_mutex (lock) spin_unlock(lock) +#define mutex_remove_waiter (lock, waiter, ti) \ + __list_del((waiter)->list.prev, (waiter)->list.next) + +#define DEBUG_WARN_ON (c) do { } while (0) +#define debug_mutex_set_owner (lock, new_owner) do { } while (0) +#define debug_mutex_clear_owner (lock) do { } while (0) +#define debug_mutex_init_waiter (waiter) do { } while (0) +#define debug_mutex_wake_waiter (lock, waiter) do { } while (0) +#define debug_mutex_free_waiter (waiter) do { } while (0) +#define debug_mutex_add_waiter (lock, waiter, ti, ip) do { } while (0) +#define debug_mutex_unlock (lock) do { } while (0) +#define debug_mutex_init (lock, name) do { } while (0) + +/* +* Return-address parameters/declarations. They are very useful for +* debugging, but add overhead in the !DEBUG case - so we go the +* trouble of using this not too elegant but zero-cost solution: +*/ +#define __IP_DECL__ +#define __IP__ +#define __RET_IP__ +