Bug 594878, part 2: Add a SharedMemoryBasic impl that uses /dev/ashmem on android. r=mwu
authorChris Jones <jones.chris.g@gmail.com>
Fri, 10 Sep 2010 16:45:59 -0500
changeset 54094 888afabb303c1fcc4f21810d3f0a061b2b582b47
parent 54093 043bef95ecd009da19b8af14809964d502674643
child 54095 173e878ad96a842e5baf0e9aec488afdffae156a
push id15768
push userdougt@mozilla.com
push dateThu, 16 Sep 2010 01:40:23 +0000
treeherdermozilla-central@cdb90b48f19f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu
bugs594878
milestone2.0b6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 594878, part 2: Add a SharedMemoryBasic impl that uses /dev/ashmem on android. r=mwu
ipc/glue/Makefile.in
ipc/glue/SharedMemoryBasic.h
ipc/glue/SharedMemoryBasic_android.cpp
ipc/glue/SharedMemoryBasic_android.h
--- a/ipc/glue/Makefile.in
+++ b/ipc/glue/Makefile.in
@@ -65,16 +65,25 @@ EXPORTS_mozilla/ipc = \
   SharedMemoryBasic.h \
   SharedMemoryBasic_chromium.h \
   SharedMemorySysV.h \
   Shmem.h \
   SyncChannel.h \
   ScopedXREEmbed.h \
   $(NULL)
 
+ifeq ($(OS_TARGET),Android)
+# Android has its own,
+# almost-but-not-quite-compatible-with-POSIX-or-/dev/shm shared memory
+# impl.
+EXPORTS_mozilla/ipc += SharedMemoryBasic_android.h
+else
+EXPORTS_mozilla/ipc += SharedMemoryBasic_chromium.h
+endif #}
+
 ENABLE_CXX_EXCEPTIONS = 1
 
 CPPSRCS += \
   AsyncChannel.cpp \
   BrowserProcessSubThread.cpp \
   GeckoChildProcessHost.cpp \
   MessagePump.cpp \
   ProcessChild.cpp \
