Date: Tue, 15 Jul 2003 03:35:24 -0700 From: Terry Lambert <tlambert2@mindspring.com> To: Petri Helenius <pete@he.iki.fi> Cc: freebsd-threads@freebsd.org Subject: Re: LinuxThreads replacement Message-ID: <3F13D8EC.8899DA42@mindspring.com> References: <007601c3467b$5f20e960$020aa8c0@aims.private> <004d01c348ae$583084f0$812a40c1@PETEX31> <3F12EF5A.71249E4D@mindspring.com> <16146.65087.69689.594109@emerger.yogotech.com> <3F13B1B4.8765B8F3@mindspring.com> <049201c34aab$9361d070$812a40c1@PETEX31>
next in thread | previous in thread | raw e-mail | index | archive | help
Petri Helenius wrote: > > One evil purpose threads can be used for is to intentionally exploit > > a decriptor close race with a blocking fd operation not protected by > > giant, such that the close invalidates the descriptor before the > > blocking operation completes, after which the code following the > > blocking operation dereferences the (now invalid) descriptor contents= =2E > > > Are you saying that this is a fundamental flaw in the design or a bug > that hasn=B4t been fixed as of yet? It depends on how you intend to handle close(2) in the case that there is a positive reference count greater than 1 for the fd being closed out from under the kernel, and it depends on how you intend to handle references on the f_data (and, now, f_vnode) members of struct file to protect them. The really evil way to do this would be to either fail or block the close. I think there is actually a lot of Java code that expects the close call to abort the pending blocked operation in progess on thread #2 when thread #1 closes the descriptor out from under it (that's what Solaris does), which probably means that's the only really viable option. > > I can also guarantee you from a performance perspective that an FSA > > will beat almost anything else you could write, in terms of raw > > ability to move data, or support high client loads, and will handily > > beat threads, unless you are on an SMP system, and aren't willing to > > run multiple copies of the program to do your scaling. > = > The usual thing I run across is to how effectively manage large > fd_set=B4s without using threaded architechture. Spinning through a few= > thousand descriptors for almost each read gets expensive quickly. > (or write, if you=B4re going that way) > As usual, suggestions are welcome and might lead to more better > code in the world... The general answer is "kqueue is your friend". 8-). One thing that is very helpful to do is to seperate out the flags and hint arguments to KNOTE(), and then pass the user void argument through to the knote() code. Doing this is very handy, besides enabling you to raise maxproc higher than the point where it collides with the hints bits, I mean. One of the things Linux-ites always complain about when talking about kqueue() is "it's level triggered, not edge triggered". By this, they mean that you don't get a separate event per source event (e.g. if you get three packets of data, and you haven't reaped the note in the time it takes to do this, then you will only reap a single note with the aggregate byte count in it, rather than three notes with the bytecount per packet). By passing in the user's void * address, you can guarantee that the user and a given new kevent can make a contract to deal with event disposition, e.g. into a buffer to contain a list of events. This lets you address the Linux argument. For example, if you were writing an AnitVirus package (speaking hypothetically), then you could trap all opens and/or writes to files, and find the guilty party who's doing the infecting, at the time of the infection. Then you terminate the program. > > Yes, this is somewhat mitigated by the fact that it's easier to write= > > threads code than an FSA, such that a lesser coder is still able to > > be productive. As a class, it's a tool I would lump in with things > > like "perl". > = > perl is good "Leatherman(TM)" tool. "Perl is a tool for other people." 8-). It's good for a quick-and-dirty implementation of something, and, as far as scripting languages go, it's possible to write readable perl; in practice, however, almost no one does. Everyone has their favorite method of solving a problem, and perl offers lots of ways to skin a cat. In practice, that tends to make the code only easily readable by the original author. Alfred told me he was helping someone out with some threads code the other day, and they ended up managing the server connections in a threads separate from the worker thread that had to deal with the descriptor. As a result, the tended to do things like close fd's out from under their worker threads (which is what put me in mind of the close race problem). I put this in the same class of naieve coding errors that one commonly makes when trying to maintain someone else's perl code. It's not so much that either one is inherently bad, but that they both tend to magnetize your feet any time you pick up a gun. 8-). > > All that said, FreeBSD's libkse is much less offensive, in terms of > > overhead and cost, than a raw 1:1 implementation, like the one in > > the current Solaris, or Linux. Solaris' argument is that it's hard > > to get something like that correct, and they were worried about the > > implementation bugs; that just adds fodder to the argument that you > > should avoid threaded code, where possible. > = > There are people who solve their database performance problems by > adding memory until everything is cached. Putting more hardware in > seems to be default operating pattern for Solaris environments. And > everybody seems to be happy with it. At least there the OS does not > bloat constantly like it does in the WinTel land. I guess to a large degree the ability to do this for Solaris comes from the fact that they are a 64bit OS, so they can just stuff RAM into the box until the power supply can no longer cope with it. 8-). It helps to have the necessary head room to be *able* to throw hardware at the problem. -- Terry
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3F13D8EC.8899DA42>