Re: copyin+copyout in one step ?

2013-05-28 Thread David Chisnall
On 28 May 2013, at 05:56, Zaphod Beeblebrox zbee...@gmail.com wrote:

 Urm... Isn't the use of shared memory the more obvious way to transfer data
 between processes?  Am I missing some nuance?

I can't speak for Luigi's use-case, but the Binder APIs in BeOS and Android 
call for this kind of copy.  The receiving process contains a ring buffer and 
the messages are pushed into it.  You could implement this in shared memory, 
but only if you trusted the sender not to modify the data at incorrect times or 
write invalid values into the metadata (or, in the case of Binder, to forge the 
pid / uid of the sender, which it attached to each message).  The kernel must 
act as an intermediary to enforce correct use of the buffer and also to allow 
the caller to block until space is available (perhaps by scheduling the 
receiver to run for a bit) without spinning and to allow multiple writers to be 
queued when there is no space, rather than have them racing.  The buffers are 
in the receiver's memory space because it is designed for resource constrained 
environments and for malicious parties to communicate, so it avoids a potential 
DoS by filling up kmem with buffers - a process that c
 reate a load of receive ports will simply fill up its own address space and 
die.

In the specific case of binder, you can avoid the overhead of extra VM lookups 
by mapping the buffer into the address space of every sender when you open the 
connection, but marking its access as privileged mode only.  This means that 
you'll be doing a simple copy.  You can also align the receive buffer in such a 
way that the consume counter is on a different page to the rest of the data 
structure, allowing you to get a page fault when the buffer transitions from 
full to non-full and there are messages waiting.

David

___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: copyin+copyout in one step ?

2013-05-28 Thread Luigi Rizzo
On Tue, May 28, 2013 at 6:56 AM, Zaphod Beeblebrox zbee...@gmail.comwrote:

 On Mon, May 27, 2013 at 7:38 PM, Luigi Rizzo ri...@iet.unipi.it wrote:


 say a process P1 wants to use the kernel to copy the content of a
 buffer SRC (in its user address space) to a buffer DST (in the
 address space of another process P2), and assume that P1 issues the
 request to the kernel when P2 has already told the kernel where the
 data should go:


 Urm... Isn't the use of shared memory the more obvious way to transfer
 data between processes?  Am I missing some nuance?


see my other message about the use between VMs.

I cannot simply share memory because otherwise 

the sender could
alter the message while the receiver is playing with it,
so at least one copy is needed (or page flipping, but that
would be way more complex/wasteful/
expensive)

.

But also, in my case the source and destination buffers
are chosen arbitrarily by the two VMs, and do not necessarily
reside in the mmapped buffers that the kernel module provides.
So at the moment I have three copies instead of one.

cheers
luigi
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


copyin+copyout in one step ?

2013-05-27 Thread Luigi Rizzo
Hi,
say a process P1 wants to use the kernel to copy the content of a
buffer SRC (in its user address space) to a buffer DST (in the
address space of another process P2), and assume that P1 issues the
request to the kernel when P2 has already told the kernel where the
data should go:

 P1P2
+--+ ++
| SRC  | | DST|
+--v---+ +--^-+
   ||--
   ||kernel
   |^

   ||
   |  ++|
   +-| tmpbuf ++
copyin|| copyout
P1 ctx++  P2 ctx

I guess the one above is the canonical way: P1 does a copyin() to a
temporary buffer, then notifies P2 which can then issue or complete
a syscall to do a copyout from tmpbuf to DST in P2's context.


But I wonder, is it possible to do it as follows: P2 tells the kernel
where the data should go (DST); later, P1 issues a system call and
through a combined copyinout() moves data directly from SRC to DST,
operating in the context of P1.

   |  copyinout() ? | 
   +---+
   issued by P1


Is this doable at all ? I suspect that tell DST to the kernel
might be especially expensive as it needs to pin the page
so it is accessible while doing the syscall for P1 ?
(the whole point for this optimization is saving the extra
copy through the buffer, but it may be pointless if pinning
the memory is more expensive than the copy)

cheers
luigi
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: copyin+copyout in one step ?

2013-05-27 Thread Alfred Perlstein

On 5/27/13 4:38 PM, Luigi Rizzo wrote:

Hi,
say a process P1 wants to use the kernel to copy the content of a
buffer SRC (in its user address space) to a buffer DST (in the
address space of another process P2), and assume that P1 issues the
request to the kernel when P2 has already told the kernel where the
data should go:

  P1P2
 +--+ ++
 | SRC  | | DST|
 +--v---+ +--^-+
||--
||kernel
|^

||
|  ++|
+-| tmpbuf ++
 copyin|| copyout
 P1 ctx++  P2 ctx

I guess the one above is the canonical way: P1 does a copyin() to a
temporary buffer, then notifies P2 which can then issue or complete
a syscall to do a copyout from tmpbuf to DST in P2's context.


But I wonder, is it possible to do it as follows: P2 tells the kernel
where the data should go (DST); later, P1 issues a system call and
through a combined copyinout() moves data directly from SRC to DST,
operating in the context of P1.

|  copyinout() ? |
+---+
issued by P1


Is this doable at all ? I suspect that tell DST to the kernel
might be especially expensive as it needs to pin the page
so it is accessible while doing the syscall for P1 ?
(the whole point for this optimization is saving the extra
copy through the buffer, but it may be pointless if pinning
the memory is more expensive than the copy)


