Futexes functionalities and improvements
cover Futexes functionalities and improvements
Hi Andrew,
This is a re-send of a series of patches concerning futexes (here
after is a short description).
I have reworked the patches to take into account the last changes
about futex, and this series should apply cleanly on -mm tree (the changes mostly affect patch 2 "futex_wait uses hrtimer")
I also took into account the remark of Peter Zijlstra in patch 3
concerning futex_requeue_pi.
Could you consider (again) them for inclusion in -mm tree ?
All of them have already been discussed in January and have already
been included in -rt for a while. I think that we agreed to potentially include them in the -mm tree.
And, again, Ulrich is specially interested by sys_futex64.
There are:
* futex uses prio list : allows RT-threads to be woken in priority order
instead of FIFO order.
* futex_wait uses hrtimer : allows the use of finer timer resolution.
* futex_requeue_pi functionality : allows use of requeue optimization for
PI-mutexes/PI-futexes.
* futex64 syscall : allows use of 64-bit futexes instead of 32-bit.
Thanks,
Signature · 1 line
Pierre P.
PATCH 1/4 futex priority based wakeup
Today, all threads waiting for a given futex are woken in FIFO order (first waiter woken first) instead of priority order.
This patch makes use of plist (pirotity ordered lists) instead of simple list in futex_hash_bucket.
All non-RT threads are stored with priority MAX_RT_PRIO, causing them to be woken last, in FIFO order (RT-threads are woken first, in priority order).
--- kernel/futex.c | 78 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 29 deletions(-)
kernel/futex.c +49 -29
@@ -81,12 +81,12 @@ struct futex_pi_state {* we can wake only the relevant ones (hashed queues may be shared). * * A futex_q has a woken state, just like tasks have TASK_RUNNING. -* It is considered woken when list_empty(&q->list) || q->lock_ptr == 0. +* It is considered woken when plist_node_empty(&q->list) || q->lock_ptr == 0. * The order of wakup is always to make the first condition true, then * wake up q->waiters, then make the second condition true. */ struct futex_q { -struct list_head list; +struct plist_node list;wait_queue_head_t waiters;/* Which hash list lock to use: */
@@ -108,8 +108,8 @@ struct futex_q {* Split the global futex_lock into every hash list lock. */ struct futex_hash_bucket { -spinlock_t lock; -struct list_head chain; +spinlock_t lock; +struct plist_head chain; };static struct futex_hash_bucket futex_queues[1 <<FUTEX_HASHBITS ];
@@ -443,13 +443,13 @@ lookup_pi_state(u32 uval, struct futex_h {struct futex_pi_state *pi_state =NULL ;struct futex_q *this, *next; -struct list_head *head; +struct plist_head *head;struct task_struct *p;pid_t pid; head = &hb->chain; -list_for_each_entry_safe (this, next, head, list) { +plist_for_each_entry_safe (this, next, head, list) {if (match_futex (&this->key, &me->key)) {/* * Another waiter already exists - bump up
@@ -513,12 +513,12 @@ lookup_pi_state(u32 uval, struct futex_h*/ static void wake_futex (struct futex_q *q) { -list_del_init (&q->list); +plist_del (&q->list, &q->list.plist);if (q->filp)send_sigio (&q->filp->f_owner, q->fd,POLL_IN );/* * The lock in wake_up_all() is a crucial memory barrier after the -* list_del_init() and also before assigning to q->lock_ptr. +* plist_del() and also before assigning to q->lock_ptr. */ wake_up_all (&q->waiters);/*
@@ -633,7 +633,7 @@ static int futex_wake(u32 __user *uaddr, {struct futex_hash_bucket *hb;struct futex_q *this, *next; -struct list_head *head; +struct plist_head *head;union futex_key key;int ret;
@@ -647,7 +647,7 @@ static int futex_wake(u32 __user *uaddr,spin_lock (&hb->lock); head = &hb->chain; -list_for_each_entry_safe (this, next, head, list) { +plist_for_each_entry_safe (this, next, head, list) {if (match_futex (&this->key, &key)) {if (this->pi_state) { ret = -EINVAL ;
@@ -675,7 +675,7 @@ futex_wake_op(u32 __user *uaddr1, u32 __ {union futex_key key1, key2;struct futex_hash_bucket *hb1, *hb2; -struct list_head *head; +struct plist_head *head;struct futex_q *this, *next;int ret, op_ret, attempt =0 ;
@@ -748,7 +748,7 @@ retry: head = &hb1->chain; -list_for_each_entry_safe (this, next, head, list) { +plist_for_each_entry_safe (this, next, head, list) {if (match_futex (&this->key, &key1)) {wake_futex (this);if (++ret >= nr_wake)
@@ -760,7 +760,7 @@ retry: head = &hb2->chain; op_ret =0 ; -list_for_each_entry_safe (this, next, head, list) { +plist_for_each_entry_safe (this, next, head, list) {if (match_futex (&this->key, &key2)) {wake_futex (this);if (++op_ret >= nr_wake2)
@@ -787,7 +787,7 @@ static int futex_requeue(u32 __user *uad {union futex_key key1, key2;struct futex_hash_bucket *hb1, *hb2; -struct list_head *head1; +struct plist_head *head1;struct futex_q *this, *next;int ret, drop_count =0 ;
@@ -836,7 +836,7 @@ static int futex_requeue(u32 __user *uad } head1 = &hb1->chain; -list_for_each_entry_safe (this, next, head1, list) { +plist_for_each_entry_safe (this, next, head1, list) {if (!match_futex (&this->key, &key1))continue ;if (++ret <= nr_wake) {
@@ -847,9 +847,13 @@ static int futex_requeue(u32 __user *uad* requeue. */ if (likely (head1 != &hb2->chain)) { -list_move_tail (&this->list, &hb2->chain); +plist_del (&this->list, &hb1->chain); +plist_add (&this->list, &hb2->chain); this->lock_ptr = &hb2->lock; - } +#ifdef CONFIG_DEBUG_PI_LIST + this->list.plist.lock = &hb2->lock; +#endif + } this->key = key2;get_futex_key_refs (&key2); drop_count++;
@@ -894,7 +898,23 @@ queue_lock(struct futex_q *q, int fd, ststatic inline void __queue_me (struct futex_q *q,struct futex_hash_bucket *hb) { -list_add_tail (&q->list, &hb->chain); +int prio; + +/* +* The priority used to register this element is +* - either the real thread-priority for the real-time threads +* (i.e. threads with a priority lower than MAX_RT_PRIO) +* - or MAX_RT_PRIO for non-RT threads. +* Thus, all RT-threads are woken first in priority order, and +* the others are woken last, in FIFO order. +*/ + prio =min (current->normal_prio,MAX_RT_PRIO ); + +plist_node_init (&q->list, prio); +#ifdef CONFIG_DEBUG_PI_LIST + q->list.plist.lock = &hb->lock; +#endif +plist_add (&q->list, &hb->chain); q->task = current;spin_unlock (&hb->lock); }
@@ -949,8 +969,8 @@ static int unqueue_me(struct futex_q *q)spin_unlock (lock_ptr); goto retry; } -WARN_ON (list_empty (&q->list)); -list_del (&q->list); +WARN_ON (plist_node_empty (&q->list)); +plist_del (&q->list, &q->list.plist);BUG_ON (q->pi_state);
@@ -968,8 +988,8 @@ static int unqueue_me(struct futex_q *q)*/ static void unqueue_me_pi (struct futex_q *q,struct futex_hash_bucket *hb) { -WARN_ON (list_empty (&q->list)); -list_del (&q->list); +WARN_ON (plist_node_empty (&q->list)); +plist_del (&q->list, &q->list.plist);BUG_ON (!q->pi_state);free_pi_state (q->pi_state);
@@ -1065,11 +1085,11 @@ static int futex_wait_abstime(u32 __user__set_current_state (TASK_INTERRUPTIBLE );add_wait_queue (&q.waiters, &wait);/* -* !list_empty() is safe here without any lock. +* !plist_node_empty() is safe here without any lock. * q.lock_ptr != 0 is not safe, because of ordering against wakeup. */ time_left =0 ; -if (likely (!list_empty (&q.list))) { +if (likely (!plist_node_empty (&q.list))) {unsigned long rel_time;if (timed) {
@@ -1384,7 +1404,7 @@ static int futex_unlock_pi(u32 __user *ustruct futex_hash_bucket *hb;struct futex_q *this, *next;u32 uval; -struct list_head *head; +struct plist_head *head;union futex_key key;int ret, attempt =0 ;
@@ -1435,7 +1455,7 @@ retry_locked:*/ head = &hb->chain; -list_for_each_entry_safe (this, next, head, list) { +plist_for_each_entry_safe (this, next, head, list) {if (!match_futex (&this->key, &key))continue ; ret =wake_futex_pi (uaddr, uval, this);
@@ -1509,10 +1529,10 @@ static unsigned int futex_poll(struct fipoll_wait (filp, &q->waiters, wait);/* -* list_empty() is safe here without any lock. +* plist_node_empty() is safe here without any lock. * q->lock_ptr != 0 is not safe, because of ordering against wakeup. */ -if (list_empty (&q->list)) +if (plist_node_empty (&q->list)) ret =POLLIN |POLLRDNORM ;return ret;
@@ -1895,7 +1915,7 @@ static int __init init(void) }for (i =0 ; i <ARRAY_SIZE (futex_queues); i++) { -INIT_LIST_HEAD (&futex_queues[i].chain); +plist_head_init (&futex_queues[i].chain, &futex_queues[i].lock);spin_lock_init (&futex_queues[i].lock); }return 0 ;
Signature · 1 line
Pierre Peiffer
PATCH 2/4 Make futex_wait() use an hrtimer for timeout
In reply to [email protected]This patch modifies futex_wait() to use an hrtimer + schedule() in place of schedule_timeout().
schedule_timeout() is tick based, therefore the timeout granularity is
the tick (1 ms, 4 ms or 10 ms depending on HZ). By using a high resolution timer for timeout wakeup, we can attain a much finer timeout granularity (in the microsecond range). This parallels what is already done for futex_lock_pi().
The timeout passed to the syscall is no longer converted to jiffies
and is therefore passed to do_futex() and futex_wait() as an absolute ktime_t therefore keeping nanosecond resolution.
Also this removes the need to pass the nanoseconds timeout part tofutex_lock_pi() in val2.
In futex_wait(), if there is no timeout then a regular schedule() is
performed. Otherwise, an hrtimer is fired before schedule() is called.
--- include/linux/futex.h | 3 + kernel/futex.c | 85 ++++++++++++++++++++++++-------------------------- kernel/futex_compat.c | 17 ++++------ 3 files changed, 51 insertions(+), 54 deletions(-)
kernel/futex.c +42 -43
@@ -1001,16 +1001,16 @@ static void unqueue_me_pi(struct futex_q }static long futex_wait_restart (struct restart_block *restart); -static int futex_wait_abstime (u32 __user *uaddr,u32 val, -int timed,unsigned long abs_time) +static int futex_wait (u32 __user *uaddr,u32 val,ktime_t *abs_time) {struct task_struct *curr = current;DECLARE_WAITQUEUE (wait, curr);struct futex_hash_bucket *hb;struct futex_q q; -unsigned long time_left =0 ;u32 uval;int ret; +struct hrtimer_sleeper t; +int rem =0 ; q.pi_state =NULL ; retry:
@@ -1088,20 +1088,29 @@ static int futex_wait_abstime(u32 __user* !plist_node_empty() is safe here without any lock. * q.lock_ptr != 0 is not safe, because of ordering against wakeup. */ - time_left =0 ;if (likely (!plist_node_empty (&q.list))) { -unsigned long rel_time; +if (!abs_time) +schedule (); +else { +hrtimer_init (&t.timer,CLOCK_MONOTONIC ,HRTIMER_MODE_ABS ); +hrtimer_init_sleeper (&t, current); + t.timer.expires = *abs_time; + +hrtimer_start (&t.timer, t.timer.expires,HRTIMER_MODE_ABS ); + +/* +* the timer could have already expired, in which +* case current would be flagged for rescheduling. +* Don't bother calling schedule. +*/ +if (likely (t.task)) +schedule (); -if (timed) { -unsigned long now = jiffies; -if (time_after (now, abs_time)) - rel_time =0 ; -else - rel_time = abs_time - now; - }else - rel_time =MAX_SCHEDULE_TIMEOUT ; +hrtimer_cancel (&t.timer); - time_left =schedule_timeout (rel_time); +/* Flag if a timeout occured */ + rem = (t.task ==NULL ); + } }__set_current_state (TASK_RUNNING );
@@ -1113,14 +1122,14 @@ static int futex_wait_abstime(u32 __user/* If we were woken (and unqueued), we succeeded, whatever. */ if (!unqueue_me (&q))return 0 ; -if (time_left ==0 ) +if (rem)return -ETIMEDOUT ;/* * We expect signal_pending(current), but another thread may * have handled it for us already. */ -if (time_left ==MAX_SCHEDULE_TIMEOUT ) +if (!abs_time)return -ERESTARTSYS ;else {struct restart_block *restart;
@@ -1128,8 +1137,7 @@ static int futex_wait_abstime(u32 __user restart->fn = futex_wait_restart; restart->arg0 = (unsigned long )uaddr; restart->arg1 = (unsigned long )val; - restart->arg2 = (unsigned long )timed; - restart->arg3 = abs_time; + restart->arg2 = (unsigned long )abs_time;return -ERESTART_RESTARTBLOCK ; }
@@ -1141,21 +1149,15 @@ static int futex_wait_abstime(u32 __userreturn ret; } -static int futex_wait (u32 __user *uaddr,u32 val,unsigned long rel_time) -{ -int timed = (rel_time !=MAX_SCHEDULE_TIMEOUT ); -return futex_wait_abstime (uaddr, val, timed, jiffies+rel_time); -}static long futex_wait_restart (struct restart_block *restart) {u32 __user *uaddr = (u32 __user *)restart->arg0;u32 val = (u32 )restart->arg1; -int timed = (int )restart->arg2; -unsigned long abs_time = restart->arg3; +ktime_t *abs_time = (ktime_t *)restart->arg2; restart->fn = do_no_restart_syscall; -return (long )futex_wait_abstime (uaddr, val, timed, abs_time); +return (long )futex_wait (uaddr, val, abs_time); }
@@ -1165,8 +1167,8 @@ static long futex_wait_restart(struct re* if there are waiters then it will block, it does PI, etc. (Due to * races the kernel might see a 0 value of the futex too.) */ -static int futex_lock_pi (u32 __user *uaddr,int detect,unsigned long sec, -long nsec,int trylock) +static int futex_lock_pi (u32 __user *uaddr,int detect,ktime_t *time, +int trylock) {struct hrtimer_sleeper timeout, *to =NULL ;struct task_struct *curr = current;
@@ -1178,11 +1180,11 @@ static int futex_lock_pi(u32 __user *uadif (refill_pi_state_cache ())return -ENOMEM ; -if (sec !=MAX_SCHEDULE_TIMEOUT ) { +if (time) { to = &timeout;hrtimer_init (&to->timer,CLOCK_REALTIME ,HRTIMER_MODE_ABS );hrtimer_init_sleeper (to, current); - to->timer.expires =ktime_set (sec, nsec); + to->timer.expires = *time; } q.pi_state =NULL ;
@@ -1818,7 +1820,7 @@ void exit_robust_list(struct task_struct } } -long do_futex (u32 __user *uaddr,int op,u32 val,unsigned long timeout, +long do_futex (u32 __user *uaddr,int op,u32 val,ktime_t *timeout,u32 __user *uaddr2,u32 val2,u32 val3) {int ret;
@@ -1844,13 +1846,13 @@ long do_futex(u32 __user *uaddr, int op, ret =futex_wake_op (uaddr, uaddr2, val, val2, val3);break ;case FUTEX_LOCK_PI : - ret =futex_lock_pi (uaddr, val, timeout, val2,0 ); + ret =futex_lock_pi (uaddr, val, timeout,0 );break ;case FUTEX_UNLOCK_PI : ret =futex_unlock_pi (uaddr);break ;case FUTEX_TRYLOCK_PI : - ret =futex_lock_pi (uaddr,0 , timeout, val2,1 ); + ret =futex_lock_pi (uaddr,0 , timeout,1 );break ;default : ret = -ENOSYS ;
@@ -1863,21 +1865,18 @@ asmlinkage long sys_futex(u32 __user *ua struct timespec __user *utime, u32 __user *uaddr2, u32 val3) { - struct timespec t; -unsigned long timeout =MAX_SCHEDULE_TIMEOUT ; + struct timespec ts; +ktime_t t, *tp =NULL ;u32 val2 =0 ;if (utime && (op ==FUTEX_WAIT || op ==FUTEX_LOCK_PI )) { -if (copy_from_user (&t, utime,sizeof (t)) !=0 ) +if (copy_from_user (&ts, utime,sizeof (ts)) !=0 )return -EFAULT ; -if (!timespec_valid (&t)) +if (!timespec_valid (&ts))return -EINVAL ;if (op ==FUTEX_WAIT ) - timeout =timespec_to_jiffies (&t) +1 ; -else { - timeout = t.tv_sec; - val2 = t.tv_nsec; - } + t =ktime_add (ktime_get (),timespec_to_ktime (ts)); + tp = &t; }/* * requeue parameter in 'utime' if op == FUTEX_REQUEUE.
@@ -1885,7 +1884,7 @@ asmlinkage long sys_futex(u32 __user *uaif (op ==FUTEX_REQUEUE || op ==FUTEX_CMP_REQUEUE ) val2 = (u32 ) (unsigned long ) utime; -return do_futex (uaddr, op, val, timeout, uaddr2, val2, val3); +return do_futex (uaddr, op, val, tp, uaddr2, val2, val3); } static int futexfs_get_sb(struct file_system_type *fs_type,
include/linux/futex.h +2 -1
@@ -1,6 +1,7 @@#ifndef _LINUX_FUTEX_H#define _LINUX_FUTEX_H +#include <linux/ktime.h> #include <linux/sched.h> /* Second argument to futex syscall */
@@ -94,7 +95,7 @@ struct robust_list_head {#define ROBUST_LIST_LIMIT 2048#ifdef __KERNEL__ -long do_futex (u32 __user *uaddr,int op,u32 val,unsigned long timeout, +long do_futex (u32 __user *uaddr,int op,u32 val,ktime_t *timeout,u32 __user *uaddr2,u32 val2,u32 val3); extern int
kernel/futex_compat.c +7 -10
@@ -141,24 +141,21 @@ asmlinkage long compat_sys_futex(u32 __u struct compat_timespec __user *utime, u32 __user *uaddr2, u32 val3) { - struct timespec t; -unsigned long timeout =MAX_SCHEDULE_TIMEOUT ; + struct timespec ts; +ktime_t t, *tp =NULL ;int val2 =0 ;if (utime && (op ==FUTEX_WAIT || op ==FUTEX_LOCK_PI )) { -if (get_compat_timespec (&t, utime)) +if (get_compat_timespec (&ts, utime))return -EFAULT ; -if (!timespec_valid (&t)) +if (!timespec_valid (&ts))return -EINVAL ;if (op ==FUTEX_WAIT ) - timeout =timespec_to_jiffies (&t) +1 ; -else { - timeout = t.tv_sec; - val2 = t.tv_nsec; - } + t =ktime_add (ktime_get (),timespec_to_ktime (ts)); + tp = &t; }if (op ==FUTEX_REQUEUE || op ==FUTEX_CMP_REQUEUE ) val2 = (int ) (unsigned long ) utime; -return do_futex (uaddr, op, val, timeout, uaddr2, val2, val3); +return do_futex (uaddr, op, val, tp, uaddr2, val2, val3); }
Signature · 1 line
Pierre Peiffer
Re: [PATCH 2.6.21-rc4-mm1 2/4] Make futex_wait() use an hrtimer for timeout
Quoted 13 lines · On Wed, 21 Mar 2007 10:54:34 +0100 [email protected] wrote:
This patch modifies
futex_wait()to use an hrtimer +schedule()in place ofschedule_timeout().
schedule_timeout()is tick based, therefore the timeout granularity is
the tick (1 ms, 4 ms or 10 ms depending on HZ). By using a high resolution timer for timeout wakeup, we can attain a much finer timeout granularity (in the microsecond range). This parallels what is already done forfutex_lock_pi().The timeout passed to the syscall is no longer converted to jiffies
and is therefore passed todo_futex()andfutex_wait()as an absolutektime_ttherefore keeping nanosecond resolution.
Quoted 6 lines
Also this removes the need to pass the nanoseconds timeout part to
futex_lock_pi()in val2.In
futex_wait(), if there is no timeout then a regularschedule()is
performed. Otherwise, an hrtimer is fired beforeschedule()is called.
Problem.
include/linux/futex.h line 6
Quoted 9 lines
include/linux/futex.h +1
-0@@ -1,6 +1,7 @@#ifndef _LINUX_FUTEX_H#define _LINUX_FUTEX_H +#include <linux/ktime.h> #include <linux/sched.h>
For a start, please print out a copy of Documentation/SubmitChecklist and tape it to your monitor. It's really good.
`make headers_check' fails with
/usr/src/devel/usr/include/linux/futex.h requires linux/ktime.h, which does not exist in exported headers
This fixes it:
include/linux/Kbuild renamed from include/linux/Kbuild~make-futex_wait-use-an-hrtimer-for-timeout-fix +3 -0
@@ -40,6 +40,7 @@ header-y += baycom.h header-y += bfs_fs.h header-y += blkpg.h header-y += bpqether.h +header-y += calc64.h header-y += cdk.h header-y += chio.h header-y += coda_psdev.h
@@ -99,7 +100,9 @@ header-y += isdn_divertif.h header-y += iso_fs.h header-y += ixjuser.h header-y += jffs2.h +header-y += jiffies.h header-y += keyctl.h +header-y += ktime.h header-y += kvm.h header-y += limits.h header-y += lock_dlm_plock.h
include/asm-i386/Kbuild renamed from include/asm-i386/Kbuild~make-futex_wait-use-an-hrtimer-for-timeout-fix +1 -0
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm header-y += boot.h header-y += debugreg.h +header-y += div64.h header-y += ldt.h header-y += ptrace-abi.h header-y += ucontext.h
_
But only for i386, and no way do we want to export all those headers.
Now. What blithering idiot carefully went and made ktime_t a typedef so we cannot forward declare it? Sigh. We tell 'em, but they don't listen.
This fixes ktime:
include/linux/ktime.h renamed from include/linux/ktime.h~declare-struct-ktime +4 -2
@@ -43,7 +43,7 @@* plain scalar nanosecond based representation can be selected by the * config switch CONFIG_KTIME_SCALAR. */ -typedef union { +union ktime { s64 tv64; #if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR) struct {
@@ -54,7 +54,9 @@ typedef union { # endif } tv;#endif -} ktime_t; +}; + +typedef union ktime ktime_t ;/* Kill this */ #define KTIME_MAX ((s64)~((u64)1 << 63))#if (BITS_PER_LONG ==64 )
_
And this fixes your patch:
include/linux/futex.h renamed from include/linux/futex.h~make-futex_wait-use-an-hrtimer-for-timeout-fix +3 -2
@@ -1,9 +1,10 @@#ifndef _LINUX_FUTEX_H#define _LINUX_FUTEX_H -#include <linux/ktime.h> #include <linux/sched.h> +union ktime ; +/* Second argument to futex syscall */
@@ -95,7 +96,7 @@ struct robust_list_head {#define ROBUST_LIST_LIMIT 2048#ifdef __KERNEL__ -long do_futex (u32 __user *uaddr,int op,u32 val,ktime_t *timeout, +long do_futex (u32 __user *uaddr,int op,u32 val,union ktime *timeout,u32 __user *uaddr2,u32 val2,u32 val3); extern int
_
And now someone needs to go all over the kernel and do a s/ktime_t/union ktime/g. Again. How often must we do this?
PATCH 3/4 futex_requeue_pi optimization
In reply to [email protected]This patch provides the futex_requeue_pi functionality, which allows some threads waiting on a normal futex to be requeued on the wait-queue of a PI-futex.
This provides an optimization, already used for (normal) futexes, to be used with the PI-futexes.
This optimization is currently used by the glibc in pthread_broadcast, when using "normal" mutexes. With futex_requeue_pi, it can be used with PRIO_INHERIT mutexes too.
--- include/linux/futex.h | 9 kernel/futex.c | 541 +++++++++++++++++++++++++++++++++++++++++++----- kernel/futex_compat.c | 3 kernel/rtmutex.c | 41 --- kernel/rtmutex_common.h | 34 +++ 5 files changed, 540 insertions(+), 88 deletions(-)
include/linux/futex.h +8 -1
@@ -16,6 +16,7 @@#define FUTEX_LOCK_PI 6#define FUTEX_UNLOCK_PI 7#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_CMP_REQUEUE_PI 9/* * Support for robust futexes: the kernel cleans up held futexes at
@@ -84,9 +85,14 @@ struct robust_list_head {#define FUTEX_OWNER_DIED 0x40000000/* +* Some processes have been requeued on this PI-futex +*/ +#define FUTEX_WAITER_REQUEUED 0x20000000 + +/* * The rest of the robust-futex field is for the TID: */ -#define FUTEX_TID_MASK 0x3fffffff +#define FUTEX_TID_MASK 0x0fffffff/* * This limit protects against a deliberately circular list.
@@ -110,6 +116,7 @@ handle_futex_death(u32 __user *uaddr, st* We set bit 0 to indicate if it's an inode-based key. */ union futex_key { +u32 __user *uaddr;struct {unsigned long pgoff;struct inode *inode;
kernel/futex.c +487 -54
712 lines not on this page · raw message
kernel/rtmutex.c +9 -32
71 lines not on this page · raw message
kernel/rtmutex_common.h +34 -0
@@ -113,6 +113,29 @@ static inline unsigned long rt_mutex_own }/* +* We can speed up the acquire/release, if the architecture +* supports cmpxchg and if there's no debugging state to be set up +*/ +#if defined(__HAVE_ARCH_CMPXCHG) && !defined(CONFIG_DEBUG_RT_MUTEXES ) +# define rt_mutex_cmpxchg (l,c,n) (cmpxchg(&l->owner, c, n) == c) +static inline void mark_rt_mutex_waiters (struct rt_mutex *lock) +{ +unsigned long owner, *p = (unsigned long *) &lock->owner; + +do { + owner = *p; + }while (cmpxchg (p, owner, owner |RT_MUTEX_HAS_WAITERS ) != owner); +} +#else +# define rt_mutex_cmpxchg (l,c,n) (0) +static inline void mark_rt_mutex_waiters (struct rt_mutex *lock) +{ + lock->owner = (struct task_struct *) + ((unsigned long )lock->owner |RT_MUTEX_HAS_WAITERS ); +} +#endif + +/* * PI-futex support (proxy locking functions, etc.): */ extern struct task_struct *rt_mutex_next_owner (struct rt_mutex *lock);
@@ -120,4 +143,15 @@ extern void rt_mutex_init_proxy_locked(s struct task_struct *proxy_owner);extern void rt_mutex_proxy_unlock (struct rt_mutex *lock,struct task_struct *proxy_owner); + +extern void rt_mutex_set_owner (struct rt_mutex *lock,struct task_struct *owner, +unsigned long mask); +extern void __rt_mutex_adjust_prio (struct task_struct *task); +extern int rt_mutex_adjust_prio_chain (struct task_struct *task, +int deadlock_detect, +struct rt_mutex *orig_lock, +struct rt_mutex_waiter *orig_waiter, +struct task_struct *top_task); +extern void remove_waiter (struct rt_mutex *lock, +struct rt_mutex_waiter *waiter);#endif
kernel/futex_compat.c +2 -1
@@ -154,7 +154,8 @@ asmlinkage long compat_sys_futex(u32 __u t =ktime_add (ktime_get (),timespec_to_ktime (ts)); tp = &t; } -if (op ==FUTEX_REQUEUE || op ==FUTEX_CMP_REQUEUE ) +if (op ==FUTEX_REQUEUE || op ==FUTEX_CMP_REQUEUE + || op ==FUTEX_CMP_REQUEUE_PI ) val2 = (int ) (unsigned long ) utime;return do_futex (uaddr, op, val, tp, uaddr2, val2, val3);
Signature · 1 line
Pierre Peiffer
PATCH 4/4 sys_futex64 : allows 64bit futexes
In reply to [email protected]This last patch is an adaptation of the sys_futex64 syscall provided in -rt patch (originally written by Ingo Molnar). It allows the use of 64-bit futex.
I have re-worked most of the code to avoid the duplication of the code.
It does not provide the functionality for all architectures (only for x64 for now).
--- include/asm-x86_64/futex.h | 113 ++++++++++++++++++ include/asm-x86_64/unistd.h | 4 include/linux/futex.h | 9 - include/linux/syscalls.h | 3 kernel/futex.c | 264 +++++++++++++++++++++++++++++++------------- kernel/futex_compat.c | 3 kernel/sys_ni.c | 1 7 files changed, 313 insertions(+), 84 deletions(-)
include/asm-x86_64/futex.h +113 -0
@@ -41,6 +41,39 @@ "=&r" (tem) \ : "r" (oparg), "i" (-EFAULT), "m" (*uaddr), "1" (0)) +#define __futex_atomic_op1_64 (insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile ( \ +"1: " insn "\n" \ +"2: .section .fixup,\"ax\"\n\ +3: movq %3, %1\n\ + jmp 2b\n\ + .previous\n\ + .section __ex_table,\"a\"\n\ + .align 8\n\ + .quad 1b,3b\n\ + .previous" \ + : "=r" (oldval), "=r" (ret), "=m" (*uaddr) \ + : "i" (-EFAULT), "m" (*uaddr), "0" (oparg), "1" (0)) + +#define __futex_atomic_op2_64 (insn, ret, oldval, uaddr, oparg) \ + __asm__ __volatile ( \ +"1: movq %2, %0\n\ + movq %0, %3\n" \ + insn "\n" \ +"2: " LOCK_PREFIX "cmpxchgq %3, %2\n\ + jnz 1b\n\ +3: .section .fixup,\"ax\"\n\ +4: movq %5, %1\n\ + jmp 3b\n\ + .previous\n\ + .section __ex_table,\"a\"\n\ + .align 8\n\ + .quad 1b,4b,2b,4b\n\ + .previous" \ + : "=&a" (oldval), "=&r" (ret), "=m" (*uaddr), \ + "=&r" (tem) \ + : "r" (oparg), "i" (-EFAULT), "m" (*uaddr), "1" (0)) +static inline int futex_atomic_op_inuser (int encoded_op,int __user *uaddr) {
@@ -95,6 +128,60 @@ futex_atomic_op_inuser (int encoded_op, }static inline int +futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) +{ +int op = (encoded_op >>28 ) &7 ; +int cmp = (encoded_op >>24 ) &15 ; +u64 oparg = (encoded_op <<8 ) >>20 ; +u64 cmparg = (encoded_op <<20 ) >>20 ; +u64 oldval =0 , ret, tem; + +if (encoded_op & (FUTEX_OP_OPARG_SHIFT <<28 )) + oparg =1 << oparg; + +if (!access_ok (VERIFY_WRITE , uaddr,sizeof (u64))) +return -EFAULT ; + +inc_preempt_count (); + +switch (op) { +case FUTEX_OP_SET : +__futex_atomic_op1_64 ("xchgq %0, %2" , ret, oldval, uaddr, oparg); +break ; +case FUTEX_OP_ADD : +__futex_atomic_op1_64 (LOCK_PREFIX "xaddq %0, %2" , ret, oldval, + uaddr, oparg); +break ; +case FUTEX_OP_OR : +__futex_atomic_op2_64 ("orq %4, %3" , ret, oldval, uaddr, oparg); +break ; +case FUTEX_OP_ANDN : +__futex_atomic_op2_64 ("andq %4, %3" , ret, oldval, uaddr, ~oparg); +break ; +case FUTEX_OP_XOR : +__futex_atomic_op2_64 ("xorq %4, %3" , ret, oldval, uaddr, oparg); +break ; +default : + ret = -ENOSYS ; + } + +dec_preempt_count (); + +if (!ret) { +switch (cmp) { +case FUTEX_OP_CMP_EQ : ret = (oldval == cmparg);break ; +case FUTEX_OP_CMP_NE : ret = (oldval != cmparg);break ; +case FUTEX_OP_CMP_LT : ret = (oldval < cmparg);break ; +case FUTEX_OP_CMP_GE : ret = (oldval >= cmparg);break ; +case FUTEX_OP_CMP_LE : ret = (oldval <= cmparg);break ; +case FUTEX_OP_CMP_GT : ret = (oldval > cmparg);break ; +default : ret = -ENOSYS ; + } + } +return ret; +} + +static inline int futex_atomic_cmpxchg_inatomic (int __user *uaddr,int oldval,int newval) {if (!access_ok (VERIFY_WRITE , uaddr,sizeof (int )))
@@ -121,5 +208,31 @@ futex_atomic_cmpxchg_inatomic(int __userreturn oldval; } +static inline u64 +futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) +{ +if (!access_ok (VERIFY_WRITE , uaddr,sizeof (u64))) +return -EFAULT ; + + __asm__ __volatile__( +"1: " LOCK_PREFIX "cmpxchgq %3, %1 \n" + +"2: .section .fixup, \"ax\" \n" +"3: mov %2, %0 \n" +" jmp 2b \n" +" .previous \n" + +" .section __ex_table, \"a\" \n" +" .align 8 \n" +" .quad 1b,3b \n" +" .previous \n" + + :"=a" (oldval),"=m" (*uaddr) + :"i" (-EFAULT ),"r" (newval),"0" (oldval) + :"memory" + ); + +return oldval; +}#endif #endif
include/asm-x86_64/unistd.h +3 -1
@@ -619,8 +619,10 @@ __SYSCALL(__NR_sync_file_range, sys_sync __SYSCALL(__NR_vmsplice, sys_vmsplice)#define __NR_move_pages 279 __SYSCALL(__NR_move_pages, sys_move_pages) +#define __NR_futex64 280 +__SYSCALL(__NR_futex64, sys_futex64) -#define __NR_syscall_max __NR_move_pages +#define __NR_syscall_max __NR_futex64#ifndef __NO_STUBS#define __ARCH_WANT_OLD_READDIR
include/linux/syscalls.h +3 -0
@@ -178,6 +178,9 @@ asmlinkage long sys_set_tid_address(intasmlinkage long sys_futex (u32 __user *uaddr,int op,u32 val,struct timespec __user *utime,u32 __user *uaddr2,u32 val3); +asmlinkage long sys_futex64 (u64 __user *uaddr,int op,u64 val, +struct timespec __user *utime,u64 __user *uaddr2, +u64 val3);asmlinkage long sys_init_module (void __user *umod,unsigned long len,const char __user *uargs);
kernel/futex.c +186 -78
606 lines not on this page · raw message
kernel/sys_ni.c +1 -0
@@ -41,6 +41,7 @@ cond_syscall(sys_sendmsg);cond_syscall (sys_recvmsg);cond_syscall (sys_socketcall);cond_syscall (sys_futex); +cond_syscall (sys_futex64);cond_syscall (compat_sys_futex);cond_syscall (sys_set_robust_list);cond_syscall (compat_sys_set_robust_list);
include/linux/futex.h +5 -4
@@ -101,8 +101,9 @@ struct robust_list_head {#define ROBUST_LIST_LIMIT 2048#ifdef __KERNEL__ -long do_futex (u32 __user *uaddr,int op,u32 val,ktime_t *timeout, -u32 __user *uaddr2,u32 val2,u32 val3); +long do_futex (unsigned long __user *uaddr,int op,unsigned long val, +ktime_t *timeout,unsigned long __user *uaddr2, +unsigned long val2,unsigned long val3,int futex64);extern int handle_futex_death (u32 __user *uaddr,struct task_struct *curr,int pi);
@@ -116,7 +117,7 @@ handle_futex_death(u32 __user *uaddr, st* We set bit 0 to indicate if it's an inode-based key. */ union futex_key { -u32 __user *uaddr; +unsigned long __user *uaddr;struct {unsigned long pgoff;struct inode *inode;
@@ -133,7 +134,7 @@ union futex_key {int offset; } both; }; -int get_futex_key (u32 __user *uaddr,union futex_key *key); +int get_futex_key (void __user *uaddr,union futex_key *key);void get_futex_key_refs (union futex_key *key);void drop_futex_key_refs (union futex_key *key);
kernel/futex_compat.c +2 -1
@@ -158,5 +158,6 @@ asmlinkage long compat_sys_futex(u32 __u || op == FUTEX_CMP_REQUEUE_PI) val2 = (int ) (unsigned long ) utime; -return do_futex (uaddr, op, val, tp, uaddr2, val2, val3); +return do_futex ((unsigned long __user *)uaddr, op, val, tp, + (unsigned long __user *)uaddr2, val2, val3,0 ); }
Signature · 1 line
Pierre Peiffer
Re: [PATCH 2.6.21-rc4-mm1 4/4] sys_futex64 : allows 64bit futexes
Quoted 1 line · On Wed, 21 Mar 2007 10:54:36 +0100 [email protected] wrote:
It does not provide the functionality for all architectures (only for x64 for now).
Well that scuppers our chances of getting -mm kernels tested on ia64, s390 and sparc64. Which is a problem - people do test s390 and ia64 and so these patches impact the testing quality of everyone else's work.
Do we have a plan to fix this (promptly, please)?
kernel/built-in.o(.text+0x683a2): In function `futex_requeue_pi':
: undefined reference to `futex_atomic_cmpxchg_inatomic64'
Re: [PATCH 2.6.21-rc4-mm1 4/4] sys_futex64 : allows 64bit futexes
In reply to [email protected]Quoted 6 lines · On Wed, Mar 21, 2007 at 10:54:36AM +0100, [email protected] wrote:
This last patch is an adaptation of the
sys_futex64syscall provided in -rt patch (originally written by Ingo Molnar). It allows the use of 64-bit futex.I have re-worked most of the code to avoid the duplication of the code.
It does not provide the functionality for all architectures (only for x64 for now).
I don't think you should blindly add all operations to sys_futex64 without thinking what they really do.
E.g. FUTEX_{{,UN,TRY}LOCK,CMP_REQUEUE}_PI doesn't really make any sense for 64-bit futexes, the format of PI futexes is hardcoded in the kernel and is always 32-bit, see FUTEX_TID_MASK, FUTEX_WAITERS, FUTEX_OWNER_DIED definitions. exit_robust_list/handle_futex_death will handle 32-bit PI futexes anyway. Similarly, sys_futex64 shouldn't support the obsolete operations that are there solely for compatibility (e.g. FUTEX_REQUEUE or FUTEX_FD).
When you just -ENOSYS on the PI ops, there is no need to implement futex_atomic_cmpxchg_inatomic64.
FUTEX_WAKE_OP is questionable for 64-bit, IMHO it is better to just -ENOSYS on it and only if anyone ever finds actual uses for it, add it.
For 64-bit futexes the only needed operations are actually FUTEX_WAIT and perhaps FUTEX_CMP_REQUEUE, so I wonder if it isn't better to just add FUTEX_WAIT64 and FUTEX_CMP_REQUEUE64 ops to sys_futex instead of adding a new syscall.
But the FUTEX_{{,UN,TRY}LOCK,CMP_REQUEUE}_PI removal for 64-bit futexes is IMHO the most important part of my complain.
Jakub
PATCH 1/1 64bit-futex - provide new commands instead of new syscall
Hi,
Quoted 16 lines · Jakub Jelinek
I don't think you should blindly add all operations to
sys_futex64without thinking what they really do.
E.g. FUTEX_{{,UN,TRY}LOCK,CMP_REQUEUE}_PI doesn't really make any sense for 64-bit futexes, the format of PI futexes is hardcoded in the kernel and is always 32-bit, seeFUTEX_TID_MASK,FUTEX_WAITERS,FUTEX_OWNER_DIEDdefinitions. exit_robust_list/handle_futex_death will handle 32-bit PI futexes anyway. Similarly,sys_futex64shouldn't support the obsolete operations that are there solely for compatibility (e.g.FUTEX_REQUEUEorFUTEX_FD).When you just
-ENOSYSon the PI ops, there is no need to implementfutex_atomic_cmpxchg_inatomic64.
FUTEX_WAKE_OPis questionable for 64-bit, IMHO it is better to just-ENOSYSon it and only if anyone ever finds actual uses for it, add it.
Quoted 8 lines
For 64-bit futexes the only needed operations are actually
FUTEX_WAITand perhapsFUTEX_CMP_REQUEUE, so I wonder if it isn't better to just addFUTEX_WAIT64andFUTEX_CMP_REQUEUE64ops tosys_futexinstead of adding a new syscall.But the FUTEX_{{,UN,TRY}LOCK,CMP_REQUEUE}_PI removal for 64-bit futexes is IMHO the most important part of my complain.
Following this mail sent few weeks ago, here is a patch which should meet your requirements.
I've quickly done it on top of the latest -mm (2.6.21-rc6-mm2) and a little bit tested.
To be honest, as I'm not really aware of your exact needs and as I don't know the exact usage which will be done with 64bit futexes, I can't really maintain it. So I'll let you take/modify/adapt this patch following your needs.
Thanks,
Signature · 1 line
Pierre
--- include/asm-ia64/futex.h | 8 - include/asm-powerpc/futex.h | 6 - include/asm-s390/futex.h | 8 - include/asm-sparc64/futex.h | 8 - include/asm-um/futex.h | 9 - include/asm-x86_64/futex.h | 86 ------------------- include/asm-x86_64/unistd.h | 2 include/linux/futex.h | 8 + include/linux/syscalls.h | 3 kernel/futex.c | 199 +++++++++++++++++--------------------------- kernel/futex_compat.c | 2 kernel/sys_ni.c | 1 12 files changed, 93 insertions(+), 247 deletions(-)
include/asm-ia64/futex.h +1 -7
@@ -124,13 +124,7 @@ futex_atomic_cmpxchg_inatomic(int __userstatic inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; -} - -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; +return -ENOSYS ; }#endif /* _ASM_FUTEX_H */
include/asm-powerpc/futex.h +0 -6
@@ -119,11 +119,5 @@ futex_atomic_cmpxchg_inatomic64(u64 __usreturn 0 ; } -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; -} -#endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_FUTEX_H */
include/asm-s390/futex.h +1 -7
@@ -51,13 +51,7 @@ static inline int futex_atomic_cmpxchg_istatic inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; -} - -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; +return -ENOSYS ; }#endif /* __KERNEL__ */
include/asm-sparc64/futex.h +1 -7
@@ -108,13 +108,7 @@ futex_atomic_cmpxchg_inatomic(int __userstatic inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; -} - -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; +return -ENOSYS ; }#endif /* !(_SPARC64_FUTEX_H) */
include/asm-um/futex.h +1 -8
@@ -6,14 +6,7 @@static inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; +return -ENOSYS ; } -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; -} - -#endif
include/asm-x86_64/futex.h +0 -86
98 lines not on this page · raw message
include/asm-x86_64/unistd.h +0 -2
@@ -619,8 +619,6 @@ __SYSCALL(__NR_sync_file_range, sys_sync __SYSCALL(__NR_vmsplice, sys_vmsplice)#define __NR_move_pages 279 __SYSCALL(__NR_move_pages, sys_move_pages) -#define __NR_futex64 280 -__SYSCALL(__NR_futex64, sys_futex64)#define __NR_signalfd 281 __SYSCALL(__NR_signalfd, sys_signalfd)#define __NR_timerfd 282
include/linux/futex.h +7 -1
@@ -19,6 +19,12 @@ union ktime;#define FUTEX_TRYLOCK_PI 8#define FUTEX_CMP_REQUEUE_PI 9 +#ifdef CONFIG_64BIT +#define FUTEX_64BIT 0x80000000 +#define FUTEX_WAIT64 FUTEX_WAIT|FUTEX_64BIT +#define FUTEX_CMP_REQUEUE64 FUTEX_CMP_REQUEUE|FUTEX_64BIT +#endif +/* * Support for robust futexes: the kernel cleans up held futexes at * thread exit time.
@@ -104,7 +110,7 @@ struct robust_list_head {#ifdef __KERNEL__long do_futex (unsigned long __user *uaddr,int op,unsigned long val,union ktime *timeout,unsigned long __user *uaddr2, -unsigned long val2,unsigned long val3,int futex64); +unsigned long val2,unsigned long val3);extern int handle_futex_death (u32 __user *uaddr,struct task_struct *curr,int pi);
include/linux/syscalls.h +0 -3
@@ -178,9 +178,6 @@ asmlinkage long sys_set_tid_address(intasmlinkage long sys_futex (u32 __user *uaddr,int op,u32 val,struct timespec __user *utime,u32 __user *uaddr2,u32 val3); -asmlinkage long sys_futex64 (u64 __user *uaddr,int op,u64 val, -struct timespec __user *utime,u64 __user *uaddr2, -u64 val3);asmlinkage long sys_init_module (void __user *umod,unsigned long len,const char __user *uargs);
kernel/futex.c +83 -118
442 lines not on this page · raw message
kernel/futex_compat.c +1 -1
@@ -161,5 +161,5 @@ asmlinkage long compat_sys_futex(u32 __u val2 = (int ) (unsigned long ) utime;return do_futex ((unsigned long __user *)uaddr, op, val, tp, - (unsigned long __user *)uaddr2, val2, val3,0 ); + (unsigned long __user *)uaddr2, val2, val3); }
kernel/sys_ni.c +0 -1
@@ -41,7 +41,6 @@ cond_syscall(sys_sendmsg);cond_syscall (sys_recvmsg);cond_syscall (sys_socketcall);cond_syscall (sys_futex); -cond_syscall (sys_futex64);cond_syscall (compat_sys_futex);cond_syscall (sys_set_robust_list);cond_syscall (compat_sys_set_robust_list);
Re: [PATCH -mm] 64bit-futex - provide new commands instead of new syscall
Quoted 2 lines · Pierre Peiffer
Following this mail sent few weeks ago, here is a patch which should meet your requirements. [...]
It looks mostly good. I wouldn't use the high bit to differentiate the 64-bit operations, though. Since we do not allow to apply it to all operations the only effect will be that the compiler has a harder time generating the code for the switch statement. If you use continuous values a simple jump table can be used and no conditionals. Smaller and faster.
PATCH 1/1 64bit-futex - provide new commands instead of new syscall
Quoted 8 lines · Ulrich Drepper
It looks mostly good. I wouldn't use the high bit to differentiate the 64-bit operations, though. Since we do not allow to apply it to all operations the only effect will be that the compiler has a harder time generating the code for the switch statement. If you use continuous values a simple jump table can be used and no conditionals. Smaller and faster.
Something like that may be...
Signature · 1 line
Pierre
--- include/asm-ia64/futex.h | 8 - include/asm-powerpc/futex.h | 6 - include/asm-s390/futex.h | 8 - include/asm-sparc64/futex.h | 8 - include/asm-um/futex.h | 9 - include/asm-x86_64/futex.h | 86 ------------------ include/asm-x86_64/unistd.h | 2 include/linux/futex.h | 6 + include/linux/syscalls.h | 3 kernel/futex.c | 203 ++++++++++++++++++-------------------------- kernel/futex_compat.c | 2 kernel/sys_ni.c | 1 12 files changed, 95 insertions(+), 247 deletions(-)
include/asm-ia64/futex.h +1 -7
@@ -124,13 +124,7 @@ futex_atomic_cmpxchg_inatomic(int __userstatic inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; -} - -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; +return -ENOSYS ; }#endif /* _ASM_FUTEX_H */
include/asm-powerpc/futex.h +0 -6
@@ -119,11 +119,5 @@ futex_atomic_cmpxchg_inatomic64(u64 __usreturn 0 ; } -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; -} -#endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_FUTEX_H */
include/asm-s390/futex.h +1 -7
@@ -51,13 +51,7 @@ static inline int futex_atomic_cmpxchg_istatic inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; -} - -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; +return -ENOSYS ; }#endif /* __KERNEL__ */
include/asm-sparc64/futex.h +1 -7
@@ -108,13 +108,7 @@ futex_atomic_cmpxchg_inatomic(int __userstatic inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; -} - -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; +return -ENOSYS ; }#endif /* !(_SPARC64_FUTEX_H) */
include/asm-um/futex.h +1 -8
@@ -6,14 +6,7 @@static inline u64 futex_atomic_cmpxchg_inatomic64 (u64 __user *uaddr,u64 oldval,u64 newval) { -return 0 ; +return -ENOSYS ; } -static inline int -futex_atomic_op_inuser64 (int encoded_op,u64 __user *uaddr) -{ -return 0 ; -} - -#endif
include/asm-x86_64/futex.h +0 -86
98 lines not on this page · raw message
include/asm-x86_64/unistd.h +0 -2
@@ -619,8 +619,6 @@ __SYSCALL(__NR_sync_file_range, sys_sync __SYSCALL(__NR_vmsplice, sys_vmsplice)#define __NR_move_pages 279 __SYSCALL(__NR_move_pages, sys_move_pages) -#define __NR_futex64 280 -__SYSCALL(__NR_futex64, sys_futex64)#define __NR_signalfd 281 __SYSCALL(__NR_signalfd, sys_signalfd)#define __NR_timerfd 282
include/linux/futex.h +5 -1
@@ -18,6 +18,10 @@ union ktime;#define FUTEX_UNLOCK_PI 7#define FUTEX_TRYLOCK_PI 8#define FUTEX_CMP_REQUEUE_PI 9 +#ifdef CONFIG_64BIT +#define FUTEX_WAIT64 10 +#define FUTEX_CMP_REQUEUE64 11 +#endif /* * Support for robust futexes: the kernel cleans up held futexes at
@@ -104,7 +108,7 @@ struct robust_list_head {#ifdef __KERNEL__long do_futex (unsigned long __user *uaddr,int op,unsigned long val,union ktime *timeout,unsigned long __user *uaddr2, -unsigned long val2,unsigned long val3,int futex64); +unsigned long val2,unsigned long val3);extern int handle_futex_death (u32 __user *uaddr,struct task_struct *curr,int pi);
include/linux/syscalls.h +0 -3
@@ -178,9 +178,6 @@ asmlinkage long sys_set_tid_address(intasmlinkage long sys_futex (u32 __user *uaddr,int op,u32 val,struct timespec __user *utime,u32 __user *uaddr2,u32 val3); -asmlinkage long sys_futex64 (u64 __user *uaddr,int op,u64 val, -struct timespec __user *utime,u64 __user *uaddr2, -u64 val3);asmlinkage long sys_init_module (void __user *umod,unsigned long len,const char __user *uargs);
kernel/futex.c +85 -118
447 lines not on this page · raw message
kernel/futex_compat.c +1 -1
@@ -161,5 +161,5 @@ asmlinkage long compat_sys_futex(u32 __u val2 = (int ) (unsigned long ) utime;return do_futex ((unsigned long __user *)uaddr, op, val, tp, - (unsigned long __user *)uaddr2, val2, val3,0 ); + (unsigned long __user *)uaddr2, val2, val3); }
kernel/sys_ni.c +0 -1
@@ -41,7 +41,6 @@ cond_syscall(sys_sendmsg);cond_syscall (sys_recvmsg);cond_syscall (sys_socketcall);cond_syscall (sys_futex); -cond_syscall (sys_futex64);cond_syscall (compat_sys_futex);cond_syscall (sys_set_robust_list);cond_syscall (compat_sys_set_robust_list);
Re: [PATCH -mm take2] 64bit-futex - provide new commands instead of new syscall
Quoted 1 line · Pierre Peiffer
Something like that may be...
Yep, looks goot to me.