blob: 579d91637e5ce173bba0540d5a62537cb3ee8436 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// 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
3// found in the LICENSE file.
avi@google.com3a208982008-08-13 06:06:40 +09004
5#include "base/shared_memory.h"
6
tc@google.com7e1fb1d2008-08-13 07:40:21 +09007#include <fcntl.h>
avi@google.com3a208982008-08-13 06:06:40 +09008#include <sys/mman.h>
9
10#include "base/logging.h"
11#include "base/string_util.h"
12
brettw@google.comc60d9892008-11-14 12:25:15 +090013namespace base {
14
avi@google.com3a208982008-08-13 06:06:40 +090015namespace {
avi@google.com9e0cc152008-08-14 04:59:07 +090016// Paranoia. Semaphores and shared memory segments should live in different
17// namespaces, but who knows what's out there.
18const char kSemaphoreSuffix[] = "-sem";
avi@google.com3a208982008-08-13 06:06:40 +090019}
20
21SharedMemory::SharedMemory()
22 : mapped_file_(-1),
23 memory_(NULL),
24 read_only_(false),
25 max_size_(0),
26 lock_(NULL) {
27}
28
29SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only)
30 : mapped_file_(handle),
31 memory_(NULL),
32 read_only_(read_only),
33 max_size_(0),
34 lock_(NULL) {
35}
36
37SharedMemory::SharedMemory(SharedMemoryHandle handle, bool read_only,
38 ProcessHandle process)
39 : mapped_file_(handle),
40 memory_(NULL),
41 read_only_(read_only),
42 max_size_(0),
43 lock_(NULL) {
44 // We don't handle this case yet (note the ignored parameter); let's die if
45 // someone comes calling.
46 NOTREACHED();
47}
48
49SharedMemory::~SharedMemory() {
50 Close();
51 if (lock_ != NULL)
52 sem_close(lock_);
53}
54
55bool SharedMemory::Create(const std::wstring &name, bool read_only,
56 bool open_existing, size_t size) {
avi@google.com3a208982008-08-13 06:06:40 +090057 read_only_ = read_only;
58
59 int posix_flags = 0;
60 posix_flags |= read_only ? O_RDONLY : O_RDWR;
pinkerton@google.com38e86812008-09-24 00:29:16 +090061 if (!open_existing || mapped_file_ <= 0)
avi@google.com9e0cc152008-08-14 04:59:07 +090062 posix_flags |= O_CREAT;
agl@chromium.org69e0a492008-11-18 09:21:05 +090063
avi@google.com9e0cc152008-08-14 04:59:07 +090064 if (CreateOrOpen(name, posix_flags)) {
agl@chromium.org69e0a492008-11-18 09:21:05 +090065 if (0 == ftruncate(mapped_file_, size)) {
66 max_size_ = size;
67 return true;
68 } else {
69 Close();
70 return false;
71 }
avi@google.com9e0cc152008-08-14 04:59:07 +090072 }
agl@chromium.org69e0a492008-11-18 09:21:05 +090073
avi@google.com9e0cc152008-08-14 04:59:07 +090074 return false;
75}
76
77bool SharedMemory::Open(const std::wstring &name, bool read_only) {
78 read_only_ = read_only;
agl@chromium.org69e0a492008-11-18 09:21:05 +090079
avi@google.com9e0cc152008-08-14 04:59:07 +090080 int posix_flags = 0;
81 posix_flags |= read_only ? O_RDONLY : O_RDWR;
agl@chromium.org69e0a492008-11-18 09:21:05 +090082
avi@google.com9e0cc152008-08-14 04:59:07 +090083 return CreateOrOpen(name, posix_flags);
84}
85
86bool SharedMemory::CreateOrOpen(const std::wstring &name, int posix_flags) {
87 DCHECK(mapped_file_ == -1);
agl@chromium.org69e0a492008-11-18 09:21:05 +090088
avi@google.com9e0cc152008-08-14 04:59:07 +090089 name_ = L"/" + name;
agl@chromium.org69e0a492008-11-18 09:21:05 +090090
brettw@google.com4a6795c2008-10-30 02:01:22 +090091 mode_t posix_mode = S_IRUSR | S_IWUSR; // owner read/write
avi@google.com3a208982008-08-13 06:06:40 +090092 std::string posix_name(WideToUTF8(name_));
93 mapped_file_ = shm_open(posix_name.c_str(), posix_flags, posix_mode);
avi@google.com3a208982008-08-13 06:06:40 +090094 if (mapped_file_ < 0)
95 return false;
agl@chromium.org69e0a492008-11-18 09:21:05 +090096
avi@google.com3a208982008-08-13 06:06:40 +090097 posix_name += kSemaphoreSuffix;
98 lock_ = sem_open(posix_name.c_str(), O_CREAT, posix_mode, 1);
99 if (lock_ == SEM_FAILED) {
100 close(mapped_file_);
101 mapped_file_ = -1;
102 shm_unlink(posix_name.c_str());
103 lock_ = NULL;
104 return false;
105 }
agl@chromium.org69e0a492008-11-18 09:21:05 +0900106
avi@google.com3a208982008-08-13 06:06:40 +0900107 return true;
108}
109
avi@google.com3a208982008-08-13 06:06:40 +0900110bool SharedMemory::Map(size_t bytes) {
111 if (mapped_file_ == -1)
112 return false;
agl@chromium.org69e0a492008-11-18 09:21:05 +0900113
avi@google.com3a208982008-08-13 06:06:40 +0900114 memory_ = mmap(NULL, bytes, PROT_READ | (read_only_ ? 0 : PROT_WRITE),
115 MAP_SHARED, mapped_file_, 0);
116
117 if (memory_)
118 max_size_ = bytes;
119
120 return (memory_ != NULL);
121}
122
123bool SharedMemory::Unmap() {
124 if (memory_ == NULL)
125 return false;
126
127 munmap(memory_, max_size_);
128 memory_ = NULL;
129 max_size_ = 0;
130 return true;
131}
132
133bool SharedMemory::ShareToProcessCommon(ProcessHandle process,
134 SharedMemoryHandle *new_handle,
135 bool close_self) {
136 *new_handle = 0;
137 // TODO(awalker): figure out if we need this, and do the appropriate
138 // VM magic if so.
139 return false;
140}
141
142
143void SharedMemory::Close() {
144 if (memory_ != NULL) {
145 munmap(memory_, max_size_);
146
147 memory_ = NULL;
148 max_size_ = 0;
149 }
150
151 std::string posix_name(WideToUTF8(name_));
brettw@google.com4a6795c2008-10-30 02:01:22 +0900152 if (mapped_file_ > 0) {
avi@google.com3a208982008-08-13 06:06:40 +0900153 close(mapped_file_);
154 shm_unlink(posix_name.c_str());
155 mapped_file_ = -1;
156 }
agl@chromium.org69e0a492008-11-18 09:21:05 +0900157
avi@google.com3a208982008-08-13 06:06:40 +0900158 if (lock_) {
159 posix_name += kSemaphoreSuffix;
160 sem_unlink(posix_name.c_str());
161 lock_ = NULL;
162 }
163}
164
165void SharedMemory::Lock() {
166 DCHECK(lock_ != NULL);
167 sem_wait(lock_);
168}
169
170void SharedMemory::Unlock() {
171 DCHECK(lock_ != NULL);
172 sem_post(lock_);
173}
license.botf003cfe2008-08-24 09:55:55 +0900174
brettw@google.comc60d9892008-11-14 12:25:15 +0900175} // namespace base