diff --git a/include/linux/sched.h b/include/linux/sched.h
index d7917b3..e96dcb3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -727,6 +727,10 @@ struct task_struct {
 	struct plist_head pi_waiters;
 	/* Deadlock detection and priority inheritance handling */
 	struct rt_mutex_waiter *pi_blocked_on;
+
+	struct robust_list_head __user *robust_list;
+	struct list_head pi_state_list;
+	void *pi_state_cache;
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
@@ -748,6 +752,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
 #define PF_STARTING	0x00000002	/* being created */
 #define PF_EXITING	0x00000004	/* getting shut down */
 #define PF_DEAD		0x00000008	/* Dead */
+#define PF_EXITPIDONE	0x00000010	/* pi exit done on shut down */
 #define PF_FORKNOEXEC	0x00000040	/* forked but didn't exec */
 #define PF_SUPERPRIV	0x00000100	/* used super-user privileges */
 #define PF_DUMPCORE	0x00000200	/* dumped core */
diff --git a/kernel/Makefile b/kernel/Makefile
index 9406e10..60fb695 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -19,7 +19,7 @@ obj-$(CONFIG_VZ_CHECKPOINT) += cpt/
 obj-$(CONFIG_VE_CALLS) += vzmon.o
 vzmon-objs = vecalls.o
 
-obj-$(CONFIG_FUTEX) += futex.o rtmutex.o
+obj-$(CONFIG_FUTEX) += futex.o rtmutex.o futex_pi.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
 obj-$(CONFIG_SMP) += cpu.o spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
diff --git a/kernel/exit.c b/kernel/exit.c
index 4d7b724..d5fdd41 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -19,6 +19,7 @@
 #include <linux/cpu.h>
 #include <linux/acct.h>
 #include <linux/file.h>
+#include <linux/futex_pi.h>
 #include <linux/binfmts.h>
 #include <linux/ptrace.h>
 #include <linux/profile.h>
@@ -979,6 +980,9 @@ asmlinkage NORET_TYPE void do_exit(long code)
 		current->tux_exit();
 	}
 
+	if (unlikely(tsk->robust_list))
+		exit_robust_list(tsk);
+
 	if (unlikely(tsk->audit_context))
 		audit_free(tsk);
 	__exit_mm(tsk);
@@ -1005,6 +1009,21 @@ asmlinkage NORET_TYPE void do_exit(long code)
 	tsk->mempolicy = NULL;
 #endif
 
+	/*
+	 * This must happen late, after the PID is not
+	 * hashed anymore:
+	 */
+	if (unlikely(!list_empty(&tsk->pi_state_list)))
+		exit_pi_state_list(tsk);
+	if (unlikely(current->pi_state_cache))
+		kfree(current->pi_state_cache);
+	/*
+	 * We can do this unlocked here. The futex code uses this flag
+	 * just to verify whether the pi state cleanup has been done
+	 * or not. In the worst case it loops once more.
+	 */
+	tsk->flags |= PF_EXITPIDONE;
+
 	BUG_ON(!(current->flags & PF_DEAD));
 	schedule();
 	BUG();
