From bdd1b89f072b1c371d57f1e54a6d9b2db8ce047b Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 10 Sep 2010 16:45:59 -0500 Subject: [PATCH] Bug 594878, part 2: Add a SharedMemoryBasic impl that uses /dev/ashmem on android. r=mwu --- ipc/glue/Makefile.in | 14 ++ ipc/glue/SharedMemoryBasic.h | 6 +- ipc/glue/SharedMemoryBasic_android.cpp | 173 +++++++++++++++++++++++++ ipc/glue/SharedMemoryBasic_android.h | 118 +++++++++++++++++ 4 files changed, 310 insertions(+), 1 deletion(-) create mode 100644 ipc/glue/SharedMemoryBasic_android.cpp create mode 100644 ipc/glue/SharedMemoryBasic_android.h diff --git a/ipc/glue/Makefile.in b/ipc/glue/Makefile.in index 9a068849283e..7db1933ea83b 100644 --- a/ipc/glue/Makefile.in +++ b/ipc/glue/Makefile.in @@ -70,6 +70,15 @@ EXPORTS_mozilla/ipc = \ 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 += \ @@ -91,9 +100,14 @@ CPPSRCS += \ 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)\" diff --git a/ipc/glue/SharedMemoryBasic.h b/ipc/glue/SharedMemoryBasic.h index f31431169a3f..5dff4602d690 100644 --- a/ipc/glue/SharedMemoryBasic.h +++ b/ipc/glue/SharedMemoryBasic.h @@ -41,6 +41,10 @@ #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 diff --git a/ipc/glue/SharedMemoryBasic_android.cpp b/ipc/glue/SharedMemoryBasic_android.cpp new file mode 100644 index 000000000000..6f457b107c41 --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 diff --git a/ipc/glue/SharedMemoryBasic_android.h b/ipc/glue/SharedMemoryBasic_android.h new file mode 100644 index 000000000000..846b815f3948 --- /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 + * + * 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