[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Some questions about libports and notification of ports
From: |
Da Zheng |
Subject: |
Re: Some questions about libports and notification of ports |
Date: |
Sat, 23 Aug 2008 13:25:46 +0200 |
User-agent: |
Thunderbird 2.0.0.16 (Macintosh/20080707) |
Thomas Bushnell BSG wrote:
> struct port_info *foo;
> ports_create_port(portclass, bucket, sizeof(*foo), &foo);
> ....
> ports_port_deref(foo); // ports_port_destroy(foo) doesn't work here.
It works just fine, *if your intention is to delete the receive right*--
a rare and unusual thing.
I have already done what your suggested, and when I look at my code
again, I find it is unnecessary to do it.
One end of the pipe is the user program and the other is the device, so
I need to create two port_info objects for the pipe.
Yes, this is correct.
When the user program exits, the port for it can be destroyed by
no-sender notification,
You are thinking "how can we destroy the port", which is the wrong
question. But yes, when the user has had this event, the port can be
destroyed.
I have to make sure every ports has been destroyed so when the
translator exits, it can check if there are still users.
and meanwhile, the other port should also be destroyed,
WHY? What possible value is there in destroying the other port?
Notice, for example, the way pipes work. Suppose the reader dies, and
there are no readers. We do not destroy the writer's port. Heaven's
no! Instead, we accept requests on it, just as normal, *and we return
EPIPE*.
We don't need to destroy the port, nor should we. It still has users.
Yes, their requests may fail, but that doesn't mean there aren't still
people holding send rights who are entitled to see the protocol
continue.
The reason is that one end is the user program, but the other is the
device (that isn't the regular user).
OK, maybe I should make the things more clear.
I'm writing a filter translator called eth-filter whose function is to
forward and filter the packet between the network device and the user
program such as pfinet,
so eth-filter needs to build a "pipe" for them.
eth-filter needs two ports, so it can get the packet from the user
program and the network device.
The user program can exit, it's quite normal, but the device cannot.
so the network device always holds the send right to the port of
eth-filter.
Let's see what the result will be. The device keeps sending the packet
to the eth-filter and eth-filter should forward it to the user program.
But the user program doesn't exit any more.
In this case, eth-filter must tell the device: the user program doesn't
exist, so please don't send me any packets that is to the user program.
The only way I can find is to destroy the port for the device. I think
it's the way of operating the network device. device_close() doesn't work.
After the port is destroyed, the device will find the send right is a
dead name and stop sending the packets (that should be to the user
program) to eth-filter.
If the port for the device isn't destroy with ports_destroy_right(), it
might never be destroyed
because its send right might always be kept by the device, and
no-senders notification will never be generated.
I'm confused. How does a device hold send rights to your port? Mach devices don't work
that way. What is this "device" that is holding a send right?
Sorry, I forget to mention it's a network device.
When we set the filter with device_set_filter, we have to give the
network device a send right, so when the network device gets a packet,
it can deliver it with the send right.
Another thing surprises me is that in some code of hurd,
ports_port_deref() is used with ports_get_right() together. For example,
error_t
S_io_duplicate (struct sock_user *user,
mach_port_t *newobject,
mach_msg_type_name_t *newobject_type)
{
struct sock_user *newuser;
if (!user)
return EOPNOTSUPP;
__mutex_lock (&global_lock);
newuser = make_sock_user (user->sock, user->isroot, 0, 0);
*newobject = ports_get_right (newuser);
*newobject_type = MACH_MSG_TYPE_MAKE_SEND;
ports_port_deref (newuser);
__mutex_unlock (&global_lock);
return 0;
}
When we create the port_info, it has one reference, held by the variable
NEWUSER. Then we call ports_get_right and create a send right. Now
there are two references, one held by NEWUSER, and one held by the
outstanding send rights. Then we release the references held by
NEWUSER, and return.
At the end of the function, the reference count is 1, and there is one
reference outstanding (the send rights).
You are busy thinking "how can we get things destroyed", in a way that
suggests you don't understand what reference counting is for.
Actually I'm thinking how I can manage the reference count correctly, so
the port_info object can be destroyed at last when it's not needed.
ports_port_deref() is need to be called here, otherwise the port_info
object cannot be destroyed by ports_port_destroy() or no-senders
notification later.
The code is right here because ports_get_right() may be called on the
port only once.
Huh? You may call ports_get_right on a port as many times as you can.
But sometimes we do need to call ports_get_right() on a port several times.
When should we call ports_port_deref() to decrease the reference count
that is created by the first ports_get_right()?
In the code above, we aren't dropping the reference from
ports_get_right, that would be crazy. We are *creating* that reference.
We are dropping the reference that was created by make_sock_user.
All outstanding send rights on a port share a single reference.
It's exactly why I think it's difficult to operate.
ports_get_right() can be called several times. Let's think about the
sequence as follow (it's not in the same function):
struct port_info *port;
ports_create_port(..., &port);
...
ports_get_right(port);
...
ports_get_right(port);
...
ports_get_right(port);
...
When should I call ports_port_deref()? after the first time of calling
ports_get_right()? or after the last time?
If it's the first time, then why ports_get_right() should increase the
reference count?
If it's the last time, it's difficult to find out that it IS the last time.
Zheng Da
- Some questions about libports and notification of ports, zhengda, 2008/08/20
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/20
- Re: Some questions about libports and notification of ports, zhengda, 2008/08/21
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/21
- Re: Some questions about libports and notification of ports, zhengda, 2008/08/21
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/22
- Re: Some questions about libports and notification of ports,
Da Zheng <=
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/23
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/23
- Re: Some questions about libports and notification of ports, Da Zheng, 2008/08/24
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/24
- Re: Some questions about libports and notification of ports, Da Zheng, 2008/08/25
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/25
- Re: Some questions about libports and notification of ports, Da Zheng, 2008/08/25
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/25
- Re: Some questions about libports and notification of ports, Da Zheng, 2008/08/26
- Re: Some questions about libports and notification of ports, Thomas Bushnell BSG, 2008/08/26