On Thu, 2008-08-21 at 11:26 +0200, zhengda wrote: > In eth-filter, I define a structure > struct proxy_info > { > /* For receiving packets from pfinet. */ > struct port_info *pfinet_pi; > hurd_ihash_locp_t p_pfinetpi_hashloc; > > /* For receiving packets from the network interface. */ > struct port_info *device_pi; > hurd_ihash_locp_t p_devicepi_hashloc; > > /* For delivering packet to pfinet. */ > mach_port_t deliver_port; > hurd_ihash_locp_t p_deliverport_hashloc; > > /* The port to the network interface. */ > mach_port_t device_port; > }; > Because I cannot put two port_info objects in one structure, I put their > pointers in the structure.
Ah, there's the mistake. First, "struct proxy" is fine; no need for "info". You have a situation very much like a pipe, except that you are doing network packet stuff on each port instead of read/write on each port. So take a look at what pflocal does for a hint. You want something like struct proxy_user { struct port_info pi; struct proxy *px; }; struct proxy { int refs; struct mutex lock; a queue; other stuff maybe; }; > The result is that I cannot find the proxy_info structure with > ports_lookup_port(). I define some hash tables for it and do exactly as > what ports_lookup_port() does. That's why I need to get the name of the > port. Here you are totally violating the abstraction of libports. Instead, you want a single structure for each outstanding port--just like libports wants--and then that structure points to the common structure for what they share. The whole point of libports is to *eliminate* the need for that. Simply turn your pointers around and have them point the other way (as I sketch above) and your life will be much easier. > ports_destroy_right decrease the reference count for the port only when > the port has the send right (PORT_HAS_SENDRIGHTS flag). When the port > gets the send right, its reference count is always increased by 1. so as > long as the functions in libports are used correctly, > ports_destroy_right() cannot destroy the port_info structure. > As I understand, in order to destroy a port created by > ports_create_port(), we have to call ports_destroy_right() and > ports_port_deref(). Notice that Hurd servers basically never think "oh, I want to destroy a port." That's a very unusual thing. You don't keep track of that; this is exactly what libports is for. Your interpretation of ports_destroy_right is wrong. It does always destroy the port, completely. The mach_port_mod_refs is what destroys the port. Note that *all* the outstanding send rights, however many there may be, occupy only *one* reference in PI->refcnt. So when we do a ports_destroy_right, first we blow away the receive right, which causes the kernel to nuke all the outstanding send rights and turn them into MACH_PORT_NULL. Then we account for their loss by doing a ports_port_deref, if there were any send rights. (Notice that the no-senders notification we have outstanding is going to be cancelled when we nuke the receive right.) The only reason that ports_port_deref might not immediately eliminate the port is because there are likely *other* references to the port, perhaps in some other thread. We can't actually free the structure until they are done with it. But trule, ports_destroy_right does blow the whole thing away. > >> For the second case, if notify is null, how can we receive the > >> notification? The same question for the dead-name notification (the > >> argument notify is also allowed to be null). > >> > > > > You can't. The result is that you are cancelling the notification if > > one is outstanding. > > > The mach manual doesn't tell that:(, or I understand it in a wrong way. What was your understanding of it? Thomas