diff options
author | mcgrathr@chromium.org <mcgrathr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-16 21:58:37 +0000 |
---|---|---|
committer | mcgrathr@chromium.org <mcgrathr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-16 21:58:37 +0000 |
commit | c783bc5e9ec1b74e88cd716ec6566575903336db (patch) | |
tree | 09275730119346870722513a0a408ba8c5cda63e | |
parent | 5cba9ff723227ca847c8cb4186be45ea903f9794 (diff) | |
download | chromium_src-c783bc5e9ec1b74e88cd716ec6566575903336db.zip chromium_src-c783bc5e9ec1b74e88cd716ec6566575903336db.tar.gz chromium_src-c783bc5e9ec1b74e88cd716ec6566575903336db.tar.bz2 |
NaCl: preallocate shared-memory object on Linux as on MacOSX
Preallocating the shared memory object saves an IPC round trip.
It also makes the code path more similar for Linux and Mac.
It also lays the groundwork for changing the allocation method
later without having to replumb the proxying layer.
BUG= http://code.google.com/p/chromium/issues/detail?id=103377
TEST= nacl still works on Linux
R=mseaborn@chromium.org,jam@chromium.org
Review URL: http://codereview.chromium.org/8513018
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110361 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.cc | 10 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.cc | 70 |
2 files changed, 48 insertions, 32 deletions
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index d254d44..a119ec3 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -498,11 +498,11 @@ void NaClProcessHost::SendStart(base::PlatformFile irt_file) { return; } -#if defined(OS_MACOSX) - // For dynamic loading support, NaCl requires a file descriptor that - // was created in /tmp, since those created with shm_open() are not - // mappable with PROT_EXEC. Rather than requiring an extra IPC - // round trip out of the sandbox, we create an FD here. +#if defined(OS_POSIX) + // For dynamic loading support, NaCl requires a file descriptor on an + // anonymous file that can have PROT_EXEC applied to its mappings. + // Rather than requiring an extra IPC round trip out of the sandbox, + // we create an FD here. base::SharedMemory memory_buffer; if (!memory_buffer.CreateAnonymous(/* size= */ 1)) { LOG(ERROR) << "Failed to allocate memory buffer"; diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index 55f7e43..9141025 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -33,41 +33,59 @@ typedef HANDLE NaClHandle; typedef int NaClHandle; #endif // NaClHandle -#if defined(OS_MACOSX) +#if defined(OS_POSIX) namespace { -// On Mac OS X, shm_open() works in the sandbox but does not give us -// an FD that we can map as PROT_EXEC. Rather than doing an IPC to -// get an executable SHM region when CreateMemoryObject() is called, -// we preallocate one on startup, since NaCl's sel_ldr only needs one -// of them. This saves a round trip. +// On Mac OS X, shm_open() works in the sandbox but does not give us an FD +// that we can map as PROT_EXEC. On Linux, shm_open() can only be used +// outside the sandbox anyway. Rather than doing an IPC to get an +// executable SHM region when CreateMemoryObject() is called, we +// preallocate one on startup, since NaCl's sel_ldr only needs one of them. +// This saves a round trip. + +bool SetShmFdSize(int fd, size_t size) { +#if defined(OS_MACOSX) + // ftruncate() is disallowed by the Mac OS X sandbox and returns EPERM. + // Luckily, we can get the same effect with lseek() + write(). + if (lseek(fd, size - 1, SEEK_SET) == -1) { + LOG(ERROR) << "lseek() failed: " << errno; + close(fd); + return false; + } + if (write(fd, "", 1) != 1) { + LOG(ERROR) << "write() failed: " << errno; + close(fd); + return -1; + } +#else + if (ftruncate(fd, size) < 0) { + LOG(ERROR) << "ftruncate() failed: " << errno; + close(fd); + return false; + } +#endif // defined(OS_MACOSX) + return true; +} base::subtle::Atomic32 g_shm_fd = -1; int CreateMemoryObject(size_t size, bool executable) { if (executable && size > 0) { int result_fd = base::subtle::NoBarrier_AtomicExchange(&g_shm_fd, -1); - if (result_fd != -1) { - // ftruncate() is disallowed by the Mac OS X sandbox and - // returns EPERM. Luckily, we can get the same effect with - // lseek() + write(). - if (lseek(result_fd, size - 1, SEEK_SET) == -1) { - LOG(ERROR) << "lseek() failed: " << errno; - return -1; - } - if (write(result_fd, "", 1) != 1) { - LOG(ERROR) << "write() failed: " << errno; - return -1; - } + if (result_fd != -1 && SetShmFdSize(result_fd, size)) return result_fd; - } } +#if defined(OS_LINUX) + // Use the proxied implementation. It doesn't really support executability. + CHECK(!executable); + return content::MakeSharedMemorySegmentViaIPC(size, executable); +#endif // Fall back to NaCl's default implementation. return -1; } } // namespace -#endif // defined(OS_MACOSX) +#endif // defined(OS_POSIX) extern "C" void NaClMainForChromium(int handle_count, const NaClHandle* handles, @@ -97,17 +115,15 @@ bool NaClListener::OnMessageReceived(const IPC::Message& msg) { } void NaClListener::OnStartSelLdr(std::vector<nacl::FileDescriptor> handles) { -#if defined(OS_LINUX) - nacl::SetCreateMemoryObjectFunc(content::MakeSharedMemorySegmentViaIPC); -#elif defined(OS_MACOSX) +#if defined(OS_POSIX) nacl::SetCreateMemoryObjectFunc(CreateMemoryObject); - CHECK(handles.size() >= 1); - g_shm_fd = nacl::ToNativeHandle(handles[handles.size() - 1]); + CHECK(!handles.empty()); + g_shm_fd = nacl::ToNativeHandle(handles.back()); handles.pop_back(); #endif - CHECK(handles.size() >= 1); - NaClHandle irt_handle = nacl::ToNativeHandle(handles[handles.size() - 1]); + CHECK(!handles.empty()); + NaClHandle irt_handle = nacl::ToNativeHandle(handles.back()); handles.pop_back(); #if defined(OS_WIN) |