Skip to content

Commit

Permalink
[PATCH] pi-futex: rt mutex core
Browse files Browse the repository at this point in the history
Core functions for the rt-mutex subsystem.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Ingo Molnar authored and Linus Torvalds committed Jun 28, 2006
1 parent b29739f commit 23f78d4
Show file tree
Hide file tree
Showing 11 changed files with 1,181 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/init_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ extern struct group_info init_groups;
.cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \
.fs_excl = ATOMIC_INIT(0), \
.pi_lock = SPIN_LOCK_UNLOCKED, \
INIT_RT_MUTEXES(tsk) \
}


Expand Down
104 changes: 104 additions & 0 deletions include/linux/rtmutex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* RT Mutexes: blocking mutual exclusion locks with PI support
*
* started by Ingo Molnar and Thomas Gleixner:
*
* Copyright (C) 2004-2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
* Copyright (C) 2006, Timesys Corp., Thomas Gleixner <tglx@timesys.com>
*
* This file contains the public data structure and API definitions.
*/

#ifndef __LINUX_RT_MUTEX_H
#define __LINUX_RT_MUTEX_H

#include <linux/linkage.h>
#include <linux/plist.h>
#include <linux/spinlock_types.h>

/*
* The rt_mutex structure
*
* @wait_lock: spinlock to protect the structure
* @wait_list: pilist head to enqueue waiters in priority order
* @owner: the mutex owner
*/
struct rt_mutex {
spinlock_t wait_lock;
struct plist_head wait_list;
struct task_struct *owner;
#ifdef CONFIG_DEBUG_RT_MUTEXES
int save_state;
struct list_head held_list_entry;
unsigned long acquire_ip;
const char *name, *file;
int line;
void *magic;
#endif
};

struct rt_mutex_waiter;
struct hrtimer_sleeper;

#ifdef CONFIG_DEBUG_RT_MUTEXES
# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname) \
, .name = #mutexname, .file = __FILE__, .line = __LINE__
# define rt_mutex_init(mutex) __rt_mutex_init(mutex, __FUNCTION__)
extern void rt_mutex_debug_task_free(struct task_struct *tsk);
#else
# define __DEBUG_RT_MUTEX_INITIALIZER(mutexname)
# define rt_mutex_init(mutex) __rt_mutex_init(mutex, NULL)
# define rt_mutex_debug_task_free(t) do { } while (0)
#endif

#define __RT_MUTEX_INITIALIZER(mutexname) \
{ .wait_lock = SPIN_LOCK_UNLOCKED \
, .wait_list = PLIST_HEAD_INIT(mutexname.wait_list, mutexname.wait_lock) \
, .owner = NULL \
__DEBUG_RT_MUTEX_INITIALIZER(mutexname)}

#define DEFINE_RT_MUTEX(mutexname) \
struct rt_mutex mutexname = __RT_MUTEX_INITIALIZER(mutexname)

/***
* rt_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 rt_mutex_is_locked(struct rt_mutex *lock)
{
return lock->owner != NULL;
}

extern void __rt_mutex_init(struct rt_mutex *lock, const char *name);
extern void rt_mutex_destroy(struct rt_mutex *lock);

extern void rt_mutex_lock(struct rt_mutex *lock);
extern int rt_mutex_lock_interruptible(struct rt_mutex *lock,
int detect_deadlock);
extern int rt_mutex_timed_lock(struct rt_mutex *lock,
struct hrtimer_sleeper *timeout,
int detect_deadlock);

extern int rt_mutex_trylock(struct rt_mutex *lock);

extern void rt_mutex_unlock(struct rt_mutex *lock);

#ifdef CONFIG_DEBUG_RT_MUTEXES
# define INIT_RT_MUTEX_DEBUG(tsk) \
.held_list_head = LIST_HEAD_INIT(tsk.held_list_head), \
.held_list_lock = SPIN_LOCK_UNLOCKED
#else
# define INIT_RT_MUTEX_DEBUG(tsk)
#endif

#ifdef CONFIG_RT_MUTEXES
# define INIT_RT_MUTEXES(tsk) \
.pi_waiters = PLIST_HEAD_INIT(tsk.pi_waiters, tsk.pi_lock), \
INIT_RT_MUTEX_DEBUG(tsk)
#else
# define INIT_RT_MUTEXES(tsk)
#endif

#endif
12 changes: 12 additions & 0 deletions include/linux/sched.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ struct sched_param {
#include <linux/seccomp.h>
#include <linux/rcupdate.h>
#include <linux/futex.h>
#include <linux/rtmutex.h>

#include <linux/time.h>
#include <linux/param.h>
Expand Down Expand Up @@ -858,6 +859,17 @@ struct task_struct {
/* Protection of the PI data structures: */
spinlock_t pi_lock;

