OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 | 10 |
11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/platform_thread.h" |
13 #include "base/string_util.h" | 14 #include "base/string_util.h" |
14 | 15 |
15 namespace base { | 16 namespace base { |
16 | 17 |
17 namespace { | 18 namespace { |
18 // Paranoia. Semaphores and shared memory segments should live in different | 19 // Paranoia. Semaphores and shared memory segments should live in different |
19 // namespaces, but who knows what's out there. | 20 // namespaces, but who knows what's out there. |
20 const char kSemaphoreSuffix[] = "-sem"; | 21 const char kSemaphoreSuffix[] = "-sem"; |
21 } | 22 } |
22 | 23 |
23 SharedMemory::SharedMemory() | 24 SharedMemory::SharedMemory() |
24 : mapped_file_(-1), | 25 : mapped_file_(-1), |
25 memory_(NULL), | 26 memory_(NULL), |
26 read_only_(false), | 27 read_only_(false), |
27 max_size_(0), | 28 max_size_(0) { |
28 lock_(NULL) { | |
29 } | 29 } |
30 | 30 |
31 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) | 31 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only) |
32 : mapped_file_(handle), | 32 : mapped_file_(handle), |
33 memory_(NULL), | 33 memory_(NULL), |
34 read_only_(read_only), | 34 read_only_(read_only), |
35 max_size_(0), | 35 max_size_(0) { |
36 lock_(NULL) { | |
37 } | 36 } |
38 | 37 |
39 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, | 38 SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only, |
40 ProcessHandle process) | 39 ProcessHandle process) |
41 : mapped_file_(handle), | 40 : mapped_file_(handle), |
42 memory_(NULL), | 41 memory_(NULL), |
43 read_only_(read_only), | 42 read_only_(read_only), |
44 max_size_(0), | 43 max_size_(0) { |
45 lock_(NULL) { | |
46 // We don't handle this case yet (note the ignored parameter); let's die if | 44 // We don't handle this case yet (note the ignored parameter); let's die if |
47 // someone comes calling. | 45 // someone comes calling. |
48 NOTREACHED(); | 46 NOTREACHED(); |
49 } | 47 } |
50 | 48 |
51 SharedMemory::~SharedMemory() { | 49 SharedMemory::~SharedMemory() { |
52 Close(); | 50 Close(); |
53 if (lock_ != NULL) | |
54 sem_close(lock_); | |
55 } | 51 } |
56 | 52 |
57 bool SharedMemory::Create(const std::wstring &name, bool read_only, | 53 bool SharedMemory::Create(const std::wstring &name, bool read_only, |
58 bool open_existing, size_t size) { | 54 bool open_existing, size_t size) { |
59 read_only_ = read_only; | 55 read_only_ = read_only; |
60 | 56 |
61 int posix_flags = 0; | 57 int posix_flags = 0; |
62 posix_flags |= read_only ? O_RDONLY : O_RDWR; | 58 posix_flags |= read_only ? O_RDONLY : O_RDWR; |
63 if (!open_existing || mapped_file_ <= 0) | 59 if (!open_existing || mapped_file_ <= 0) |
64 posix_flags |= O_CREAT; | 60 posix_flags |= O_CREAT; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 // possibly shrink. | 194 // possibly shrink. |
199 if ((ftruncate(fileno(fp), size) != 0) || | 195 if ((ftruncate(fileno(fp), size) != 0) || |
200 (fflush(fp) != 0)) { | 196 (fflush(fp) != 0)) { |
201 return false; | 197 return false; |
202 } | 198 } |
203 } | 199 } |
204 } | 200 } |
205 | 201 |
206 mapped_file_ = dup(fileno(fp)); | 202 mapped_file_ = dup(fileno(fp)); |
207 DCHECK(mapped_file_ >= 0); | 203 DCHECK(mapped_file_ >= 0); |
208 | |
209 mode_t posix_mode = S_IRUSR | S_IWUSR; // owner read/write | |
210 // name_ that includes a tmpdir easily exceeds SEM_NAME_LEN, | |
211 // so we cannot use it directly as the basis for a sem_name_. | |
212 sem_name_ = WideToUTF8(name) + kSemaphoreSuffix; | |
213 lock_ = sem_open(sem_name_.c_str(), O_CREAT, posix_mode, 1); | |
214 if (lock_ == SEM_FAILED) { | |
215 close(mapped_file_); | |
216 mapped_file_ = -1; | |
217 lock_ = NULL; | |
218 return false; | |
219 } | |
220 | |
221 return true; | 204 return true; |
222 } | 205 } |
223 | 206 |
224 bool SharedMemory::Map(size_t bytes) { | 207 bool SharedMemory::Map(size_t bytes) { |
225 if (mapped_file_ == -1) | 208 if (mapped_file_ == -1) |
226 return false; | 209 return false; |
227 | 210 |
228 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), | 211 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE), |
229 MAP_SHARED, mapped_file_, 0); | 212 MAP_SHARED, mapped_file_, 0); |
230 | 213 |
(...skipping 25 matching lines...) Expand all Loading... |
256 | 239 |
257 void SharedMemory::Close() { | 240 void SharedMemory::Close() { |
258 | 241 |
259 Unmap(); | 242 Unmap(); |
260 | 243 |
261 std::string posix_name(WideToUTF8(name_)); | 244 std::string posix_name(WideToUTF8(name_)); |
262 if (mapped_file_ > 0) { | 245 if (mapped_file_ > 0) { |
263 close(mapped_file_); | 246 close(mapped_file_); |
264 mapped_file_ = -1; | 247 mapped_file_ = -1; |
265 } | 248 } |
| 249 } |
266 | 250 |
267 if (lock_) { | 251 void SharedMemory::LockOrUnlockCommon(int function) { |
268 sem_unlink(sem_name_.c_str()); | 252 DCHECK(mapped_file_ >= 0); |
269 lock_ = NULL; | 253 while (lockf(mapped_file_, function, 0) < 0) { |
| 254 if (errno == EINTR) { |
| 255 continue; |
| 256 } else if (errno == ENOLCK) { |
| 257 // temporary kernel resource exaustion |
| 258 PlatformThread::Sleep(500); |
| 259 continue; |
| 260 } else { |
| 261 NOTREACHED() << "lockf() failed." |
| 262 << " function:" << function |
| 263 << " fd:" << mapped_file_ |
| 264 << " errno:" << errno |
| 265 << " msg:" << strerror(errno); |
| 266 } |
270 } | 267 } |
271 } | 268 } |
272 | 269 |
273 void SharedMemory::Lock() { | 270 void SharedMemory::Lock() { |
274 DCHECK(lock_ != NULL); | 271 LockOrUnlockCommon(F_LOCK); |
275 while(sem_wait(lock_) < 0) { | |
276 DCHECK(errno == EAGAIN || errno == EINTR); | |
277 } | |
278 } | 272 } |
279 | 273 |
280 void SharedMemory::Unlock() { | 274 void SharedMemory::Unlock() { |
281 DCHECK(lock_ != NULL); | 275 LockOrUnlockCommon(F_ULOCK); |
282 int result = sem_post(lock_); | |
283 DCHECK(result == 0); | |
284 } | 276 } |
285 | 277 |
286 } // namespace base | 278 } // namespace base |
OLD | NEW |