aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/futex.h29
-rw-r--r--kernel/futex.c50
2 files changed, 43 insertions, 36 deletions
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 3f153b4e156c..820125c628c1 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -100,6 +100,35 @@ long do_futex(u32 __user *uaddr, int op, u32 val, unsigned long timeout,
100extern int 100extern int
101handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi); 101handle_futex_death(u32 __user *uaddr, struct task_struct *curr, int pi);
102 102
103/*
104 * Futexes are matched on equal values of this key.
105 * The key type depends on whether it's a shared or private mapping.
106 * Don't rearrange members without looking at hash_futex().
107 *
108 * offset is aligned to a multiple of sizeof(u32) (== 4) by definition.
109 * We set bit 0 to indicate if it's an inode-based key.
110 */
111union futex_key {
112 struct {
113 unsigned long pgoff;
114 struct inode *inode;
115 int offset;
116 } shared;
117 struct {
118 unsigned long address;
119 struct mm_struct *mm;
120 int offset;
121 } private;
122 struct {
123 unsigned long word;
124 void *ptr;
125 int offset;
126 } both;
127};
128int get_futex_key(u32 __user *uaddr, union futex_key *key);
129void get_futex_key_refs(union futex_key *key);
130void drop_futex_key_refs(union futex_key *key);
131
103#ifdef CONFIG_FUTEX 132#ifdef CONFIG_FUTEX
104extern void exit_robust_list(struct task_struct *curr); 133extern void exit_robust_list(struct task_struct *curr);
105extern void exit_pi_state_list(struct task_struct *curr); 134extern void exit_pi_state_list(struct task_struct *curr);
diff --git a/kernel/futex.c b/kernel/futex.c
index 5a270b5e3f95..7ae2f50641ed 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -48,6 +48,7 @@
48#include <linux/pagemap.h> 48#include <linux/pagemap.h>
49#include <linux/syscalls.h> 49#include <linux/syscalls.h>
50#include <linux/signal.h> 50#include <linux/signal.h>
51#include <linux/module.h>
51#include <asm/futex.h> 52#include <asm/futex.h>
52 53
53#include "rtmutex_common.h" 54#include "rtmutex_common.h"
@@ -55,32 +56,6 @@
55#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) 56#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
56 57
57/* 58/*
58 * Futexes are matched on equal values of this key.
59 * The key type depends on whether it's a shared or private mapping.
60 * Don't rearrange members without looking at hash_futex().
61 *
62 * offset is aligned to a multiple of sizeof(u32) (== 4) by definition.
63 * We set bit 0 to indicate if it's an inode-based key.
64 */
65union futex_key {
66 struct {
67 unsigned long pgoff;
68 struct inode *inode;
69 int offset;
70 } shared;
71 struct {
72 unsigned long address;
73 struct mm_struct *mm;
74 int offset;
75 } private;
76 struct {
77 unsigned long word;
78 void *ptr;
79 int offset;
80 } both;
81};
82
83/*
84 * Priority Inheritance state: 59 * Priority Inheritance state:
85 */ 60 */
86struct futex_pi_state { 61struct futex_pi_state {
@@ -175,7 +150,7 @@ static inline int match_futex(union futex_key *key1, union futex_key *key2)
175 * 150 *
176 * Should be called with &current->mm->mmap_sem but NOT any spinlocks. 151 * Should be called with &current->mm->mmap_sem but NOT any spinlocks.
177 */ 152 */
178static int get_futex_key(u32 __user *uaddr, union futex_key *key) 153int get_futex_key(u32 __user *uaddr, union futex_key *key)
179{ 154{
180 unsigned long address = (unsigned long)uaddr; 155 unsigned long address = (unsigned long)uaddr;
181 struct mm_struct *mm = current->mm; 156 struct mm_struct *mm = current->mm;
@@ -246,6 +221,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
246 } 221 }
247 return err; 222 return err;
248} 223}
224EXPORT_SYMBOL_GPL(get_futex_key);
249 225
250/* 226/*
251 * Take a reference to the resource addressed by a key. 227 * Take a reference to the resource addressed by a key.
@@ -254,7 +230,7 @@ static int get_futex_key(u32 __user *uaddr, union futex_key *key)
254 * NOTE: mmap_sem MUST be held between get_futex_key() and calling this 230 * NOTE: mmap_sem MUST be held between get_futex_key() and calling this
255 * function, if it is called at all. mmap_sem keeps key->shared.inode valid. 231 * function, if it is called at all. mmap_sem keeps key->shared.inode valid.
256 */ 232 */
257static inline void get_key_refs(union futex_key *key) 233inline void get_futex_key_refs(union futex_key *key)
258{ 234{
259 if (key->both.ptr != 0) { 235 if (key->both.ptr != 0) {
260 if (key->both.offset & 1) 236 if (key->both.offset & 1)
@@ -263,12 +239,13 @@ static inline void get_key_refs(union futex_key *key)
263 atomic_inc(&key->private.mm->mm_count); 239 atomic_inc(&key->private.mm->mm_count);
264 } 240 }
265} 241}
242EXPORT_SYMBOL_GPL(get_futex_key_refs);
266 243
267/* 244/*
268 * Drop a reference to the resource addressed by a key. 245 * Drop a reference to the resource addressed by a key.
269 * The hash bucket spinlock must not be held. 246 * The hash bucket spinlock must not be held.
270 */ 247 */
271static void drop_key_refs(union futex_key *key) 248void drop_futex_key_refs(union futex_key *key)
272{ 249{
273 if (key->both.ptr != 0) { 250 if (key->both.ptr != 0) {
274 if (key->both.offset & 1) 251 if (key->both.offset & 1)
@@ -277,6 +254,7 @@ static void drop_key_refs(union futex_key *key)
277 mmdrop(key->private.mm); 254 mmdrop(key->private.mm);
278 } 255 }
279} 256}
257EXPORT_SYMBOL_GPL(drop_futex_key_refs);
280 258
281static inline int get_futex_value_locked(u32 *dest, u32 __user *from) 259static inline int get_futex_value_locked(u32 *dest, u32 __user *from)
282{ 260{
@@ -873,7 +851,7 @@ static int futex_requeue(u32 __user *uaddr1, u32 __user *uaddr2,
873 this->lock_ptr = &hb2->lock; 851 this->lock_ptr = &hb2->lock;
874 } 852 }
875 this->key = key2; 853 this->key = key2;
876 get_key_refs(&key2); 854 get_futex_key_refs(&key2);
877 drop_count++; 855 drop_count++;
878 856
879 if (ret - nr_wake >= nr_requeue) 857 if (ret - nr_wake >= nr_requeue)
@@ -886,9 +864,9 @@ out_unlock:
886 if (hb1 != hb2) 864 if (hb1 != hb2)
887 spin_unlock(&hb2->lock); 865 spin_unlock(&hb2->lock);
888 866
889 /* drop_key_refs() must be called outside the spinlocks. */ 867 /* drop_futex_key_refs() must be called outside the spinlocks. */
890 while (--drop_count >= 0) 868 while (--drop_count >= 0)
891 drop_key_refs(&key1); 869 drop_futex_key_refs(&key1);
892 870
893out: 871out:
894 up_read(&current->mm->mmap_sem); 872 up_read(&current->mm->mmap_sem);
@@ -906,7 +884,7 @@ queue_lock(struct futex_q *q, int fd, struct file *filp)
906 884
907 init_waitqueue_head(&q->waiters); 885 init_waitqueue_head(&q->waiters);
908 886
909 get_key_refs(&q->key); 887 get_futex_key_refs(&q->key);
910 hb = hash_futex(&q->key); 888 hb = hash_futex(&q->key);
911 q->lock_ptr = &hb->lock; 889 q->lock_ptr = &hb->lock;
912 890
@@ -925,7 +903,7 @@ static inline void
925queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb) 903queue_unlock(struct futex_q *q, struct futex_hash_bucket *hb)
926{ 904{
927 spin_unlock(&hb->lock); 905 spin_unlock(&hb->lock);
928 drop_key_refs(&q->key); 906 drop_futex_key_refs(&q->key);
929} 907}
930 908
931/* 909/*
@@ -980,7 +958,7 @@ static int unqueue_me(struct futex_q *q)
980 ret = 1; 958 ret = 1;
981 } 959 }
982 960
983 drop_key_refs(&q->key); 961 drop_futex_key_refs(&q->key);
984 return ret; 962 return ret;
985} 963}
986 964
@@ -999,7 +977,7 @@ static void unqueue_me_pi(struct futex_q *q, struct futex_hash_bucket *hb)
999 977
1000 spin_unlock(&hb->lock); 978 spin_unlock(&hb->lock);
1001 979
1002 drop_key_refs(&q->key); 980 drop_futex_key_refs(&q->key);
1003} 981}
1004 982
1005static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time) 983static int futex_wait(u32 __user *uaddr, u32 val, unsigned long time)