#ifdef CONFIG_RT_MUTEXES
/* PI waiters blocked on a rt_mutex held by this task */
struct plist_head pi_waiters;
/* Deadlock detection and priority inheritance handling */
struct rt_mutex_waiter *pi_blocked_on;
# ifdef CONFIG_DEBUG_RT_MUTEXES
spinlock_t held_list_lock;
struct list_head held_list_head;
# endif
#endif

#ifdef CONFIG_DEBUG_MUTEXES
/* mutex deadlock detection */
struct mutex_waiter *blocked_on;
Expand Down
1 change: 1 addition & 0 deletions include/linux/sysctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ enum
KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */
KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */
KERN_COMPAT_LOG=73, /* int: print compat layer messages */
KERN_MAX_LOCK_DEPTH=74,
};


Expand Down
5 changes: 5 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,14 @@ config BASE_FULL
kernel data structures. This saves memory on small machines,
but may reduce performance.

config RT_MUTEXES
boolean
select PLIST

config FUTEX
bool "Enable futex support" if EMBEDDED
default y
select RT_MUTEXES
help
Disabling this option will cause the kernel to be built without
support for "fast userspace mutexes". The resulting kernel may not
Expand Down
1 change: 1 addition & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ obj-$(CONFIG_FUTEX) += futex.o
ifeq ($(CONFIG_COMPAT),y)
obj-$(CONFIG_FUTEX) += futex_compat.o
endif
obj-$(CONFIG_RT_MUTEXES) += rtmutex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
obj-$(CONFIG_SMP) += cpu.o spinlock.o
obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock.o
Expand Down
16 changes: 16 additions & 0 deletions kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ static kmem_cache_t *mm_cachep;
void free_task(struct task_struct *tsk)
{
free_thread_info(tsk->thread_info);
rt_mutex_debug_task_free(tsk);
free_task_struct(tsk);
}
EXPORT_SYMBOL(free_task);
Expand Down Expand Up @@ -913,6 +914,19 @@ asmlinkage long sys_set_tid_address(int __user *tidptr)
return current->pid;
}

static inline void rt_mutex_init_task(struct task_struct *p)
{
#ifdef CONFIG_RT_MUTEXES
spin_lock_init(&p->pi_lock);
plist_head_init(&p->pi_waiters, &p->pi_lock);
p->pi_blocked_on = NULL;
# ifdef CONFIG_DEBUG_RT_MUTEXES
spin_lock_init(&p->held_list_lock);
INIT_LIST_HEAD(&p->held_list_head);
# endif
#endif
}

/*
* This creates a new process as a copy of the old one,
* but does not actually start it yet.
Expand Down Expand Up @@ -1034,6 +1048,8 @@ static task_t *copy_process(unsigned long clone_flags,
mpol_fix_fork_child_flag(p);
#endif

rt_mutex_init_task(p);

#ifdef CONFIG_DEBUG_MUTEXES
p->blocked_on = NULL; /* not blocked yet */
#endif
Expand Down
Loading

0 comments on commit 23f78d4

Please sign in to comment.