@@ -86,19 +95,24 @@ CPPSRCS += \
   $(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 CPPSRCS += \
   SharedMemory_windows.cpp \
   WindowsMessageLoop.cpp \
   $(NULL)
 else
+# This generic code works on android.
 CPPSRCS += SharedMemory_posix.cpp
 endif
 
+ifeq ($(OS_TARGET),Android)
+CPPSRCS += SharedMemoryBasic_android.cpp
+endif #}
+
 include $(topsrcdir)/ipc/app/defs.mk
 DEFINES += -DMOZ_CHILD_PROCESS_NAME=\"$(MOZ_CHILD_PROCESS_NAME)\"
 DEFINES += -DMOZ_CHILD_PROCESS_BUNDLE=\"$(MOZ_CHILD_PROCESS_BUNDLE)\"
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 include $(topsrcdir)/config/rules.mk
--- a/ipc/glue/SharedMemoryBasic.h
+++ b/ipc/glue/SharedMemoryBasic.h
@@ -36,11 +36,15 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_ipc_SharedMemoryBasic_h
 #define mozilla_ipc_SharedMemoryBasic_h
 
-#include "mozilla/ipc/SharedMemoryBasic_chromium.h"
+#ifdef ANDROID
+#  include "mozilla/ipc/SharedMemoryBasic_android.h"
+#else
+#  include "mozilla/ipc/SharedMemoryBasic_chromium.h"
+#endif
 
 #endif // ifndef mozilla_ipc_SharedMemoryBasic_h
new file mode 100644
--- /dev/null
+++ b/ipc/glue/SharedMemoryBasic_android.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <android/log.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/process_util.h"
+
+#include "SharedMemoryBasic.h"
+
+//
+// Temporarily go directly to the kernel interface until we can
+// interact better with libcutils.
+//
+#define ASHMEM_DEVICE  		"/dev/ashmem"
+#define ASHMEM_NAME_LEN		256
+#define __ASHMEMIOC 0x77
+#define ASHMEM_SET_NAME		_IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
+#define ASHMEM_GET_NAME		_IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
+#define ASHMEM_SET_SIZE		_IOW(__ASHMEMIOC, 3, size_t)
+#define ASHMEM_GET_SIZE		_IO(__ASHMEMIOC, 4)
+#define ASHMEM_SET_PROT_MASK	_IOW(__ASHMEMIOC, 5, unsigned long)
+#define ASHMEM_GET_PROT_MASK	_IO(__ASHMEMIOC, 6)
+
+namespace mozilla {
+namespace ipc {
+
+static void
+LogError(const char* what)
+{
+  __android_log_print(ANDROID_LOG_ERROR, "Gecko",
+                      "%s: %s (%d)", what, strerror(errno), errno);
+}
+
+SharedMemoryBasic::SharedMemoryBasic()
+  : mShmFd(-1)
+  , mSize(0)
+  , mMemory(nsnull)
+{ }
+
+SharedMemoryBasic::SharedMemoryBasic(const Handle& aHandle)
+  : mShmFd(aHandle.fd)
+  , mSize(0)
+  , mMemory(nsnull)
+{ }
+
+SharedMemoryBasic::~SharedMemoryBasic()
+{
+  Unmap();
+  if (mShmFd > 0) {
+    close(mShmFd);
+  }
+}
+
+bool
+SharedMemoryBasic::Create(size_t aNbytes)
+{
+  NS_ABORT_IF_FALSE(-1 == mShmFd, "Already Create()d");
+
+  // Carve a new instance off of /dev/ashmem
+  int shmfd = open(ASHMEM_DEVICE, O_RDWR, 0600);
+  if (-1 == shmfd) {
+    LogError("ShmemAndroid::Create():open");
+    return false;
+  }
+
+  if (ioctl(shmfd, ASHMEM_SET_SIZE, aNbytes)) {
+    LogError("ShmemAndroid::Unmap():ioctl(SET_SIZE)");
+    close(shmfd);
+    return false;
+  }
+
+  mShmFd = shmfd;
+  return true;
+}
+
+bool
+SharedMemoryBasic::Map(size_t nBytes)
+{
+  NS_ABORT_IF_FALSE(nsnull == mMemory, "Already Map()d");
+
+  mMemory = mmap(nsnull, nBytes,
+                 PROT_READ | PROT_WRITE,
+                 MAP_SHARED,
+                 mShmFd,
+                 0);
+  if (MAP_FAILED == mMemory) {
+    LogError("ShmemAndroid::Map()");
+    mMemory = nsnull;
+    return false;
+  }
+
+  mSize = nBytes;
+  return true;
+}
+
+bool
+SharedMemoryBasic::ShareToProcess(base::ProcessHandle/*unused*/,
+                                  Handle* aNewHandle)
+{
+  NS_ABORT_IF_FALSE(mShmFd >= 0, "Should have been Create()d by now");
+
+  int shmfdDup = dup(mShmFd);
+  if (-1 == shmfdDup) {
+    LogError("ShmemAndroid::ShareToProcess()");
+    return false;
+  }
+
+  aNewHandle->fd = shmfdDup;
+  aNewHandle->auto_close = true;
+  return true;
+}
+
+void
+SharedMemoryBasic::Unmap()
+{
+  if (!mMemory) {
+    return;
+  }
+
+  if (munmap(mMemory, mSize)) {
+    LogError("ShmemAndroid::Unmap()");
+  }
+  mMemory = nsnull;
+  mSize = 0;
+}
+
+} // namespace ipc
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/glue/SharedMemoryBasic_android.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at:
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   The Mozilla Foundation
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chris Jones <jones.chris.g@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_ipc_SharedMemoryBasic_android_h
+#define mozilla_ipc_SharedMemoryBasic_android_h
+
+#include "base/file_descriptor_posix.h"
+
+#include "SharedMemory.h"
+
+//
+// This is a low-level wrapper around platform shared memory.  Don't
+// use it directly; use Shmem allocated through IPDL interfaces.
+//
+
+namespace mozilla {
+namespace ipc {
+
+class SharedMemoryBasic : public SharedMemory
+{
+public:
+  typedef base::FileDescriptor Handle;
+
+  SharedMemoryBasic();
+
+  SharedMemoryBasic(const Handle& aHandle);
+
+  virtual ~SharedMemoryBasic();
+
+  NS_OVERRIDE
+  virtual bool Create(size_t aNbytes);
+
+  NS_OVERRIDE
+  virtual bool Map(size_t nBytes);
+
+  NS_OVERRIDE
+  virtual size_t Size() const
+  {
+    return mSize;
+  }
+
+  NS_OVERRIDE
+  virtual void* memory() const
+  {
+    return mMemory;
+  }
+
+  NS_OVERRIDE
+  virtual SharedMemoryType Type() const
+  {
+    return TYPE_BASIC;
+  }
+
+  static Handle NULLHandle()
+  {
+    return Handle();
+  }
+
+  static bool IsHandleValid(const Handle &aHandle)
+  {
+    return aHandle.fd >= 0;
+  }
+
+  bool ShareToProcess(base::ProcessHandle aProcess,
+                      Handle* aNewHandle);
+
+private:
+  void Unmap();
+
+  // The /dev/ashmem fd we allocate.
+  int mShmFd;
+  // Mapped size, 0 if unmapped.
+  size_t mSize;
+  // Pointer to mapped region, null if unmapped.
+  void *mMemory;
+};
+
+} // namespace ipc
+} // namespace mozilla
+
+#endif // ifndef mozilla_ipc_SharedMemoryBasic_android_h