(Message inbox:2033)
From Linus.Torvalds@cs.Helsinki.FI Fri Jul 28 02:44:00 1995
Received: from keos.cs.Helsinki.FI by postbox.acs.ohio-state.edu (8.6.9/5.901231)
	id CAA25727; Fri, 28 Jul 1995 02:43:58 -0400
Received: (torvalds@localhost) by keos.cs.Helsinki.FI (8.6.10/H46) id JAA03124; Fri, 28 Jul 1995 09:43:48 +0300
Date: Fri, 28 Jul 1995 09:43:48 +0300
From: Linus Torvalds <Linus.Torvalds@cs.Helsinki.FI>
Message-Id: <199507280643.JAA03124@keos.cs.Helsinki.FI>
In-Reply-To: Bob Manson's message as of Jul 27, 22:48
X-Mailer: Mail User's Shell (7.2.0 10/31/90)
To: manson@magnus.acs.ohio-state.edu, davidm@cs.arizona.edu
Subject: Re: read() bug

Bob Manson: "Re: read() bug" (Jul 27, 22:48):
> 
> Ok, let's try it again...
> 
> I "fixed" the problem by changing line 225 in fs/select.c from
> 	timeout = ~0UL;
> to
> 	timeout = 0x7fffffff;

Yup.  Once you told me "select returns 0 even with no timeout", the
problem was obvious.  The new timeout code (to better handle efficient
scheduling) has a sign problem.  That's true even on the i386, so I'm
surprised I haven't got bombarded with bug-reports. 

Anyway, your fix isn't the correct one, as that still leaves some of the
terminal layer timeouts wrong.  A more correct fix is to make sure that
a very large (unsigned) value for "current->timeout" doesn't result in a
negative value for the (signed) "expire" in the process timer. 

The alternative fix would be to make the "current->timeout" pointer be a
relative value (like the "timer->expire" one), and that would make jiffy
overflow a bit more graceful, for example (on the alpha, 64-bit overflow
isn't exactly a problem, though).  That would mean quite a lot of
changes, and not all of them beneficial, though. 

I'm including an untested fix for the process timeout code, could you
test this out?

		Linus

----------
--- old-version/linux/kernel/sched.c	Tue Jul 18 17:56:31 1995
+++ linux/kernel/sched.c	Fri Jul 28 09:30:23 1995
@@ -190,12 +190,17 @@
 			if (current->signal & ~current->blocked)
 				goto makerunnable;
 			timeout = current->timeout;
-			if (timeout && (timeout <= jiffies)) {
-				current->timeout = 0;
-				timeout = 0;
+			if (timeout) {
+				if (timeout <= jiffies) {
+					current->timeout = 0;
+					timeout = 0;
 		makerunnable:
-				current->state = TASK_RUNNING;
-				break;
+					current->state = TASK_RUNNING;
+					break;
+				}
+				timeout -= jiffies;
+				if ((long) timeout < 0)
+					timeout = (~0UL)>>1;
 			}
 		default:
 			del_from_runqueue(current);
@@ -229,7 +234,7 @@
 		kstat.context_swtch++;
 		if (timeout) {
 			init_timer(&timer);
-			timer.expires = timeout - jiffies;
+			timer.expires = timeout;
 			timer.data = (unsigned long) current;
 			timer.function = process_timeout;
 			add_timer(&timer);
----------

