New issue
Advanced search Search tips

Issue 786180 link

Starred by 1 user

Issue metadata

Status: WontFix
Owner: ----
Closed: Dec 3
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Mac
Pri: 3
Type: Bug



Sign in to add a comment

Mojo EDK: Reduce overhead to a single "intermediate" port per-Message, rather than one-per-port-to-send.

Project Member Reported by w...@chromium.org, Nov 16 2017

Issue description

When Mojo messages containing Mach ports are send via IPC, for each sent-port an intermediate port is created in the target task and a send-once right extracted, through which the sent-port is passed.

The send-once port technique is a standard pattern when a process wants to receive ports while also being able to detect if the sender fails to send, e.g. because they have crashed. However, since we are implementing it from the sender, we take the penalty of a couple of context-switches for each port transferred (to create the port in the target task, and extract the right), to no useful purpose.

We should remove the intermediate port, and pass Mach ports directly from sender to target task.
 

Comment 1 by w...@chromium.org, Nov 22 2017

Cc: rsesek@chromium.org
Status: Started (was: Assigned)
We're currently inserting an intermediate port into the peer address-space and then sending across that, so in principle we'd just replace this with simple insertion of the original port right, directly into the peer task.

We can insert into the peer process, but if the port name is already in-use there then we'll get a KERN_NAME_EXISTS failure. Conversely, we can allocate a new "dead" name and insert using that, but then mach_port_insert_rights() will fail with KERN_RIGHT_EXISTS if the receiving task already has a name for that port.

We can instead continue to use mach_msg(), takes care of whether to increment the ref-count of an existing port name, or allocate a new one, but then we to arrange a port across which to send. We could use a port per-Channel, in principle, but only if we can move the port-sending work into ChannelPosix, to keep it synchronized with Message sending.

Alternatively we can allocate an intermediate port per-Message, write all the ports-to-send into that, and pass the name in the MachPortsExtraHeader rather than a separate name per-port. This should still allow us to eliminate the MACH_NAME complexity.
> We can insert into the peer process, but if the port name is already in-use there then we'll get a KERN_NAME_EXISTS failure. 

This is what you want. You'll need to guess at random port names until you find a free space. This seems kind of weird [partly why I didn't do this when first implementing, but *shrug*.

> Alternatively we can allocate an intermediate port per-Message, write all the ports-to-send into that, and pass the name in the MachPortsExtraHeader rather than a separate name per-port. This should still allow us to eliminate the MACH_NAME complexity.

Err...I actually think this is more complex than the current solution.

Comment 3 by rsesek@chromium.org, Nov 22 2017

> This is what you want. You'll need to guess at random port names until you find a free space. This seems kind of weird [partly why I didn't do this when first implementing, but *shrug*.

I think you should be able to allocate a dead name right into the target task space, and then insert a real right on top of that name.

Comment 4 by w...@chromium.org, Nov 22 2017

Re #2: Agreed, I would prefer not to guess random port names; that seems
silly and fragile. As for complexity, it's similar to the current solution,
with the difference that we reduce the number of RPCs to the receiving task
from several-per-port to a couple per-message. It'd still be simpler for
most surrounding code because it would no longer have to deal with
MACH_NAME, only MACH or POSIX (though you might argue that a lot of the
complexity with the current impl is more a question of the different bits
of code being spread across a load of different layers, rather than the
mechanism itself).

Re #3: I don't think that will work, though; I think
mach_port_insert_rights() will only work in that way if the peer process
doesn't already have a name for the right we're sending - if it already has
that right, under a different name, then the call will fail with
KERN_RIGHT_EXISTS.
Ahh, I see. The automatic de-duplication of already-existing ports [to avoid KERN_RIGHT_EXISTS] is why we originally went with the intermediary port solution. I don't think there's a simpler solution than the current mechanism.

Comment 6 by w...@chromium.org, Dec 2 2017

Owner: ----
Status: Available (was: Started)
Summary: Mojo EDK: Reduce overhead to a single "intermediate" port per-Message, rather than one-per-port-to-send. (was: Mojo EDK: Remove "intermediate" port dance when sending Mach ports between peers)
Cc: -roc...@chromium.org rockot@google.com
Status: WontFix (was: Available)
So based on comment #5 this sounds like a no-op.

Sign in to add a comment