Re: Important patch to fix select!

Rogier Wolff (R.E.Wolff@BitWizard.nl)
Thu, 8 Jul 1999 17:08:00 +0200 (MEST)


Dong Liu wrote:
>
> You should not blindly add the extra one, you should check if usec == 0
> first.

Agreed.

> Maybe your way is more correct, but my way is more useful. Suppose
> you want generate a stream of UDP packets with 10 ms second length
> of voice, in this case it is not very inportant if you occasionally
> send a packet too fast or to slow, so I can do it like this,

Right.

How would you like that the filesystem would occasionally return data
that was in a file a few days ago? I mean it was there at some moment
in time, why are you getting upset about reading that data now?

The programming interface gives us guarantees. If you perform a read
on a file, you get the most recent data. If you ask for a timeout of
10ms, you get to wait at least 10 ms.

A friend of mine has a CD-changer. Two CD players, and a robot arm to
fetch any of the 300 CDs that the rack will hold. The stepper motors
can step at 300Hz. So on an alpha, you'd simply

usleep (3000);

before instructing the motor to do the next step. It is perfectly
accpetable that this usually takes 4ms. You loose about 25% of the
speed of the robot, because it usually takes 4ms, but you have about 3
minutes to go get the next CD anyway. However the motor will loose a
step every time you step it in 2ms. Loosing steps means damaging CDs.
(Stepper motors come with the guarantee that they are exactly in the
position that you programmed them to be, provided that you stick to
the rules.... so no: it is not practical to have sensors all over the
place to detect the exact position of cd-grab-tool. That's why the
stepper motors were used.)

> But if use your approach, I have to rely on some other trick, like
> increasing HZ, using itimer signal or using the RTC driver.

Yes. Sorry. But being right carries more weight than convenience....

> I think the best way is to schedule for the minimun timeout, when wakeup
> check to see if the timeout is really expired, if not then scheduling
> for the one extra jiffie.

That won't work. You'd have to do the cycle-counter gettimeofday call
every time to get that. Now we just rely on "jiffies".

Roger.

----- New-and-improved patch ----------------------------------------

diff -ur linux-2.2.10.clean/fs/select.c linux/fs/select.c
--- linux-2.2.10.clean/fs/select.c Thu Jun 17 16:19:39 1999
+++ linux/fs/select.c Thu Jul 8 16:54:41 1999
@@ -39,6 +39,45 @@
* Linus noticed. -- jrs
*/

+/*
+ * An important issue that people seem to forget is that if I request
+ * a timeout of xx ms, then the system should NEVER timeout BEFORE
+ * those xx ms are over. On a multitasking operating system I should
+ * always be prepared to be woken up a bit later (e.g. because another
+ * task was running, or because my pages were suddenly swapped to
+ * disk), but I can count on not being woken up earlier.
+ *
+ * (For simplicity the following uses the numbers for Intel machines.
+ * On Machines with a HZ value that is different than 100, the same
+ * applies, but at a different scale).
+ *
+ * Now, indeed when things seem to matter is when an application
+ * requests a timeout that is very small. Because the system timer
+ * runs at 100Hz, the system has to round everything to a multiple of
+ * the 10ms system clock. And due to the requirement of never timing
+ * out early, we have to round up. But there is one more issue. As we
+ * want maximum speed here, we won't use the cycle counters or
+ * something like that to determine where in the 10ms interval between
+ * two timerticks we are. So for all we know, we could be only a
+ * microsecond away from the next timertick.
+ *
+ * So therefore, besides rounding up, we need to add in one more timer
+ * tick to compensate for this.
+ *
+ * This means that an application that has something trivial to do and
+ * then sleeps for an interval < 1/Hz, will be put to sleep for two
+ * timer ticks. However we cannot tolerate that an application that
+ * takes 9.9 ms to do its work and then requests a timeout in 9.9 ms
+ * gets woken up in just 0.1 ms.
+ *
+ * Is this clear to everyone? Now please don't break this again.
+ * Thanks.
+ *
+ * -- REW.
+ *
+ */
+
+
static void free_wait(poll_table * p)
{
struct poll_table_entry * entry;
@@ -261,9 +300,13 @@
if (sec < 0 || usec < 0)
goto out_nofds;

+ /* See note at the top of this file. */
if ((unsigned long) sec < MAX_SELECT_SECONDS) {
- timeout = ROUND_UP(usec, 1000000/HZ);
- timeout += sec * (unsigned long) HZ;
+ if (usec || sec) {
+ timeout = 1 + ROUND_UP(usec, 1000000/HZ);
+ timeout += sec * (unsigned long) HZ;
+ } else
+ timeout = 0;
}
}

Only in linux/fs: select.c~

-- 
** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2137555 **
*-- BitWizard writes Linux device drivers for any device you may have! --*
------ Microsoft SELLS you Windows, Linux GIVES you the whole house ------

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/