FROM: Peter Wemm DATE: 10/31/1998 13:10:00 SUBJECT: RE: kern/8500: FreeBSD 3.0 thread scheduler is broken The following reply was made to PR kern/8500; it has been noted by GNATS.
From: Peter Wemm <>
To: HighWind Software Information <>
Cc:
Subject: Re: kern/8500: FreeBSD 3.0 thread scheduler is broken
Date: Sun, 01 Nov 1998 03:08:44 +0800
HighWind Software Information wrote:
>
> > >Number: 8500
> > >Category: kern
> > >Synopsis: FreeBSD 3.0 thread scheduler is broken
> >
> > >Description:
> > When an application has threads that are I/O intensive, that thread
> > unfairly steals cycles from all other threads. This makes writing
> > an MT program that does any real amount of I/O impossible.
>
> Yes, open(), read(), write(), etc block the entire process. The libc_r
> thread engine only works for things that can be select()ed apon, and read/
> write cannot (yet).
>
> Ummm. Not to be rude.. But...
>
> That is NOT TRUE AT ALL. read() and write() CERTAINLY are selected
> apon and do NOT block the whole process when using libc_r.
>
> Read /usr/src/lib/libc_r/uthread/uthread_write.c and see for yourself.
Yes, but only if the file descriptor itself supports O_NONBLOCK mode..
/* called by open() wrapper */
_thread_fd_table_init(int fd)
{ ...
/* Get the flags for the file: */
if (fd >= 3 && (entry->flags =
_thread_sys_fcntl(fd, F_GETFL, 0)) == -1) {
ret = -1;
}
else {
...
}
And in write(), it just calls the write system call:
write()
{
....
/* Check if file operations are to block */
blocking = ((_thread_fd_table[fd]->flags & O_NONBLOCK) == 0);
/*
* Loop while no error occurs and until the expected number
* of bytes are written if performing a blocking write:
*/
while (ret == 0) {
/* Perform a non-blocking write syscall: */
^^^^^^^^^^^^^^^^^ - only if opened in O_NONBLOCK
n = _thread_sys_write(fd, buf + num, nbytes - num);
/* Check if one or more bytes were written: */
if (n > 0)
It`s similar for read().
There`s a couple of big ifs so far. *If* you open the file in O_NONBLOCK
mode specifically, then you get non-blocking read/write syscalls. The
syscalls themselves are only non-blocking *if* the underlying fd supports
it. Sockets and pipes support it. Files (at least on ufs/ffs) do not.
No matter whether you ask for O_NONBLOCK or not, you will always get a
blocking read/write with disk IO with read and write.
> The only alternatives are to use the aio/lio syscalls (which work), or
> rfork(). libc_r could probably be modified to use rfork() to have the
> read/write/open/close/etc done in parallel.
>
> I don`t think that is necessary.
It is if you want the threading to continue while the disk is grinding
away. aio_read() and aio_write() would probably be enough to help file
IO, but open() will still be blocking.
Squid has some fairly extensive async disk-IO routines. They happen to
use pthreads as a mechanism of having child processes do the blocking
work. FreeBSD could use rfork() for arranging the blocking stuff in child
processes with shared address space. It would be a lot of work though,
and would be a problem on SMP systems.
> -Rob
Cheers,
-Peter
To Unsubscribe: send mail to
with "unsubscribe freebsd-bugs" in the body of the message
|