diff --git a/kernel/fork.c b/kernel/fork.c
index 0db6868..b1f682d 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1270,6 +1270,9 @@ task_t *copy_process(unsigned long clone_flags,
 	 * Clear TID on mm_release()?
 	 */
 	p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
+	p->robust_list = NULL;
+	INIT_LIST_HEAD(&p->pi_state_list);
+	p->pi_state_cache = NULL;
 
 	/*
 	 * Syscall tracing should be turned off in the child regardless
diff --git a/kernel/futex_pi.c b/kernel/futex_pi.c
index 4e82ac7..a7b1856 100644
--- a/kernel/futex_pi.c
+++ b/kernel/futex_pi.c
@@ -46,16 +46,25 @@
 #include <linux/file.h>
 #include <linux/jhash.h>
 #include <linux/init.h>
-#include <linux/futex.h>
+#include <linux/futex_pi.h>
 #include <linux/mount.h>
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/signal.h>
-#include <asm/futex.h>
+#include <asm/futex_pi.h>
 
 #include "rtmutex_common.h"
 
-#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
+#define FUTEX_HASHBITS 8
+
+/* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */
+static inline int valid_signal(unsigned long sig)
+{
+	return sig <= _NSIG ? 1 : 0;
+}
+
+#define timespec_valid(ts) \
+	(((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
 
 /*
  * Futexes are matched on equal values of this key.
@@ -728,10 +737,10 @@ double_lock_hb(struct futex_hash_bucket *hb1, struct futex_hash_bucket *hb2)
 	if (hb1 <= hb2) {
 		spin_lock(&hb1->lock);
 		if (hb1 < hb2)
-			spin_lock_nested(&hb2->lock, SINGLE_DEPTH_NESTING);
+			spin_lock(&hb2->lock);
 	} else { /* hb1 > hb2 */
 		spin_lock(&hb2->lock);
-		spin_lock_nested(&hb1->lock, SINGLE_DEPTH_NESTING);
+		spin_lock(&hb1->lock);
 	}
 }
 
@@ -1302,7 +1311,7 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
 			 int detect, unsigned long sec,
 			 long nsec, int trylock)
 {
-	struct hrtimer_sleeper timeout, *to = NULL;
+	struct timer_list timeout, *to = NULL;
 	struct task_struct *curr = current;
 	struct futex_hash_bucket *hb;
 	u32 uval, newval, curval;
@@ -1314,9 +1323,10 @@ static int futex_lock_pi(u32 __user *uaddr, struct rw_semaphore *fshared,
 
 	if (sec != MAX_SCHEDULE_TIMEOUT) {
 		to = &timeout;
-		hrtimer_init(&to->timer, CLOCK_REALTIME, HRTIMER_ABS);
-		hrtimer_init_sleeper(to, current);
-		to->timer.expires = ktime_set(sec, nsec);
+		init_timer(&timeout);
+		timeout.expires = jiffies + sec * HZ + nsec * HZ / NSEC_PER_SEC;
+		timeout.data = (unsigned long) curr;
+		timeout.function = rt_mutex_timeout_fn;
 	}
 
 	q.pi_state = NULL;
@@ -2005,7 +2015,7 @@ void exit_robust_list(struct task_struct *curr)
 				   curr, pip);
 }
 
-long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
+long do_futex_pi(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
 		u32 __user *uaddr2, u32 val2, u32 val3)
 {
 	int ret;
@@ -2051,7 +2061,7 @@ long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
 }
 
 
-asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
+asmlinkage long sys_futex_pi(u32 __user *uaddr, int op, u32 val,
 			  struct timespec __user *utime, u32 __user *uaddr2,
 			  u32 val3)
 {
@@ -2078,18 +2088,17 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
 	if (cmd == FUTEX_REQUEUE || cmd == FUTEX_CMP_REQUEUE)
 		val2 = (u32) (unsigned long) utime;
 
-	return do_futex(uaddr, op, val, timeout, uaddr2, val2, val3);
+	return do_futex_pi(uaddr, op, val, timeout, uaddr2, val2, val3);
 }
 
-static int futexfs_get_sb(struct file_system_type *fs_type,
-			  int flags, const char *dev_name, void *data,
-			  struct vfsmount *mnt)
+static struct super_block *futexfs_get_sb(struct file_system_type *fs_type,
+			  int flags, const char *dev_name, void *data)
 {
-	return get_sb_pseudo(fs_type, "futex", NULL, 0xBAD1DEA, mnt);
+	return get_sb_pseudo(fs_type, "futex_pi", NULL, 0xBAD1DEA);
 }
 
 static struct file_system_type futex_fs_type = {
-	.name		= "futexfs",
+	.name		= "futexfs_pi",
 	.get_sb		= futexfs_get_sb,
 	.kill_sb	= kill_anon_super,
 };
