Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Kernel v2.6.24.4 /kernel/futex.c

Filename:/kernel/futex.c
Lines Added:42
Lines Deleted:10
Also changed in: (Previous) 2.6.24.4-rc3  2.6.24.4-rc2  2.6.24.4-rc1  2.6.24.3  2.6.24.3-rc1  2.6.24-git22 
(Following) 2.6.24.5  2.6.24.6  2.6.24.7  2.6.25-rc7  2.6.25-rc7-git3  2.6.25-rc7-git4 

Location
[  2.6.24.4
  [  kernel
     o  futex.c

Patch

diff --git a/kernel/futex.c b/kernel/futex.c
index db9824d..d166080 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -60,6 +60,8 @@
 
 #include "rtmutex_common.h"
 
+int __read_mostly futex_cmpxchg_enabled;
+
 #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
 /*
@@ -466,6 +468,8 @@ void exit_pi_state_list(struct task_struct *curr)
    struct futex_hash_bucket *hb;
    union futex_key key;
 
+   if (!futex_cmpxchg_enabled)
+      return;
    /*
     * We are a ZOMBIE and nobody can enqueue itself on
     * pi_state_list anymore, but we have to be careful
@@ -1854,6 +1858,8 @@ asmlinkage long
 sys_set_robust_list(struct robust_list_head __user *head,
           size_t len)
 {
+   if (!futex_cmpxchg_enabled)
+      return -ENOSYS;
    /*
     * The kernel knows only one size for now:
     */
@@ -1878,6 +1884,9 @@ sys_get_robust_list(int pid, struct robust_list_head __user * __user *head_ptr,
    struct robust_list_head __user *head;
    unsigned long ret;
 
+   if (!futex_cmpxchg_enabled)
+      return -ENOSYS;
+
    if (!pid)
       head = current->robust_list;
    else {
@@ -1980,6 +1989,9 @@ void exit_robust_list(struct task_struct *curr)
    unsigned long futex_offset;
    int rc;
 
+   if (!futex_cmpxchg_enabled)
+      return;
+
    /*
     * Fetch the list head (which was registered earlier, via
     * sys_set_robust_list()):
@@ -2034,7 +2046,7 @@ void exit_robust_list(struct task_struct *curr)
 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
       u32 __user *uaddr2, u32 val2, u32 val3)
 {
-   int ret;
+   int ret = -ENOSYS;
    int cmd = op & FUTEX_CMD_MASK;
    struct rw_semaphore *fshared = NULL;
 
@@ -2062,13 +2074,16 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout,
       ret = futex_wake_op(uaddr, fshared, uaddr2, val, val2, val3);
       break;
    case FUTEX_LOCK_PI:
-      ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
+      if (futex_cmpxchg_enabled)
+         ret = futex_lock_pi(uaddr, fshared, val, timeout, 0);
       break;
    case FUTEX_UNLOCK_PI:
-      ret = futex_unlock_pi(uaddr, fshared);
+      if (futex_cmpxchg_enabled)
+         ret = futex_unlock_pi(uaddr, fshared);
       break;
    case FUTEX_TRYLOCK_PI:
-      ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
+      if (futex_cmpxchg_enabled)
+         ret = futex_lock_pi(uaddr, fshared, 0, timeout, 1);
       break;
    default:
       ret = -ENOSYS;
@@ -2094,7 +2109,7 @@ asmlinkage long sys_futex(u32 __user *uaddr, int op, u32 val,
 
       t = timespec_to_ktime(ts);
       if (cmd == FUTEX_WAIT)
-         t = ktime_add(ktime_get(), t);
+         t = ktime_add_safe(ktime_get(), t);
       tp = &t;
    }
    /*
@@ -2123,8 +2138,29 @@ static struct file_system_type futex_fs_type = {
 
 static int __init init(void)
 {
-   int i = register_filesystem(&futex_fs_type);
+   u32 curval;
+   int i;
+
+   /*
+    * This will fail and we want it. Some arch implementations do
+    * runtime detection of the futex_atomic_cmpxchg_inatomic()
+    * functionality. We want to know that before we call in any
+    * of the complex code paths. Also we want to prevent
+    * registration of robust lists in that case. NULL is
+    * guaranteed to fault and we get -EFAULT on functional
+    * implementation, the non functional ones will return
+    * -ENOSYS.
+    */
+   curval = cmpxchg_futex_value_locked(NULL, 0, 0);
+   if (curval == -EFAULT)
+      futex_cmpxchg_enabled = 1;
 
+   for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
+      plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock);
+      spin_lock_init(&futex_queues[i].lock);
+   }
+
+   i = register_filesystem(&futex_fs_type);
    if (i)
       return i;
 
@@ -2134,10 +2170,6 @@ static int __init init(void)
       return PTR_ERR(futex_mnt);
    }
 
-   for (i = 0; i < ARRAY_SIZE(futex_queues); i++) {
-      plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock);
-      spin_lock_init(&futex_queues[i].lock);
-   }
    return 0;
 }
 __initcall(init);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.