On Thu, Apr 21, 2011 at 5:55 AM, Marcus Lorentzon < marcus.xm.lorentzon@stericsson.com> wrote:
On 04/21/2011 02:15 PM, Arnd Bergmann wrote:
On Wednesday 20 April 2011, Marcus Lorentzon wrote:
On 04/20/2011 06:19 PM, Arnd Bergmann wrote:
File descriptors have a number of very nice properties that we can use:
- Efficient lookup in system calls
If both use the idr I don't see how fds are faster than ints.
File descriptors don't use idr.
My mistake, but still, ints could use an array too, and idr or lookup in general should not be an efficiency problem anyway.
- Established ways to pass them around
What could be easier than passing an int? I just don't like the "feature" of passing fds where they are dup-ed without driver knowing so. If you want to store process specific info associated with the fd you have to use a list since you don't know if the app sends the fd to another process. Probably not a big deal, but I don't like it ;)
The problem with passing an integer is that it doesn't have any concept of ownership or lifetime rules.
The idea of passing global ids should not affect lifetime. These ints are still lifetime controlled by the "fd" device that created them. So I think they do have a defined lifetime, that of whatever device this int is registered in. And if the process is shut down, all buffers registered in the drm/v4l2 device fd will be released and even freed if it was the last ref. And if you mean lifetime while process is still alive, even fds has to be closed, and ints has to be closed/unregistered using ioctl. And this is not something that is used by applications either, these refs and allocs are handled by the user space drivers, like libEGL / libGL / X-drivers etc, so ioctl vs. close should not matter.
The problem isn't managing their lifetime in the side that created the buffer, it's managing it while they are in flight. What happens if process 1 passes a buffer to process 2 and before process 2 takes a reference to it, process 1 crashes? Some central clearing house has to handle that. I'm guessing that's the X server in the X case. In my proposal that's handled by the extra reference being held by the passed fd itself (ie the kernel has a reference as long as the file struct exists in either processes file descriptor table).
If you allow any process access to all integers, a malicious process
might be able to guess it unless you use long cryptographic random numbers.
That's why you put a security model on top. Like GEM auth (which only have access all or nothing) or something like HWMEM where each buffer/id has read/write/import rights per process. This is also easier to trace/debug security since driver is notified when a buffer is transfered to another process. You never get this info from binder/pipe (dup-ed).
It's totally trivial to have debug info on what buffers are currently mapped into what processes. The kernel knows where all the memory manager's file descriptors have gone. This is already implemented in the proposal I posted. From userspace security becomes really simple, a process owns all the buffers it's created and any that have been shared with it. If it doesn't want to share a buffer with another process, it doesn't pass it to it.
When you have a file descriptor, you can assume that the object
is still alive until you close it. With an integer passed by some other application, that is less clear.
That's why I prefer the register/import global id step with device. It gives the driver a chance to store meta data and prepare to use this buffer. If this has to be done for every device ioctl call, you loose efficiency and all device APIs would have to be updated with cloned ops for fds. Register/import an fd/globalid and then use device local handles is much more efficient and don't require API changes, only additions.
That's exactly what I'm proposing, you import an fd that's been passed to you.
- Allows arbitrary subsystems to create compatible handles. Like a
socket can be provided by unrelated subsystems, this file handle could be created by any of GEM, v4l, tmpfs, ... and we can have operations that each of them provides as callbacks
Global ids should also be "compatible", since they are from the same name space. But what do you mean by callbacks? In kernel API on buffer objects? If so, idr_find(ID)->buffer_struct->callback() should be similar to idr_find(FD)->file_struct->callback()
In the idr example, the modules all need to link to the code that provides does the DEFINE_IDR(), in the file example, they only need to provide the same interfaces, so the modules need not link against any common code other than the VFS.
Not a major point though.
True, but I would prefer an in kernel API or callback ifc to do the "mem ops" like resolve.
Most of this can be seen in code @ http://git.linaro.org/gitweb?p=bsp/st-ericsson/linux-2.6.35-ux500.git%3Ba=tr.... But the idea is very close to GEM, actually we just needed a few lines of code in our KMS proto to use HWMEM in KMS & Wayland without changes to user space drm protocols and libs. But note that I'm not promoting HWMEM for unified mem driver, only showing some concepts that could be employed in GEM for use in Android & Wayland with common driver (I consider X "dead" in embedded ;).
/BR /Marcus
Linaro-mm-sig mailing list Linaro-mm-sig@lists.linaro.org http://lists.linaro.org/mailman/listinfo/linaro-mm-sig