1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include <android/log.h>
8 #include <errno.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/mman.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16
17 #include "base/process_util.h"
18
19 #include "SharedMemoryBasic.h"
20
21 //
22 // Temporarily go directly to the kernel interface until we can
23 // interact better with libcutils.
24 //
25 #include <linux/ashmem.h>
26
27 namespace mozilla {
28 namespace ipc {
29
30 static void
LogError(const char * what)31 LogError(const char* what)
32 {
33 __android_log_print(ANDROID_LOG_ERROR, "Gecko",
34 "%s: %s (%d)", what, strerror(errno), errno);
35 }
36
SharedMemoryBasic()37 SharedMemoryBasic::SharedMemoryBasic()
38 : mShmFd(-1)
39 , mMemory(nullptr)
40 { }
41
~SharedMemoryBasic()42 SharedMemoryBasic::~SharedMemoryBasic()
43 {
44 Unmap();
45 CloseHandle();
46 }
47
48 bool
SetHandle(const Handle & aHandle)49 SharedMemoryBasic::SetHandle(const Handle& aHandle)
50 {
51 MOZ_ASSERT(-1 == mShmFd, "Already Create()d");
52 mShmFd = aHandle.fd;
53 return true;
54 }
55
56 bool
Create(size_t aNbytes)57 SharedMemoryBasic::Create(size_t aNbytes)
58 {
59 MOZ_ASSERT(-1 == mShmFd, "Already Create()d");
60
61 // Carve a new instance off of /dev/ashmem
62 int shmfd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600);
63 if (-1 == shmfd) {
64 LogError("ShmemAndroid::Create():open");
65 return false;
66 }
67
68 if (ioctl(shmfd, ASHMEM_SET_SIZE, aNbytes)) {
69 LogError("ShmemAndroid::Unmap():ioctl(SET_SIZE)");
70 close(shmfd);
71 return false;
72 }
73
74 mShmFd = shmfd;
75 Created(aNbytes);
76 return true;
77 }
78
79 bool
Map(size_t nBytes)80 SharedMemoryBasic::Map(size_t nBytes)
81 {
82 MOZ_ASSERT(nullptr == mMemory, "Already Map()d");
83
84 mMemory = mmap(nullptr, nBytes,
85 PROT_READ | PROT_WRITE,
86 MAP_SHARED,
87 mShmFd,
88 0);
89 if (MAP_FAILED == mMemory) {
90 LogError("ShmemAndroid::Map()");
91 mMemory = nullptr;
92 return false;
93 }
94
95 Mapped(nBytes);
96 return true;
97 }
98
99 bool
ShareToProcess(base::ProcessId,Handle * aNewHandle)100 SharedMemoryBasic::ShareToProcess(base::ProcessId/*unused*/,
101 Handle* aNewHandle)
102 {
103 MOZ_ASSERT(mShmFd >= 0, "Should have been Create()d by now");
104
105 int shmfdDup = dup(mShmFd);
106 if (-1 == shmfdDup) {
107 LogError("ShmemAndroid::ShareToProcess()");
108 return false;
109 }
110
111 aNewHandle->fd = shmfdDup;
112 aNewHandle->auto_close = true;
113 return true;
114 }
115
116 void
Unmap()117 SharedMemoryBasic::Unmap()
118 {
119 if (!mMemory) {
120 return;
121 }
122
123 if (munmap(mMemory, Size())) {
124 LogError("ShmemAndroid::Unmap()");
125 }
126 mMemory = nullptr;
127 }
128
129 void
CloseHandle()130 SharedMemoryBasic::CloseHandle()
131 {
132 if (mShmFd != -1) {
133 close(mShmFd);
134 mShmFd = -1;
135 }
136 }
137
138 } // namespace ipc
139 } // namespace mozilla
140