On Sun, 4 Jul 1999, Jonathan Lemon wrote: > > This is an earlier posting that I attempted to make, perhaps > it can provide a starting point for discussion. While this > is already implemented, I'm not adverse to tossing it all for > something better. > -- > Jonathan > > > ----- Forwarded message from owner-freebsd-a...@freebsd.org ----- > > Date: Mon, 5 Apr 1999 17:42:02 -0500 > From: Jonathan Lemon <jle...@cs.wisc.edu> > To: freebsd-a...@freebsd.org > > I'd like to open discussion on adding a new interface to FreeBSD, > specifically, a variant of poll(). > > The problem is that poll() (and select(), as well) do not scale > well as the number of open file descriptors increases. When there > are a large number of descriptors under consideration, poll() takes > an inordinate amount of time. For the purposes of my particular > application, "large" translates into roughly 40K descriptors. > > As having to walk this descriptor list (and pass it between user and > kernel space) is unpalatable, I would like to have the interface > simply take a "change" list instead. The kernel would keep the > state of the descriptors being examined, and would in turn, return > a short list of descriptors that actually had any activity. > > In essence, I want to move the large "struct pollfd" array that I > have into the kernel, and then instruct the kernel to add/remove > entries from this array, and only return the array subset which > has activity.
How does the kernel manage this? Does each process potentially store a struct pollfd in struct proc? This seems a bit limiting since it forces a program to have exactly one call to poll. Peter's description of David Filo's event queue thing seems to solve that problem by introducing a new kernel object (the event queue). > > A possible (actually, my current) implementation looks like this: > > struct fd_change { > short fd; > short events; > }; Limited to 32767 file descriptors. Trivial to change though. Do you remove a fd from the list by setting events to 0? > > int > new_poll( > int nchanges; // entries in new changelist > struct fd_change *changelist; // changes to be made > int n_events; // max size of output list > struct fd_change *event; // returned list of events > int timeout; // timeout (same as poll) > ) > > Where the returned value is either an error, or the number of events > stored in the returned changelist. > > Some pseudo-code that would exercise the interface: > > struct fd_change fc[ MAXCHANGE ]; > > fc[0].fd = 20; > fc[0].events = ADD | READ ; // add, mark read "interest" > > fc[1].fd = -1; // ignore this one > > fc[2].fd = 32; > fc[2].events = DELETE ; // delete previous fd > > fc[3].fd = 46; > fc[3].events = WRITE ; // ask for writable events > > n_changes = new_poll(4, fc, MAXCHANGE, fc, -1); > > > Comments? Note that I haven't discussed the implementation details; > the implementation is done, and can probably be altered/improved, > but I would like to solicit feedback on the feasability of the interface. As I said before I'm uneasy about the kernel tracking the state (list of fds) in the process. A separate kernel object would be a much cleaner solution and would be usable by a program which called poll in many different ways. With this api, a library would be unable to use the new interface since it would not know the new_poll state setup by the main program and would not be able to change it without potentially breaking the caller's state. -- Doug Rabson Mail: d...@nlsystems.com Nonlinear Systems Ltd. Phone: +44 181 442 9037 To Unsubscribe: send mail to majord...@freebsd.org with "unsubscribe freebsd-hackers" in the body of the message