Skip to contentSkip to conversation

futex and timeouts

DISCUSSION Hubertus Franke 6 participants 14 messages Mar 13, 2002 – Mar 18, 2002

lore
Share & tools
lore
#0 lore raw

Ulrich, it seems to me that absolute timeouts are the easiest to do.

(a) expand by additional parameter (0) means no timeout desired
(b) differentiate the schedule call in futex_down..

Question is whether the granularity of jiffies (10ms) is sufficiently small for timeouts.....

Rusty, take a look, wether there's something wrong with this and see whether you can integrate it or improve and integrate it.

/* Simplified from arch/ppc/kernel/semaphore.c: Paul M. is a genius. */ static int futex_down(struct list_head *head, struct page *page, int offset,
signed long timeout)

{
        int retval = 0;
        struct futex_q q;
 
        current->state = TASK_INTERRUPTIBLE;
        queue_me(head, &q, page, offset);
 
        while (!decrement_to_zero(page, offset)) {
                if (signal_pending(current)) {
                        retval = -EINTR;
                        break;
                }
	    if (!timeout) {
	        schedule();
                    current->state = TASK_INTERRUPTIBLE;	
	        continue;
                }
	    delay = schedule_timeout(timeout);
	    if (delay == 0)  {
		retval = -EAGAIN;
		break;
	    }
	    current->state = TASK_INTERRUPTIBLE;
	    timeout -= delay;
        }
        current->state = TASK_RUNNING;
        unqueue_me(&q);
        /* If we were signalled, we might have just been woken: we
           must wake another one.  Otherwise we need to wake someone
           else (if they are waiting) so they drop the count below 0,
           and when we "up" in userspace, we know there is a
           waiter. */
        wake_one_waiter(head, page, offset);
        return retval;
}
Signature · 1 line
-- Hubertus Franke  ([email protected])
#1 lore raw
Quoted 1 line · Hubertus Franke

Ulrich, it seems to me that absolute timeouts are the easiest to do.

Does it work with settimeofday()?

Quoted 2 lines

Question is whether the granularity of jiffies (10ms) is sufficiently small for timeouts.....

Hopefully there will be support for high-resolution clocks and timers sometime soon. I don't know how to prepare new interfaces for this. I guess there will be a whole bunch of interface changes/additions so you could ignore the problem for now.

Signature · 3 lines
---------------.                          ,-.   1325 Chesapeake Terrace
Ulrich Drepper  \    ,-------------------'   \  Sunnyvale, CA 94089 USA
Red Hat          `--' drepper at redhat.com   `------------------------
#2 lore raw
In reply to Hubertus Franke

In message <[email protected]> you write:

Quoted 8 lines

Ulrich, it seems to me that absolute timeouts are the easiest to do.

(a) expand by additional parameter (0) means no timeout desired
(b) differentiate the schedule call in futex_down..

Question is whether the granularity of jiffies (10ms) is sufficiently small for timeouts.....

1) You must not export jiffies to userspace.

2) They are not a time, they are a counter, and they do wrap.

3) This does not handle the settimeofday case: you need to check in userspace for that anyway.

So, since you need to check if you're trying to sleep for longer than (say) 49 days, AND you need to check if you are after the given abstime in userspace anyway (settimeofday backwards), you might as well convert to relative in userspace.

Sorry,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

#3 lore raw
Quoted 16 lines · Rusty Russell

In message <[email protected]> you write:

Quoted 7 lines

Ulrich, it seems to me that absolute timeouts are the easiest to do.

(a) expand by additional parameter (0) means no timeout desired
(b) differentiate the schedule call in futex_down..

Question is whether the granularity of jiffies (10ms) is sufficiently small for timeouts.....

1) You must not export jiffies to userspace.

2) They are not a time, they are a counter, and they do wrap.

3) This does not handle the settimeofday case: you need to check in userspace for that anyway.

Quoted 7 lines

So, since you need to check if you're trying to sleep for longer than (say) 49 days, AND you need to check if you are after the given abstime in userspace anyway (settimeofday backwards), you might as well convert to relative in userspace.

Sorry,
Rusty.

3) I think one of us is misunderstanding (its probably me)

What I was proposing was a relative wall clock time, vs application virtual time.

