ken@gvax.cs.cornell.edu (Ken Birman) (03/27/90)
Joe Boykin at Encore answered my questions as follows: 1) I can't get "select" to run on a Mach port; have to fork off a thread for each port-set on which I want to do a read (or perhaps for each port) and structure my code to interrupt the select if a message comes in this way. 2) I need to use the environment manager to pass the receive rights, or build some equivalent mechanism into ISIS to map from ISIS addresses to mach ports. My guess is that (1) translates to a lot of code for me, (2) seems pretty straightforward. Probably, I will do this, but as an aside to the Mach group let me make the following points. For a project like mine, there is no major advantage to Mach except speed: it is a more elegant operating system, granted, but my code already was working just fine, and portability is very important to me. So, to the extent that I specialize I am going to have to combine UNIX and Mach features, and will do it mostly for some overwhelming performance advantage. The scheme Joe outlined actually implies a fairly substantial amount of code in ISIS: I would estimate 1-2 weeks full time for someone without much Mach experience. On the other hand, if Mach offered me an AF_MACH socket type from UNIX, I could benefit from Mach performance without adding a zillion ifdef's to use the various special Mach facilities that I seem unable to avoid. As I see it, there seems to be some inconsistency between Rick (who recently explained that he views Mach as a core system, with interfaces like UNIX, VMS, and even OS/2 layered around it for those who want them) and Joe, who seems to be more of a purist (if you want the speed, do it our way). Personally, I want do minimize the amount of work I do and maximize portability for my UNIX code, while also benefiting from Mach performance... And, the bottom line is that this will only benefit ISIS users who run ISIS over Mach: a small minority of our community. So how about it, Rick? Why not give me an AF_MACH socket type and a make_unix_fdes(port-no) system call, so that I can do select and just hack my recvfrom/sendto code... I bet that there are more people like me than you realize. Sure, I like your system, but I'm just too busy to do everything differently to make use of it. And, unless a lot of people do redo things, it looks to me as if the major Mach advantages are very hard to "experience" without a big investment. That is, if you are doing UNIX over Mach, why not do it right? Ken
avie@wb1.cs.cmu.edu (Avadis Tevanian) (03/27/90)
In article <39068@cornell.UUCP> ken@cs.cornell.edu (Ken Birman) writes: >So how about it, Rick? Why not give me an AF_MACH socket type and >a make_unix_fdes(port-no) system call, so that I can do select and >just hack my recvfrom/sendto code... Well, if you were to do this you'd end up throwing away most of the performance gains you are after. One advantages of the Mach interface is that you can effectively combine the UNIX select/recv into just one call, msg_receive. Besides, the code is actually not that difficult. The way we do this in NextStep is to assume that the majority of communication occurs using Mach IPC (it does). All of the main pathways are IPC based, if someone also wants to wait on a fd, a separate thread does the select and sends a message to the main thread with data is available. The common case is super fast, the less common case is not a lot slower than it was before (the additional context switch is negligible when compared to the costs of the write/select/ read). -- Avadis Tevanian, Jr. (Avie) Manager, System Software NeXT, Inc. avie@NeXT.COM
Richard.Draves@CS.CMU.EDU (03/29/90)
> Excerpts from netnews.comp.os.mach: 26-Mar-90 Re: Combining UNIX-style > an.. Avadis Tevanian@wb1.cs.c (1094) > In article <39068@cornell.UUCP> ken@cs.cornell.edu (Ken Birman) writes: > >So how about it, Rick? Why not give me an AF_MACH socket type and > >a make_unix_fdes(port-no) system call, so that I can do select and > >just hack my recvfrom/sendto code... > Well, if you were to do this you'd end up throwing away most of the > performance > gains you are after. One advantages of the Mach interface is that you > can effectively combine the UNIX select/recv into just one call, > msg_receive. Avie makes a good point here. select() is a hefty performance hit, and combining select/receive into a single msg_receive is a big win. Another optimization you should try for is combining send/receive into a single msg_rpc. This avoids another system call and lets the kernel use a more efficient path through the scheduling code. > Besides, the code is actually not that difficult. The way we do this in > NextStep is to assume that the majority of communication occurs using > Mach IPC (it does). All of the main pathways are IPC based, if someone > also > wants to wait on a fd, a separate thread does the select and sends a > message > to the main thread with data is available. The common case is super > fast, > the less common case is not a lot slower than it was before (the > additional > context switch is negligible when compared to the costs of the > write/select/ > read). It is a little more complicated, but it is possible to avoid the performance hit for the socket operations. I'm assuming your server code isn't written to be multi-threaded, so the easiest approach (having multiple server threads processing requests from different sources in parallel) isn't possible. The basic idea is to have a giant lock around most of the server code, with a queue to hold requests that can't be processed because the lock is taken. Your server has two threads, one blocking in msg_receive and the other blocking in select. The two threads communicate with each other through a shared data structure that holds pending requests and records which thread, if any, is off in the non-parallel server code processing a request. When a thread unblocks with a new request, it checks the shared data structure. If the other thread is busy processing, it drops the new request in the queue and blocks again. If the other thread isn't processing, then it go ahead and process the request directly, recording this in the shared data structure. When a thread finishes processing a request, it checks the shared data structure. If there are queued requests, then it picks them up and continues processing. Otherwise it records that no thread is processing and blocks for more requests. Rich