Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: base/shared_memory_posix.cc

Issue 7184032: Upstream android file related code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/shared_memory.h" 5 #include "base/shared_memory.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <sys/mman.h> 9 #include <sys/mman.h>
10 #include <sys/stat.h> 10 #include <sys/stat.h>
11 #include <unistd.h> 11 #include <unistd.h>
12 12
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
16 #include "base/safe_strerror_posix.h" 16 #include "base/safe_strerror_posix.h"
17 #include "base/threading/thread_restrictions.h" 17 #include "base/threading/thread_restrictions.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 19
20 #if defined(OS_ANDROID)
21 // For Android, we use ashmem to implement SharedMemory. ashmem_create_region
22 // will automatically pin the region. We never explicitly call pin/unpin. When
23 // all the file descriptors from different processes associated with the region
24 // are closed, the memory buffer will go away.
25 #include "third_party/ashmem/ashmem.h"
26 #endif
27
20 #if defined(OS_MACOSX) 28 #if defined(OS_MACOSX)
21 #include "base/mac/foundation_util.h" 29 #include "base/mac/foundation_util.h"
22 #endif // OS_MACOSX 30 #endif // OS_MACOSX
23 31
24 namespace base { 32 namespace base {
25 33
26 namespace { 34 namespace {
27 // Paranoia. Semaphores and shared memory segments should live in different 35 // Paranoia. Semaphores and shared memory segments should live in different
28 // namespaces, but who knows what's out there. 36 // namespaces, but who knows what's out there.
29 const char kSemaphoreSuffix[] = "-sem"; 37 const char kSemaphoreSuffix[] = "-sem";
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 } 104 }
97 105
98 // Chromium mostly only uses the unique/private shmem as specified by 106 // Chromium mostly only uses the unique/private shmem as specified by
99 // "name == L"". The exception is in the StatsTable. 107 // "name == L"". The exception is in the StatsTable.
100 // TODO(jrg): there is no way to "clean up" all unused named shmem if 108 // TODO(jrg): there is no way to "clean up" all unused named shmem if
101 // we restart from a crash. (That isn't a new problem, but it is a problem.) 109 // we restart from a crash. (That isn't a new problem, but it is a problem.)
102 // In case we want to delete it later, it may be useful to save the value 110 // In case we want to delete it later, it may be useful to save the value
103 // of mem_filename after FilePathForMemoryName(). 111 // of mem_filename after FilePathForMemoryName().
104 bool SharedMemory::CreateNamed(const std::string& name, 112 bool SharedMemory::CreateNamed(const std::string& name,
105 bool open_existing, uint32 size) { 113 bool open_existing, uint32 size) {
114 #if defined(OS_ANDROID)
darin (slow to review) 2011/06/17 16:29:29 it seems like almost all of the code in this file
michaelbai 2011/06/17 22:41:29 I moved fully android specific methods into shared
115 DCHECK(mapped_file_ == -1);
joth 2011/06/17 11:25:54 DCHECK_EQ(-1, mapped_file_)
michaelbai 2011/06/17 22:41:29 Done.
116
117 // "name" is just a label in ashmem. It is visible in /proc/pid/maps.
118 mapped_file_ = ashmem_create_region(name.data(), size);
joth 2011/06/17 11:25:54 name.c_str(), to ensure it is null terminated
michaelbai 2011/06/17 22:41:29 Done, thanks
119 if (-1 == mapped_file_) {
120 LOG(ERROR) << "Shared memory creation failed";
darin (slow to review) 2011/06/17 16:29:29 nit: do you really need these log statements to be
michaelbai 2011/06/17 22:41:29 Done.
121 return false;
122 }
123
124 int err = ashmem_set_prot_region(mapped_file_,
125 PROT_READ | PROT_WRITE | PROT_EXEC);
126 if (err < 0) {
127 LOG(ERROR) << "Error " << err << " when setting protection of ashmem";
128 return false;
129 }
130 created_size_ = size;
131
132 return true;
133 #else
106 DCHECK_EQ(-1, mapped_file_); 134 DCHECK_EQ(-1, mapped_file_);
107 if (size == 0) return false; 135 if (size == 0) return false;
108 136
109 // This function theoretically can block on the disk, but realistically 137 // This function theoretically can block on the disk, but realistically
110 // the temporary files we create will just go into the buffer cache 138 // the temporary files we create will just go into the buffer cache
111 // and be deleted before they ever make it out to disk. 139 // and be deleted before they ever make it out to disk.
112 base::ThreadRestrictions::ScopedAllowIO allow_io; 140 base::ThreadRestrictions::ScopedAllowIO allow_io;
113 141
114 FILE *fp; 142 FILE *fp;
115 bool fix_size = true; 143 bool fix_size = true;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix."; 192 << "/dev/shm. Try 'sudo chmod 1777 /dev/shm' to fix.";
165 } 193 }
166 } 194 }
167 #else 195 #else
168 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; 196 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed";
169 #endif 197 #endif
170 return false; 198 return false;
171 } 199 }
172 200
173 return PrepareMapFile(fp); 201 return PrepareMapFile(fp);
202 #endif // defined(OS_ANDROID)
174 } 203 }
175 204
176 // Our current implementation of shmem is with mmap()ing of files. 205 // Our current implementation of shmem is with mmap()ing of files.
177 // These files need to be deleted explicitly. 206 // These files need to be deleted explicitly.
178 // In practice this call is only needed for unit tests. 207 // In practice this call is only needed for unit tests.
179 bool SharedMemory::Delete(const std::string& name) { 208 bool SharedMemory::Delete(const std::string& name) {
209 #if defined(OS_ANDROID)
210 // ashmem doesn't support name mapping
211 NOTIMPLEMENTED();
212 return false;
213 #endif
214
180 FilePath path; 215 FilePath path;
181 if (!FilePathForMemoryName(name, &path)) 216 if (!FilePathForMemoryName(name, &path))
182 return false; 217 return false;
183 218
184 if (file_util::PathExists(path)) { 219 if (file_util::PathExists(path)) {
185 return file_util::Delete(path, false); 220 return file_util::Delete(path, false);
186 } 221 }
187 222
188 // Doesn't exist, so success. 223 // Doesn't exist, so success.
189 return true; 224 return true;
190 } 225 }
191 226
192 bool SharedMemory::Open(const std::string& name, bool read_only) { 227 bool SharedMemory::Open(const std::string& name, bool read_only) {
193 FilePath path; 228 FilePath path;
194 if (!FilePathForMemoryName(name, &path)) 229 if (!FilePathForMemoryName(name, &path))
195 return false; 230 return false;
196 231
197 read_only_ = read_only; 232 read_only_ = read_only;
198 233
234 #if defined(OS_ANDROID)
235 // ashmem doesn't support name mapping
236 NOTIMPLEMENTED();
237 return false;
238 #endif
239
199 const char *mode = read_only ? "r" : "r+"; 240 const char *mode = read_only ? "r" : "r+";
200 FILE *fp = file_util::OpenFile(path, mode); 241 FILE *fp = file_util::OpenFile(path, mode);
201 return PrepareMapFile(fp); 242 return PrepareMapFile(fp);
202 } 243 }
203 244
204 bool SharedMemory::Map(uint32 bytes) { 245 bool SharedMemory::Map(uint32 bytes) {
205 if (mapped_file_ == -1) 246 if (mapped_file_ == -1)
206 return false; 247 return false;
207 248
249 #if defined(OS_ANDROID)
250 const uint32 ashmem_bytes = ashmem_get_size_region(mapped_file_);
joth 2011/06/17 11:25:54 ashmem_get_size_region appears to return 'int', pr
michaelbai 2011/06/17 22:41:29 Done.
251 DCHECK_GE(ashmem_bytes, bytes);
252 if (bytes == 0) {
253 // The caller wants to determine the map region size from ashmem.
254 bytes = ashmem_bytes;
255 // HACK: we set the created size here so that it is available in
256 // transport_dib_android.cc. Other choices would be to add an accessor to
257 // mapped_size_ (apparently undesirable, see the comment for created_size()
258 // in shared_memory.h) or to duplicate the ashmem_get_size_region call above
259 // in TransportDIB::Map().
joth 2011/06/17 11:25:54 can we fix this? It seems to be abusing both Map(0
michaelbai 2011/06/17 22:41:29 Method added, I will have another CL to handle the
260 created_size_ = bytes;
261 }
262 #endif
263
208 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), 264 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
209 MAP_SHARED, mapped_file_, 0); 265 MAP_SHARED, mapped_file_, 0);
210 266
211 if (memory_) 267 if (memory_)
212 mapped_size_ = bytes; 268 mapped_size_ = bytes;
213 269
214 bool mmap_succeeded = (memory_ != (void*)-1); 270 bool mmap_succeeded = (memory_ != (void*)-1);
215 DCHECK(mmap_succeeded) << "Call to mmap failed, errno=" << errno; 271 DCHECK(mmap_succeeded) << "Call to mmap failed, errno=" << errno;
216 return mmap_succeeded; 272 return mmap_succeeded;
217 } 273 }
(...skipping 15 matching lines...) Expand all
233 void SharedMemory::Close() { 289 void SharedMemory::Close() {
234 Unmap(); 290 Unmap();
235 291
236 if (mapped_file_ > 0) { 292 if (mapped_file_ > 0) {
237 if (HANDLE_EINTR(close(mapped_file_)) < 0) 293 if (HANDLE_EINTR(close(mapped_file_)) < 0)
238 PLOG(ERROR) << "close"; 294 PLOG(ERROR) << "close";
239 mapped_file_ = -1; 295 mapped_file_ = -1;
240 } 296 }
241 } 297 }
242 298
299 // The lockf() function is not available on Android; we translate to flock().
300 #if defined(OS_ANDROID)
301 #define F_LOCK LOCK_EX
302 #define F_ULOCK LOCK_UN
303 static inline int lockf(int fd, int cmd, off_t ignored_len) {
joth 2011/06/17 11:25:54 nit: use anon namespace rather than static (unless
michaelbai 2011/06/17 22:41:29 Done.
304 return flock(fd, cmd);
305 }
306 #endif
307
308
243 void SharedMemory::Lock() { 309 void SharedMemory::Lock() {
244 LockOrUnlockCommon(F_LOCK); 310 LockOrUnlockCommon(F_LOCK);
245 } 311 }
246 312
247 void SharedMemory::Unlock() { 313 void SharedMemory::Unlock() {
248 LockOrUnlockCommon(F_ULOCK); 314 LockOrUnlockCommon(F_ULOCK);
249 } 315 }
250 316
317 #if !defined(OS_ANDROID)
251 bool SharedMemory::PrepareMapFile(FILE *fp) { 318 bool SharedMemory::PrepareMapFile(FILE *fp) {
252 DCHECK_EQ(-1, mapped_file_); 319 DCHECK_EQ(-1, mapped_file_);
253 if (fp == NULL) return false; 320 if (fp == NULL) return false;
254 321
255 // This function theoretically can block on the disk, but realistically 322 // This function theoretically can block on the disk, but realistically
256 // the temporary files we create will just go into the buffer cache 323 // the temporary files we create will just go into the buffer cache
257 // and be deleted before they ever make it out to disk. 324 // and be deleted before they ever make it out to disk.
258 base::ThreadRestrictions::ScopedAllowIO allow_io; 325 base::ThreadRestrictions::ScopedAllowIO allow_io;
259 326
260 file_util::ScopedFILE file_closer(fp); 327 file_util::ScopedFILE file_closer(fp);
261 328
262 mapped_file_ = dup(fileno(fp)); 329 mapped_file_ = dup(fileno(fp));
263 if (mapped_file_ == -1) { 330 if (mapped_file_ == -1) {
264 if (errno == EMFILE) { 331 if (errno == EMFILE) {
265 LOG(WARNING) << "Shared memory creation failed; out of file descriptors"; 332 LOG(WARNING) << "Shared memory creation failed; out of file descriptors";
266 return false; 333 return false;
267 } else { 334 } else {
268 NOTREACHED() << "Call to dup failed, errno=" << errno; 335 NOTREACHED() << "Call to dup failed, errno=" << errno;
269 } 336 }
270 } 337 }
271 338
272 struct stat st; 339 struct stat st;
273 if (fstat(mapped_file_, &st)) 340 if (fstat(mapped_file_, &st))
274 NOTREACHED(); 341 NOTREACHED();
275 inode_ = st.st_ino; 342 inode_ = st.st_ino;
276 343
277 return true; 344 return true;
278 } 345 }
346 #endif
279 347
280 // For the given shmem named |mem_name|, return a filename to mmap() 348 // For the given shmem named |mem_name|, return a filename to mmap()
281 // (and possibly create). Modifies |filename|. Return false on 349 // (and possibly create). Modifies |filename|. Return false on
282 // error, or true of we are happy. 350 // error, or true of we are happy.
283 bool SharedMemory::FilePathForMemoryName(const std::string& mem_name, 351 bool SharedMemory::FilePathForMemoryName(const std::string& mem_name,
284 FilePath* path) { 352 FilePath* path) {
285 // mem_name will be used for a filename; make sure it doesn't 353 // mem_name will be used for a filename; make sure it doesn't
286 // contain anything which will confuse us. 354 // contain anything which will confuse us.
287 DCHECK_EQ(std::string::npos, mem_name.find('/')); 355 DCHECK_EQ(std::string::npos, mem_name.find('/'));
288 DCHECK_EQ(std::string::npos, mem_name.find('\0')); 356 DCHECK_EQ(std::string::npos, mem_name.find('\0'));
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 new_handle->fd = new_fd; 399 new_handle->fd = new_fd;
332 new_handle->auto_close = true; 400 new_handle->auto_close = true;
333 401
334 if (close_self) 402 if (close_self)
335 Close(); 403 Close();
336 404
337 return true; 405 return true;
338 } 406 }
339 407
340 } // namespace base 408 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698