interface would be to always specify in futex how long to wait (relative) and not until when to wait (absolute).
What I propose is not to export jiffies (ofcourse not), but either usecs or msecs and whether one should state what the minimum wait time is. Right now we know it can't be less then 10ms (x86) unless we busywait and above that the granularity will be in 10ms increments.

So from the previous post of code example, one has to add the conversion from timeout to timeout_jiffies.
Also we need to determine the best API for this. Somebody (Rusty ?) suggest to pass a pointer to (struct timeval) vs a single counter. Only disadvantage is an additional copy_from_user, but it gives much bigger timeouts.

I think its a good idea to add it.

Signature · 1 line
-- Hubertus Franke  ([email protected])
#4 lore raw

In message <[email protected]> you write:

Quoted 7 lines

3) I think one of us is misunderstanding (its probably me)

What I was proposing was a relative wall clock time, vs application virtual time.

interface would be to always specify in futex how long to wait (relative) and not until when to wait (absolute).

Yep, sorry, my mistake. I suggest make it a relative "struct timespec *" (more futureproof that timeval). It would make sense to split the interface into futex_down and futex_up syuscalls, since futex_up doesn't need a timeout arg, but I haven't for the moment.

(Untested) patch below,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

kernel/futex.c +20 -6
diff -urN -I \$.*\$ --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal linux-2.5.7-pre1/kernel/futex.c working-2.5.7-pre1-futex-timeout/kernel/futex.c
@@ -32,6 +32,7 @@
 #include <linux/fs.h>
 #include <linux/futex.h>
 #include <linux/highmem.h>
+#include <linux/time.h>
 #include <asm/atomic.h>
 
 /* These mutexes are a very simple counter: the winner is the one who
@@ -146,10 +147,19 @@
 }
 
 /* Simplified from arch/ppc/kernel/semaphore.c: Paul M. is a genius. */
-static int futex_down(struct list_head *head, struct page *page, int offset)
+static int futex_down(struct list_head *head, struct page *page, int offset,
+		      struct timespec *utime)
 {
 	int retval = 0;
 	struct futex_q q;
+	unsigned long time = MAX_SCHEDULE_TIMEOUT;
+
+	if (utime) {
+		struct timespec t;
+		if (copy_from_user(&t, utime, sizeof(t)) != 0)
+			return -EFAULT;
+		time = timespec_to_jiffies(&t) + 1;
+	}
 
 	current->state = TASK_INTERRUPTIBLE;
 	queue_me(head, &q, page, offset);
@@ -159,13 +169,17 @@
 			retval = -EINTR;
 			break;
 		}
-		schedule();
+		time = schedule_timeout(time);
+		if (time == 0) {
+			retval = -ETIMEDOUT;
+			break;
+		}
 		current->state = TASK_INTERRUPTIBLE;
 	}
 	current->state = TASK_RUNNING;
 	unqueue_me(&q);
-	/* If we were signalled, we might have just been woken: we
-	   must wake another one.  Otherwise we need to wake someone
+	/* If we were signalled, or timed out, we might have just been woken:
+	   we must wake another one.  Otherwise we need to wake someone
 	   else (if they are waiting) so they drop the count below 0,
 	   and when we "up" in userspace, we know there is a
 	   waiter. */
@@ -185,7 +199,7 @@
 	return 0;
 }
 
