https://bugs.winehq.org/show_bug.cgi?id=37355
Richard Yao ryao@gentoo.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |ryao@gentoo.org
--- Comment #20 from Richard Yao ryao@gentoo.org ---
The problem is that there is no way to properly implement this on Linux since there is no way to simply map the memory of a different process if you are not inside the kernel. Since wine is no kernel module it can only use memory of different processes, when they explicitly create it as shared memory block. Sadly you can not declare a memory block as shared after it was allocated, so this does not help implementing this command.
Are you sure?
The way that I see it, if we can insert code into the other process in advance that we can trigger forassistance, this is doable.
1. Our “kernel” process somehow pings the other process. Then it attaches ptrace, saves the registers and request information to a predetermined place in memory and changes the instruction pointer to jump into an pseudo-interrupt handler. It resumes that process and then blocks on hearing back from the other process. 2. The other process’ pseudo-interrupt handler will create an anonymous file, either by making a file and unlinking it or by using O_TMPFILE. The file will be set to the size of the memory region being mapped via ftruncate(). This is then mapped into the address space using mmap(). The memory in the existing region is then copied. The handler now does mmap() the anonymous file into the correct position while calling unmap() on the previous mapping. Finally, it sends the file descriptor to the “kernel” process (via the wine server, a named pipe, whatever). 3. The “kernel” process the calls mmap() on the file descriptor. We have now mapped the region into the process.
I am not well versed in wine’s architecture, but this would achieve shared memory. The caveat being that you are not sharing the existing pages, but making new ones. If multiple processes are sharing the same pages, then we would need help from the wine server in keeping track of who has what mapped where and triggering the interrupt handlers in all processes that are sharing memory that is being mapped somewhere to remap it using a new copy. They also all would need to be paused.
This definitively becomes more complicated than that when you consider other corner cases, like what happens if we have a race where multiple “kernel threads” try to do this at the same time, but the general idea ought to work. Also, I said to use an anonymous file rather than POSIX shared memory to avoid having to keep track of the shared memory objects, but I suppose that if the wineserver is tracking things for the case of multiple processes sharing the same memory having this call done on that memory, then it could also keep track of shared memory objects so that processes using them will be told to properly free them should the mapping disappear so that we don’t risk leaking memory with long running processes.