I suspect you'll want to use something like vslock(9) and sf_bufs.

Have a look at vm/vm_glue.c - vslock() vm_imgact_hold_page().

On amd64, I *think* mapping an sfbuf or if you are really evil you can 
optimistically wire the page in the vm (cheap). If it's present then you 
can just use the direct map to access it.  However, if it's not present, 
then fall back to another  method, or maybe just fault it in (which will 
have to happen anyhow) and then retry.


Sounds like a cool project!

-Alfred
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: copyin+copyout in one step ?

2013-05-27 Thread Alfred Perlstein

On 5/27/13 4:56 PM, Alfred Perlstein wrote:

On 5/27/13 4:38 PM, Luigi Rizzo wrote:

Hi,
say a process P1 wants to use the kernel to copy the content of a
buffer SRC (in its user address space) to a buffer DST (in the
address space of another process P2), and assume that P1 issues the
request to the kernel when P2 has already told the kernel where the
data should go:

  P1P2
 +--+ ++
 | SRC  | | DST|
 +--v---+ +--^-+
||--
||kernel
|^

||
|  ++|
+-| tmpbuf ++
 copyin|| copyout
 P1 ctx++  P2 ctx

I guess the one above is the canonical way: P1 does a copyin() to a
temporary buffer, then notifies P2 which can then issue or complete
a syscall to do a copyout from tmpbuf to DST in P2's context.


But I wonder, is it possible to do it as follows: P2 tells the kernel
where the data should go (DST); later, P1 issues a system call and
through a combined copyinout() moves data directly from SRC to DST,
operating in the context of P1.

|  copyinout() ? |
+---+
issued by P1


Is this doable at all ? I suspect that tell DST to the kernel
might be especially expensive as it needs to pin the page
so it is accessible while doing the syscall for P1 ?
(the whole point for this optimization is saving the extra
copy through the buffer, but it may be pointless if pinning
the memory is more expensive than the copy)


I suspect you'll want to use something like vslock(9) and sf_bufs.

Have a look at vm/vm_glue.c - vslock() vm_imgact_hold_page().

On amd64, I *think* mapping an sfbuf or if you are really evil you can 
optimistically wire the page in the vm (cheap). If it's present then 
you can just use the direct map to access it. However, if it's not 
present, then fall back to another  method, or maybe just fault it in 
(which will have to happen anyhow) and then retry.


Sounds like a cool project!

-Alfred
Oh, one other thing.. look at the pipe code.  It used to do what you 
suggest, I think however it was driven by the READER pinning the 
WRITER's address space and doing a direct copy.  However it may not be 
optimized for NOT-mapping into kva as I suggested doing.


-Alfred
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org


Re: copyin+copyout in one step ?

2013-05-27 Thread Konstantin Belousov
On Tue, May 28, 2013 at 01:38:01AM +0200, Luigi Rizzo wrote:
 Hi,
 say a process P1 wants to use the kernel to copy the content of a
 buffer SRC (in its user address space) to a buffer DST (in the
 address space of another process P2), and assume that P1 issues the
 request to the kernel when P2 has already told the kernel where the
 data should go:
 
  P1P2
 +--+ ++
 | SRC  | | DST|
 +--v---+ +--^-+
||--
||kernel
|^
 
||
|  ++|
+-| tmpbuf ++
 copyin|| copyout
 P1 ctx++  P2 ctx
 
 I guess the one above is the canonical way: P1 does a copyin() to a
 temporary buffer, then notifies P2 which can then issue or complete
 a syscall to do a copyout from tmpbuf to DST in P2's context.
 
 
 But I wonder, is it possible to do it as follows: P2 tells the kernel
 where the data should go (DST); later, P1 issues a system call and
 through a combined copyinout() moves data directly from SRC to DST,
 operating in the context of P1.
 
|  copyinout() ? | 
+---+
issued by P1
 
 
 Is this doable at all ? I suspect that tell DST to the kernel
 might be especially expensive as it needs to pin the page
 so it is accessible while doing the syscall for P1 ?
 (the whole point for this optimization is saving the extra
 copy through the buffer, but it may be pointless if pinning
 the memory is more expensive than the copy)

Yes, it is doable.  If the copy can happen when either P1 or P2 are
active context, then proc_rwmem() already perform exactly what you
want.  The virtual address in the address space of the 'other process'
is specified as uio-uio_offset.  The iov specifies the region(s) for
the current process.

If you want to perform the copy from P1 to P2 while some other context
P3 is active, the same structure as proc_rwmem() would work, but you 
obviously would need to do vm_fault_hold() for both sides, and use
pmap_copy_pages() instead of uiomove_fromphys().

In either case, you get copy without temporal buffer, but the setup cost
could be non-trivial. You never know until measured.


pgpTQLn3fMXt7.pgp
Description: PGP signature


Re: copyin+copyout in one step ?

2013-05-27 Thread Zaphod Beeblebrox
On Mon, May 27, 2013 at 7:38 PM, Luigi Rizzo ri...@iet.unipi.it wrote:


 say a process P1 wants to use the kernel to copy the content of a
 buffer SRC (in its user address space) to a buffer DST (in the
 address space of another process P2), and assume that P1 issues the
 request to the kernel when P2 has already told the kernel where the
 data should go:


Urm... Isn't the use of shared memory the more obvious way to transfer data
between processes?  Am I missing some nuance?
___
freebsd-current@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to freebsd-current-unsubscr...@freebsd.org