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 idunknown
push userunknown
push dateunknown
reviewersmwu
bugs594878
milestone2.0b6pre
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