auto import from //depot/cupcake/@135843
diff --git a/simulator/app/Shmem.cpp b/simulator/app/Shmem.cpp
new file mode 100644
index 0000000..4c619c2
--- /dev/null
+++ b/simulator/app/Shmem.cpp
@@ -0,0 +1,558 @@
+//
+// Copyright 2005 The Android Open Source Project
+//
+// Shared memory interface.
+//
+#include "Shmem.h"
+#include "utils/Log.h"
+
+#if defined(HAVE_MACOSX_IPC) || defined(HAVE_ANDROID_IPC)
+# include <sys/mman.h>
+# include <fcntl.h>
+# include <unistd.h>
+#elif defined(HAVE_SYSV_IPC)
+# include <sys/types.h>
+# include <sys/ipc.h>
+# include <sys/shm.h>
+#elif defined(HAVE_WIN32_IPC)
+# include <windows.h>
+#else
+# error "unknown shm config"
+#endif
+
+#include <errno.h>
+#include <assert.h>
+
+using namespace android;
+
+
+#if defined(HAVE_MACOSX_IPC) || defined(HAVE_ANDROID_IPC)
+
+/*
+ * SysV IPC under Mac OS X seems to have problems. It works fine on
+ * some machines but totally fails on others. We're working around it
+ * here by using mmap().
+ */
+
+#define kInvalidHandle ((unsigned long)-1)
+
+static const char* kShmemFile = "/tmp/android-";
+
+/*
+ * Constructor. Just set up the fields.
+ */
+Shmem::Shmem(void)
+ : mHandle(kInvalidHandle), mAddr(MAP_FAILED), mLength(-1), mCreator(false),
+ mKey(-1)
+{
+}
+
+/*
+ * Destructor. Detach and, if we created it, mark the segment for
+ * destruction.
+ */
+Shmem::~Shmem(void)
+{
+ if (mAddr != MAP_FAILED)
+ munmap(mAddr, mLength);
+ if ((long)mHandle >= 0) {
+ close(mHandle);
+
+ if (mCreator) {
+ char nameBuf[64];
+ int cc;
+
+ snprintf(nameBuf, sizeof(nameBuf), "%s%d", kShmemFile, mKey);
+ cc = unlink(nameBuf);
+ if (cc != 0) {
+ LOG(LOG_WARN, "shmem", "Couldn't clean up '%s'\n", nameBuf);
+ /* oh well */
+ }
+ }
+ }
+}
+
+/*
+ * Create the segment and attach ourselves to it.
+ */
+bool Shmem::create(int key, long size, bool deleteExisting)
+{
+ char nameBuf[64];
+ int fd, cc;
+
+ snprintf(nameBuf, sizeof(nameBuf), "%s%d", kShmemFile, key);
+
+ if (deleteExisting) {
+ cc = unlink(nameBuf);
+ if (cc != 0 && errno != ENOENT) {
+ LOG(LOG_ERROR, "shmem", "Failed to remove old map file '%s'\n",
+ nameBuf);
+ return false;
+ }
+ }
+
+ fd = open(nameBuf, O_CREAT|O_EXCL|O_RDWR, 0600);
+ if (fd < 0) {
+ LOG(LOG_ERROR, "shmem", "Unable to create map file '%s' (errno=%d)\n",
+ nameBuf, errno);
+ return false;
+ }
+
+ /*
+ * Set the file size by seeking and writing.
+ */
+ if (ftruncate(fd, size) == -1) {
+ LOG(LOG_ERROR, "shmem", "Unable to set file size in '%s' (errno=%d)\n",
+ nameBuf, errno);
+ close(fd);
+ return false;
+ }
+
+ mAddr = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mAddr == MAP_FAILED) {
+ LOG(LOG_ERROR, "shmem", "mmap failed (errno=%d)\n", errno);
+ close(fd);
+ return false;
+ }
+
+ mHandle = fd;
+ mLength = size;
+ mCreator = true;
+ mKey = key;
+
+ /* done with shmem, create the associated semaphore */
+ if (!mSem.create(key, 1, true)) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed creating semaphore for Shmem (key=%d)\n", key);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Attach ourselves to an existing segment.
+ */
+bool Shmem::attach(int key)
+{
+ char nameBuf[64];
+ int fd;
+
+ snprintf(nameBuf, sizeof(nameBuf), "%s%d", kShmemFile, key);
+ fd = open(nameBuf, O_RDWR, 0600);
+ if (fd < 0) {
+ LOG(LOG_ERROR, "shmem", "Unable to open map file '%s' (errno=%d)\n",
+ nameBuf, errno);
+ return false;
+ }
+
+ off_t len;
+ len = lseek(fd, 0, SEEK_END);
+ if (len == (off_t) -1) {
+ LOG(LOG_ERROR, "shmem",
+ "Could not determine file size of '%s' (errno=%d)\n",
+ nameBuf, errno);
+ close(fd);
+ return false;
+ }
+
+ mAddr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (mAddr == MAP_FAILED) {
+ LOG(LOG_ERROR, "shmem", "mmap failed (errno=%d)\n", errno);
+ close(fd);
+ return false;
+ }
+
+ mHandle = fd;
+ mLength = len;
+ assert(mCreator == false);
+ mKey = key;
+
+ /* done with shmem, attach to associated semaphore */
+ if (!mSem.attach(key)) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed to attach to semaphore for Shmem (key=%d)\n", key);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Get address.
+ */
+void* Shmem::getAddr(void)
+{
+ assert(mAddr != MAP_FAILED);
+ return mAddr;
+}
+
+/*
+ * Return the length of the segment.
+ *
+ * Returns -1 on failure.
+ */
+long Shmem::getLength(void)
+{
+ if (mLength >= 0)
+ return mLength;
+
+ // we should always have it by now
+ assert(false);
+ return -1;
+}
+
+
+#elif defined(HAVE_SYSV_IPC) // ----------------------------------------------
+
+/*
+ * SysV-style IPC. The SysV shared memory API is fairly annoying to
+ * deal with, but it's present on many UNIX-like systems.
+ */
+
+#define kInvalidHandle ((unsigned long)-1)
+
+/*
+ * Constructor. Just set up the fields.
+ */
+Shmem::Shmem(void)
+ : mHandle(kInvalidHandle), mAddr(NULL), mLength(-1), mCreator(false),
+ mKey(-1)
+{
+}
+
+/*
+ * Destructor. Detach and, if we created it, mark the segment for
+ * destruction.
+ */
+Shmem::~Shmem(void)
+{
+ int cc;
+
+ //LOG(LOG_DEBUG, "shmem", "~Shmem(handle=%ld creator=%d)",
+ // mHandle, mCreator);
+
+ if (mAddr != NULL)
+ cc = shmdt(mAddr);
+
+ if (mCreator && mHandle != kInvalidHandle) {
+ cc = shmctl((int) mHandle, IPC_RMID, NULL);
+ if (cc != 0) {
+ LOG(LOG_WARN, "shmem",
+ "Destructor failed to remove shmid=%ld (errno=%d)\n",
+ mHandle, errno);
+ }
+ }
+}
+
+/*
+ * Create the segment and attach ourselves to it.
+ */
+bool Shmem::create(int key, long size, bool deleteExisting)
+{
+ int shmid, cc;
+
+ if (deleteExisting) {
+ shmid = shmget(key, size, 0);
+ if (shmid != -1) {
+ LOG(LOG_DEBUG, "shmem",
+ "Key %d exists (shmid=%d), marking for destroy", key, shmid);
+ cc = shmctl(shmid, IPC_RMID, NULL);
+ if (cc != 0) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed to remove key=%d shmid=%d (errno=%d)\n",
+ key, shmid, errno);
+ return false; // IPC_CREAT | IPC_EXCL will fail, so bail now
+ } else {
+ LOG(LOG_DEBUG, "shmem",
+ "Removed previous segment with key=%d\n", key);
+ }
+ }
+ }
+
+ shmid = shmget(key, size, 0600 | IPC_CREAT | IPC_EXCL);
+ if (shmid == -1) {
+ LOG(LOG_ERROR, "shmem", "Failed to create key=%d (errno=%d)\n",
+ key, errno);
+ return false;
+ }
+
+ mHandle = shmid;
+ mCreator = true;
+ mKey = key;
+
+ void* addr = shmat(shmid, NULL, 0);
+ if (addr == (void*) -1) {
+ LOG(LOG_ERROR, "shmem",
+ "Could not attach to key=%d shmid=%d (errno=%d)\n",
+ key, shmid, errno);
+ return false;
+ }
+
+ mAddr = addr;
+ mLength = size;
+
+ /* done with shmem, create the associated semaphore */
+ if (!mSem.create(key, 1, true)) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed creating semaphore for Shmem (key=%d)\n", key);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Attach ourselves to an existing segment.
+ */
+bool Shmem::attach(int key)
+{
+ int shmid;
+
+ shmid = shmget(key, 0, 0);
+ if (shmid == -1) {
+ LOG(LOG_ERROR, "shmem", "Failed to find key=%d\n", key);
+ return false;
+ }
+
+ mHandle = shmid;
+ assert(mCreator == false);
+ mKey = key;
+
+ void* addr = shmat(shmid, NULL, 0);
+ if (addr == (void*) -1) {
+ LOG(LOG_ERROR, "shmem", "Could not attach to key=%d shmid=%d\n",
+ key, shmid);
+ return false;
+ }
+
+ mAddr = addr;
+
+ /* done with shmem, attach to associated semaphore */
+ if (!mSem.attach(key)) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed to attach to semaphore for Shmem (key=%d)\n", key);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Get address.
+ */
+void* Shmem::getAddr(void)
+{
+ assert(mAddr != NULL);
+ return mAddr;
+}
+
+/*
+ * Return the length of the segment.
+ *
+ * Returns -1 on failure.
+ */
+long Shmem::getLength(void)
+{
+ if (mLength >= 0)
+ return mLength;
+
+ assert(mHandle != kInvalidHandle);
+
+ struct shmid_ds shmids;
+ int cc;
+
+ cc = shmctl((int) mHandle, IPC_STAT, &shmids);
+ if (cc != 0) {
+ LOG(LOG_ERROR, "shmem", "Could not IPC_STAT shmid=%ld\n", mHandle);
+ return -1;
+ }
+ mLength = shmids.shm_segsz; // save a copy to avoid future lookups
+
+ return mLength;
+}
+
+
+#elif defined(HAVE_WIN32_IPC) // ---------------------------------------------
+
+/*
+ * Win32 shared memory implementation.
+ *
+ * Shared memory is implemented as an "anonymous" file mapping, using the
+ * memory-mapped I/O interfaces.
+ */
+
+static const char* kShmemStr = "android-shmem-";
+
+/*
+ * Constructor. Just set up the fields.
+ */
+Shmem::Shmem(void)
+ : mHandle((unsigned long) INVALID_HANDLE_VALUE),
+ mAddr(NULL), mLength(-1), mCreator(false), mKey(-1)
+{
+}
+
+/*
+ * Destructor. The Win32 API doesn't require a distinction between
+ * the "creator" and other mappers.
+ */
+Shmem::~Shmem(void)
+{
+ LOG(LOG_DEBUG, "shmem", "~Shmem(handle=%ld creator=%d)",
+ mHandle, mCreator);
+
+ if (mAddr != NULL)
+ UnmapViewOfFile(mAddr);
+ if (mHandle != (unsigned long) INVALID_HANDLE_VALUE)
+ CloseHandle((HANDLE) mHandle);
+}
+
+/*
+ * Create the segment and map it.
+ */
+bool Shmem::create(int key, long size, bool deleteExisting)
+{
+ char keyBuf[64];
+ HANDLE hMapFile;
+
+ snprintf(keyBuf, sizeof(keyBuf), "%s%d", kShmemStr, key);
+
+ hMapFile = CreateFileMapping(
+ INVALID_HANDLE_VALUE, // use paging file, not actual file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // max size; no need to cap
+ size, // min size
+ keyBuf); // mapping name
+ if (hMapFile == NULL || hMapFile == INVALID_HANDLE_VALUE) {
+ LOG(LOG_ERROR, "shmem",
+ "Could not create mapping object '%s' (err=%ld)\n",
+ keyBuf, GetLastError());
+ return false;
+ }
+
+ mHandle = (unsigned long) hMapFile;
+ mCreator = true;
+ mKey = key;
+
+ mAddr = MapViewOfFile(
+ hMapFile, // handle to map object
+ FILE_MAP_ALL_ACCESS, // read/write
+ 0, // offset (hi)
+ 0, // offset (lo)
+ size); // #of bytes to map
+ if (mAddr == NULL) {
+ LOG(LOG_ERROR, "shmem", "Could not map shared area (err=%ld)\n",
+ GetLastError());
+ return false;
+ }
+ mLength = size;
+
+ /* done with shmem, create the associated semaphore */
+ if (!mSem.create(key, 1, true)) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed creating semaphore for Shmem (key=%d)\n", key);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Attach ourselves to an existing segment.
+ */
+bool Shmem::attach(int key)
+{
+ char keyBuf[64];
+ HANDLE hMapFile;
+
+ snprintf(keyBuf, sizeof(keyBuf), "%s%d", kShmemStr, key);
+
+ hMapFile = OpenFileMapping(
+ FILE_MAP_ALL_ACCESS, // read/write
+ FALSE, // don't let kids inherit handle
+ keyBuf); // mapping name
+ if (hMapFile == NULL) {
+ LOG(LOG_ERROR, "shmem",
+ "Could not open mapping object '%s' (err=%ld)\n",
+ keyBuf, GetLastError());
+ return false;
+ }
+
+ mHandle = (unsigned long) hMapFile;
+ assert(mCreator == false);
+ mKey = key;
+
+ mAddr = MapViewOfFile(
+ hMapFile, // handle to map object
+ FILE_MAP_ALL_ACCESS, // read/write
+ 0, // offset (hi)
+ 0, // offset (lo)
+ 0); // #of bytes to map
+ if (mAddr == NULL) {
+ LOG(LOG_ERROR, "shmem", "Could not map shared area (err=%ld)\n",
+ GetLastError());
+ return false;
+ }
+
+ /* done with shmem, attach to associated semaphore */
+ if (!mSem.attach(key)) {
+ LOG(LOG_ERROR, "shmem",
+ "Failed to attach to semaphore for Shmem (key=%d)\n", key);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Get address.
+ */
+void* Shmem::getAddr(void)
+{
+ assert(mAddr != NULL);
+ return mAddr;
+}
+
+/*
+ * Get the length of the segment.
+ */
+long Shmem::getLength(void)
+{
+ SIZE_T size;
+ MEMORY_BASIC_INFORMATION mbInfo;
+
+ if (mLength >= 0)
+ return mLength;
+
+ assert(mAddr != NULL);
+
+ size = VirtualQuery(mAddr, &mbInfo, sizeof(mbInfo));
+ if (size == 0) {
+ LOG(LOG_WARN, "shmem", "VirtualQuery returned no data\n");
+ return -1;
+ }
+
+ mLength = mbInfo.RegionSize;
+ return mLength;
+}
+
+#endif // --------------------------------------------------------------------
+
+/*
+ * Semaphore operations.
+ */
+void Shmem::lock(void)
+{
+ mSem.acquire();
+}
+void Shmem::unlock(void)
+{
+ mSem.release();
+}
+bool Shmem::tryLock(void)
+{
+ return mSem.tryAcquire();
+}
+