[comp.os.mach] port name matching

nobody@orca.wv.tek.com (-for inetd server command) (12/25/89)

I am writing some server programs that deal with multiple clients.  Each
client (typically) has send rights to some ports owned by the server.
I've noticed that when the server task receives a port-death notification
message, the notify_port member of the message differs by one from the
port_name_t variable held by the server.  Since this behavior appears
consistent, I simply add 1 to the value supplied in the message (after
casting to 'int'), and use this value as the key in a table search for
the client connection that has been broken.  But why the difference?
What is the port_name_t supplied in the notify message supposed to mean?

In general, what is the algorithm for correlating port names supplied
in notifications and reports with the port names held by the task?

While in the case mentioned above, my ad hoc solution of 'add one' seems
to work, another server I am writing has not yet yielded such an empirical
transform.  This is an out-of-kernel server to implement System V shared
memory semantics.  This server uses the netmemoryserver to supply the
shared memory.  The SysV "shmget" routine is implemented by a
netmemory_create() performed by the server; it retains rights to the
paging_object and control_port supplied. A unique 'shmid' (shared memoryID)
is created by the server and returned.  The SysV "shmat" (attach) function is
implemented by having the server perform a vm_map() operation on the
client's task port.  The "shmat" function supplies as argument the shmid
created during the shmget; this ID is used as a key for a table search

The problem arises in the SysV "shmdt" (detach) function.  The sole
argument specified in the SVID is the virtual address of the memory to
detach from the client's address space.  How can the server determine
which of many netmemory objects is to be detached?  [The PID, UID and GID
of the caller is supplied by our kernel layer to the server, along with
the caller's task port.  This is not enough, because processes may attach
a shared memory segment and then fork.  The memory is shared between parent
and child.  We would like not to clutter up the kernel by adding an kernel
message to the server on forks.  Duplicating the SysV inheritance behaviour
is of course no problem; during the vm_map() operation the server specifies
VM_INHERIT_SHARE.]

My current, partial, solution is to use vm_region() with the supplied
virtual address against the client's task port.  This gives the server
the size of the object, which completes the information necessary to
perform a vm_deallocate() on the client's behalf to detach the memory.

Vm_region() also supplies a port name corresponding to the paging object of
the region.  But this value differs from the value of the port_name_t
variables retained by the server.  How can I use the information supplied
by vm_region() to identify the netmemory_object in question?  In what
"name space" are these port names valid?

Thanks,

Bill Kerr
Tektronix
billk@orca.wv.tek.com

Richard.Draves@CS.CMU.EDU (12/26/89)

Excerpts from netnews.comp.os.mach: 24-Dec-89 port name matching -for i.
s. command@orca. (2988)

> In general, what is the algorithm for correlating port names supplied
> in notifications and reports with the port names held by the task?

The port name supplied in a port-deleted notification is the name of the
erstwhile send right.  When a port is destroyed, because its receive
right is deallocated, the kernel deallocates any remaining send rights
and notifies the holders of those rights with port-deleted notifications.

It sounds like you are expecting the notification to be generated before
the kernel actually generates it, so that when you expect a notification
for port N you are actually getting the notification for the previous
port, N-1.  (In Mach 2.5, the kernel picks names for port rights
sequentially.  This is an implementation choice, and is subject to
change.  The kernel can pick any unused name for a new port right.)  I
don't understand your scenario, however.  You say the clients have send
rights for ports owned by the server, and then go on to talk about
notifications received by the server.


> Vm_region() also supplies a port name corresponding to the paging object of
> the region.  But this value differs from the value of the port_name_t
> variables retained by the server.  How can I use the information supplied
> by vm_region() to identify the netmemory_object in question?  In what
> "name space" are these port names valid?

The vm_region() call returns send rights for a name port.  The external
memory management interface deals with three kinds of ports.  The memory
object is represented by a memory object port, or memory_object_t.  The
server (netmemoryserver in this case) holds receive rights for the
memory object port.  You supply send rights to this port in vm_map()
calls.  When a kernel first encounters a memory object in a vm_map()
call, it creates a control port (memory_object_control_t) and name port
(memory_object_name_t).  If a memory object is mapped into address
spaces on multiple machines, a single object will have multiple control
and name ports.  The kernel has receive rights for the control and name
ports.  The kernel sends messages (from the memory_object.defs
interface) to the memory object port.  The server sends messages (from
the mach.defs interface) to the control port.  Messages aren't sent to
the name port; it is used for identification purposes in vm_region()
calls.

The control port returned by netmemory_create() is different from the
memory object control port for which the kernel holds receive rights. 
The netmemoryserver has receive rights for the control port from
netmemory_create().  The control and name ports owned by the kernel
haven't yet been created at the time of netmemory_create(); that doesn't
happen until somebody maps the object.

One possibility would be to use vm_region() immediately after vm_map(),
to find out what the name port is.  Then you can make use of the name
port from later vm_region() calls.

Rich