-asmlinkage int sys_futex(void *uaddr, int op)
+asmlinkage int sys_futex_down(void *uaddr, int op, struct timespec *utime)
 {
 	int ret;
 	unsigned long pos_in_page;
@@ -210,7 +224,7 @@
 		ret = futex_up(head, page, pos_in_page);
 		break;
 	case FUTEX_DOWN:
-		ret = futex_down(head, page, pos_in_page);
+		ret = futex_down(head, page, pos_in_page, utime);
 		break;
 	/* Add other lock types here... */
 	default:
#5 lore raw
In reply to Hubertus Franke
Quoted 4 lines · Rusty Russell

Yep, sorry, my mistake. I suggest make it a relative "struct timespec *" (more futureproof that timeval). It would make sense to split the interface into futex_down and futex_up syuscalls, since futex_up doesn't need a timeout arg, but I haven't for the moment.

Why waste a syscall? The user is going to be using a library
wrapper. They don't have to know that futex_up() calls sys_futex(futex, FUTEX_UP, NULL);

Joel

Signature · 6 lines
Life's Little Instruction Book #182

	"Be romantic."

			http://www.jlbec.org/
			[email protected]
#6 lore raw

In message <[email protected]> you write:

Quoted 9 lines · Rusty Russell
Quoted 4 lines

Yep, sorry, my mistake. I suggest make it a relative "struct timespec *" (more futureproof that timeval). It would make sense to split the interface into futex_down and futex_up syuscalls, since futex_up doesn't need a timeout arg, but I haven't for the moment.

Why waste a syscall? The user is going to be using a library
wrapper. They don't have to know that futex_up() calls sys_futex(futex, FUTEX_UP, NULL);

My bad. There was a mistake in the patch (ie. I didn't actually do this).

OTOH, shades of fcntl! Syscalls are not "wasted": one for every fundamental operation makes *sense*. If I were doing it with timeouts from scratch, I'd definitely have done two syscalls. As it is, the "op" arg gives us a chance for more overloading in future.

Hope that clarifies,
Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

#7 lore raw
In reply to Hubertus Franke
Followup to:  <[email protected]>
By author:    Joel Becker <[email protected]>
In newsgroup: linux.dev.kernel
Quoted 11 lines · Rusty Russell
Quoted 4 lines

Yep, sorry, my mistake. I suggest make it a relative "struct timespec *" (more futureproof that timeval). It would make sense to split the interface into futex_down and futex_up syuscalls, since futex_up doesn't need a timeout arg, but I haven't for the moment.

Why waste a syscall? The user is going to be using a library
wrapper. They don't have to know that futex_up() calls sys_futex(futex, FUTEX_UP, NULL);

Syscalls are (by and large) cheap. Extra dispatches, however, hurt.

-hpa

Signature · 3 lines
<[email protected]> at work, <[email protected]> in private!
"Unix gives you enough rope to shoot yourself in the foot."
http://www.zytor.com/~hpa/puzzle.txt	<[email protected]>
#8 lore raw
In reply to Hubertus Franke
Quoted 11 lines · Joel Becker
Quoted 4 lines · Rusty Russell

Yep, sorry, my mistake. I suggest make it a relative "struct timespec *" (more futureproof that timeval). It would make sense to split the interface into futex_down and futex_up syuscalls, since futex_up doesn't need a timeout arg, but I haven't for the moment.

Why waste a syscall? The user is going to be using a library
wrapper. They don't have to know that futex_up() calls sys_futex(futex, FUTEX_UP, NULL);

Joel

I agree with that, only for the reason that we are getting scarce on syscall nubmers. Is 256-delta the max ?
On the other hand, it requires to always push 2 more arguments (operand and useless parameter).

One thing to consider is that many don't want to use libraries. They want to inline, which would result only in a few instruction.

What I would like to see is an interface that lets me pass optional parameters to the syscall interface, so I can call with different number of parameters.

Signature · 1 line
-- Hubertus Franke  ([email protected])
#9 lore raw
In reply to Hubertus Franke
Quoted 6 lines · Hubertus Franke
Quoted 3 lines

Why waste a syscall? The user is going to be using a library
wrapper. They don't have to know that futex_up() calls sys_futex(futex, FUTEX_UP, NULL);

I agree with that, only for the reason that we are getting scarce on syscall nubmers. Is 256-delta the max ?

This was my impression, and why I called it "wasting" a syscall.
On architectures where syscall numbers or handles are unlimited, of course there is no reason to keep it to one syscall.

Quoted 2 lines

One thing to consider is that many don't want to use libraries. They want to inline, which would result only in a few instruction.

Inlined you only take the penalty from the argument pushes. You
still have to go through the motions of checking whether you can get/release the lock in userspace.

Quoted 3 lines

What I would like to see is an interface that lets me pass optional parameters to the syscall interface, so I can call with different number of parameters.

Is this to lock multiple futexes "atomically"? If we are
looking for a fast path stack-wise, this seems extra work.

Joel

Signature · 5 lines
"Friends may come and go, but enemies accumulate." 
        - Thomas Jones

			http://www.jlbec.org/
			[email protected]
#10 lore raw
In reply to Hubertus Franke
Quoted 19 lines · Joel Becker
Quoted 6 lines · Hubertus Franke
Quoted 3 lines

Why waste a syscall? The user is going to be using a library
wrapper. They don't have to know that futex_up() calls sys_futex(futex, FUTEX_UP, NULL);

I agree with that, only for the reason that we are getting scarce on syscall nubmers. Is 256-delta the max ?

This was my impression, and why I called it "wasting" a syscall.
On architectures where syscall numbers or handles are unlimited, of course there is no reason to keep it to one syscall.

Quoted 2 lines

One thing to consider is that many don't want to use libraries. They want to inline, which would result only in a few instruction.

Inlined you only take the penalty from the argument pushes. You
still have to go through the motions of checking whether you can get/release the lock in userspace.

Quoted 8 lines
Quoted 3 lines

What I would like to see is an interface that lets me pass optional parameters to the syscall interface, so I can call with different number of parameters.

Is this to lock multiple futexes "atomically"? If we are
looking for a fast path stack-wise, this seems extra work.

Joel

No, take for example...

syscall3(int,futex,int,op, struct futex*, futex, int opt_arg);

I will be always forced by the compiler (-Wall) to supply 3 arguments even as in the case of "no time out desired" I have to push a 3rd meaningless optional argument on the stack.

Signature · 1 line
-- Hubertus Franke  ([email protected])
#11 lore raw
In reply to Hubertus Franke
Quoted 10 lines · Hubertus Franke
Quoted 6 lines
Quoted 3 lines

What I would like to see is an interface that lets me pass optional parameters to the syscall interface, so I can call with different number of parameters.

Is this to lock multiple futexes "atomically"? If we are
looking for a fast path stack-wise, this seems extra work.

No, take for example...

syscall3(int,futex,int,op, struct futex*, futex, int opt_arg);

Oh, I totally misparsed your statement. I thought you meant you
wanted a vararg sys_futex(), not a smarter _syscall() :-)

Joel

Signature · 6 lines
Life's Little Instruction Book #347

	"Never waste the oppourtunity to tell someone you love them."

			http://www.jlbec.org/
			[email protected]
#12 lore raw
In reply to Hubertus Franke
Quoted 6 lines · Joel Becker
Quoted 4 lines · Hubertus Franke
Quoted 4 lines
Quoted 3 lines

What I would like to see is an interface that lets me pass optional parameters to the syscall interface, so I can call with different number of parameters.

Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

Is this to lock multiple futexes "atomically"? If we are
looking for a fast path stack-wise, this seems extra work.

No, take for example...

syscall3(int,futex,int,op, struct futex*, futex, int opt_arg);

I don't think there is anything "broken" in defining more than one syscall stub to the same system call, each with a different parameter count (or completely different arguments). The call code will need to be able to figure it out, but there is nothing in the way as far as doing it.

-g

Quoted 13 lines

--

Life's Little Instruction Book #347

"Never waste the oppourtunity to tell someone you love them."

http://www.jlbec.org/
[email protected]

_______________________________________________
Lse-tech mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/lse-tech

Signature · 3 lines
George           [email protected]
High-res-timers: http://sourceforge.net/projects/high-res-timers/
Real time sched: http://sourceforge.net/projects/rtsched/
#13 lore raw
In reply to Hubertus Franke
Quoted 13 lines · george anzinger
Quoted 11 lines · Joel Becker
Quoted 10 lines · Hubertus Franke
Quoted 6 lines
Quoted 3 lines

What I would like to see is an interface that lets me pass optional parameters to the syscall interface, so I can call with different number of parameters.

Is this to lock multiple futexes "atomically"? If we are
looking for a fast path stack-wise, this seems extra work.

No, take for example...

syscall3(int,futex,int,op, struct futex*, futex, int opt_arg);

Quoted 8 lines

I don't think there is anything "broken" in defining more than one syscall stub to the same system call, each with a different parameter count (or completely different arguments). The call code will need to be able to figure it out, but there is nothing in the way as far as doing it.

-g

Ofcourse, no difficulties here, but no convenient way either, as the __NR_futex is automatically used.

Signature · 1 line
-- Hubertus Franke  ([email protected])