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: Thomas Bushnell BSG
Subject: Re: Some questions about libports and notification of ports
Date: Mon, 25 Aug 2008 09:21:41 -0700

On Mon, 2008-08-25 at 13:20 +0200, Da Zheng wrote:
> Yes, these ports have the receive rights.
> They are used for the user program, and I want to make sure they have 
> all been destroyed before the translator exits, so the translator knows 
> all user programs connected to it have all exited and it can exit 
> without causing any problems.
> I think every translator does it. For example, pfinet checks 
> "ports_count_class (socketport_class) != 0" in its trivfs_goaway(). If 
> the count of socket port class isn't 0, pfinet doesn't exit.

If you are exiting in the goaway routine, this is the right thing,
because the goaway routine is really about detaching from the parent
filesystem, and then exiting only once your users are done.

pfinet is not destroying any ports here, which is quite different from
what you asked.  If you want to make sure there are no ports, the thing
pfinet does is right.  If you want to destroy ports unconditionally,
then exit, then you can just exit.  That will automatically deallocate
all the ports in the task, including its receive rights.

> Right, I define three structures. My translator still run in one thread, 
> so I don't define a lock. and it's very uncommon for the device to exit 
> before the user program exits, so I don't destroy the port for the user 
> when the port for the device is destroyed. Actually the user program 
> will find it anyway.
> 
> struct proxy_user
> {
>   struct port_info pi;
>   struct proxy *proxy;
> };
> 
> struct proxy_device
> {
>   struct port_info pi;
>   struct proxy *proxy;
> };

Note that if you don't have any difference between these structures--if
there is nothing extra you need--you can combine them into one name.
Port classes will keep them separate for practical purposes.

> struct proxy
> {
>   struct proxy_device *device;
>   mach_port_t deliver_port;
>   hurd_ihash_locp_t p_deliverport_hashloc;
>   mach_port_t device_port;
> };


> 
> To create the proxy_user and proxy_device objects:
> 
> error_t
> create_proxy_user (struct proxy *proxy, mach_port_t *port)
> {
>   error_t err;
>   struct proxy_user *user;
> 
>   err = ports_create_port (user_portclass, port_bucket, sizeof (*user), 
> &user);
>   if (err)
>       return err;
>   user->proxy = proxy;
> 
>   *port = ports_get_right (user);
>   ports_port_deref (user);
>   return 0;
> }

Just to repeat here, b/c there was confusion before.  The
ports_port_deref you call here has nothing to do with the
ports_get_right call.  Nothing at all.  It is there because of the
ports_create_port call.

> Here are the most important server side functions in device.defs.
> In ds_device_open(), I create the proxy_user and proxy object.
> 
> kern_return_t
> ds_device_open (mach_port_t master_port, mach_port_t reply_port,
>         mach_msg_type_name_t reply_portPoly,
>         dev_mode_t mode, dev_name_t name, mach_port_t *device,
>         mach_msg_type_name_t *devicetype)
> {
>   kern_return_t err;
>   mach_port_t master_device;
>   mach_port_t user_port;
>   struct proxy *proxy;
> 
>   if (device_file == NULL)
>     return D_NO_SUCH_DEVICE;
> 
>   master_device = file_name_lookup (device_file, 0, 0);
>   if (master_device == MACH_PORT_NULL)
>     return errno;
> 
>   proxy = (struct proxy *)calloc (1, sizeof (*proxy));
>   if (proxy == NULL)
>     {
>       mach_port_deallocate (mach_task_self (), master_device);
>       return D_NO_MEMORY;
>     }
> 
>   err = device_open (master_device, mode, name, &proxy->device_port);
>   mach_port_deallocate (mach_task_self (), master_device);
>   if (err != KERN_SUCCESS)
>     {
>       free (proxy);
>       return err;
>     }
> 
>   err = create_proxy_user (proxy, &user_port);
>   if (err)
>     {
>       mach_port_deallocate (mach_task_self (), master_device);
>       free (proxy);
>       return err;
>     }
> 
>   *device = user_port;
>   *devicetype = MACH_MSG_TYPE_MAKE_SEND;
> 
>   return 0;
> }

What is device_file set to?

Note that network device users are not obliged to use device_set_filter!
They can just use device_read and device_write as normal if they please.
You'll need to implement the whole device interface.

> Since eth-filter works as a proxy for several user programs, it can 
> receive many device_open requests.
> Should I call device_open only once in eth-filter or call it as long as 
> a device_open request comes?
> eth-filter connects to only one device, so device_open always returns 
> the same send right, even though the mode of opening device is changed.
> I don't know if it will cause a problem.

I would just open it once, with maximal permissions, and then manage the
permissions yourself.

Thomas






reply via email to

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