bug-hurd
[Top][All Lists]
Advanced

[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: Sun, 24 Aug 2008 19:36:36 +0200
User-agent: Thunderbird 2.0.0.16 (Macintosh/20080707)

Thomas Bushnell BSG wrote:
On Sat, 2008-08-23 at 13:25 +0200, Da Zheng wrote:
I have to make sure every ports has been destroyed so when the translator exits, it can check if there are still users.

Huh?  When the translator exits, all the ports are going to be destroyed
anyway.
The ports for the user program should all have been destroyed before the translator exits, so we can make sure all user programs connected to the translator has all exited and the exit of the translator won't cause any problems. The way we do it is to check the count of the portclass that is used to generate the ports for the user program.
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?

You don't call ports_port_deref because of ports_get_right *AT ALL*.
You call it because the variable PORT holds a reference, and *that*
reference is going away.  The call to ports_port_deref has *nothing* to
do with ports_get_right at all.  It is because the variable PORT holds a
reference, and that's a stack variable which is going to be deallocated
once this function returns.
Maybe I haven't made it clear enough. We are thinking about it in a different angle. My point is how to make sure the port will be destroyed in no-sender notification.

As I said above, I have to make sure all ports created for the user program have been destroyed before the translator exits. Assume that I create a port for the user programs and give its send right to them. After ports_create_port() and several ports_get_right() are called, the reference count of the port is 2. When all user programs exit, the no-senders notification for the port is generated. If ports_port_deref() isn't called somewhere, the reference count of the port is still 2 when the no-senders notification comes, therefore, the port cannot be destroyed by ports_no_senders() or ports_do_mach_notify_no_senders() or something else. As a result, when the translator checks the count of some portclass, it thinks that some user programs are still running (actually they are not), and doesn't exit. That's the problem. That's why I ask you for a suggestion where I should call ports_port_deref() to decrease the reference count when there is a sequence of ports_get_right() calls.

I hope I have made the things clear. I'm really a bad teller:(

Ah, I see now, the device_set_filter interface is very unusual.  I had
remembered that you could have only one filter at a time, but that's not
correct.  The only way to make the filter go away is to make the port go
dead.

So this is, as it happens, a rare case where you do need
ports_delete_right.

I still insist that the correct structuring of the structs is as I
outlined.

First, you still want the memory be allocated in the way that libports
expects:

struct filter_user {
  struct port_info pi;
  struct filter_setup *filter;
};

struct filter_device {
  struct port_info pi;
  struct filter_setup *filter;
};

struct filter_user and filter_device need to be distinct port classes.
They might end up being the same struct if you don't need any extra
members, of course.

struct filter_setup {
  struct mutex lock;
  struct filter_user *u; /* does NOT hold a reference */
  struct filter_device *d; /* does NOT hold a reference */
  ...
};

In the clean routine for filter_user, you would need to do the
following:
  if (fu->filter->d)
    ports_destroy_right (fu->filter->d);
  fu->filter->d = 0;

The ports_destroy_right will nuke the receive right, causing the kernel
to (eventually) clean up its data structures, and the ports_port_deref
accounts for the FU->dev reference itself which is going away.

You have to be very careful to remember that you have no control over
the order the clean routines would be called and so forth.
It's exactly what I did after I followed your suggestion to use the structure of proxy_user, proxy_device and proxy:-).
In the clean routine of proxy_user, I also freed the memory of proxy.
In the clean routine of proxy_device, I just set the pointer to the proxy_device in the proxy structure null (device->proxy->device = NULL).

Zheng Da




reply via email to

[Prev in Thread] Current Thread [Next in Thread]