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

Side by Side Diff: mojo/edk/system/shared_buffer_dispatcher.cc

Issue 1585493002: [mojo] Ports EDK (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "mojo/edk/system/shared_buffer_dispatcher.h" 5 #include "mojo/edk/system/shared_buffer_dispatcher.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm>
11 #include <limits> 10 #include <limits>
12 #include <utility> 11 #include <utility>
13 12
14 #include "base/logging.h" 13 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
16 #include "mojo/edk/embedder/embedder_internal.h" 15 #include "mojo/edk/embedder/embedder_internal.h"
17 #include "mojo/edk/embedder/platform_support.h" 16 #include "mojo/edk/embedder/platform_support.h"
18 #include "mojo/edk/system/configuration.h" 17 #include "mojo/edk/system/configuration.h"
19 #include "mojo/edk/system/options_validation.h" 18 #include "mojo/edk/system/options_validation.h"
20 #include "mojo/public/c/system/macros.h" 19 #include "mojo/public/c/system/macros.h"
21 20
22 namespace mojo { 21 namespace mojo {
23 namespace edk { 22 namespace edk {
24 23
25 namespace { 24 namespace {
26 25
27 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher { 26 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher {
28 MOJO_ALIGNAS(4) uint32_t num_bytes; 27 size_t num_bytes;
Anand Mistry (off Chromium) 2016/01/28 02:26:24 Please don't use size_t in serialised messages.
29 MOJO_ALIGNAS(4) uint32_t platform_handle_index;
30 }; 28 };
31 29
32 } // namespace 30 } // namespace
33 31
34 // static 32 // static
35 const MojoCreateSharedBufferOptions 33 const MojoCreateSharedBufferOptions
36 SharedBufferDispatcher::kDefaultCreateOptions = { 34 SharedBufferDispatcher::kDefaultCreateOptions = {
37 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), 35 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
38 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE}; 36 MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE};
39 37
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 76
79 scoped_refptr<PlatformSharedBuffer> shared_buffer( 77 scoped_refptr<PlatformSharedBuffer> shared_buffer(
80 platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes))); 78 platform_support->CreateSharedBuffer(static_cast<size_t>(num_bytes)));
81 if (!shared_buffer) 79 if (!shared_buffer)
82 return MOJO_RESULT_RESOURCE_EXHAUSTED; 80 return MOJO_RESULT_RESOURCE_EXHAUSTED;
83 81
84 *result = CreateInternal(std::move(shared_buffer)); 82 *result = CreateInternal(std::move(shared_buffer));
85 return MOJO_RESULT_OK; 83 return MOJO_RESULT_OK;
86 } 84 }
87 85
88 Dispatcher::Type SharedBufferDispatcher::GetType() const {
89 return Type::SHARED_BUFFER;
90 }
91
92 // static 86 // static
93 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( 87 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize(
94 const void* source, 88 const void* bytes,
95 size_t size, 89 size_t num_bytes,
96 PlatformHandleVector* platform_handles) { 90 const ports::PortName* ports,
97 91 size_t num_ports,
98 if (size != sizeof(SerializedSharedBufferDispatcher)) { 92 PlatformHandle* platform_handles,
93 size_t num_platform_handles) {
94 if (num_bytes != sizeof(SerializedSharedBufferDispatcher)) {
99 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; 95 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)";
100 return nullptr; 96 return nullptr;
101 } 97 }
102 98
103 const SerializedSharedBufferDispatcher* serialization = 99 const SerializedSharedBufferDispatcher* serialization =
104 static_cast<const SerializedSharedBufferDispatcher*>(source); 100 static_cast<const SerializedSharedBufferDispatcher*>(bytes);
105 size_t num_bytes = serialization->num_bytes; 101 if (!serialization->num_bytes) {
106 size_t platform_handle_index = serialization->platform_handle_index;
107
108 if (!num_bytes) {
109 LOG(ERROR) 102 LOG(ERROR)
110 << "Invalid serialized shared buffer dispatcher (invalid num_bytes)"; 103 << "Invalid serialized shared buffer dispatcher (invalid num_bytes)";
111 return nullptr; 104 return nullptr;
112 } 105 }
113 106
114 if (!platform_handles || platform_handle_index >= platform_handles->size()) { 107 if (!platform_handles || num_platform_handles != 1 || num_ports) {
115 LOG(ERROR) 108 LOG(ERROR)
116 << "Invalid serialized shared buffer dispatcher (missing handles)"; 109 << "Invalid serialized shared buffer dispatcher (missing handles)";
117 return nullptr; 110 return nullptr;
118 } 111 }
119 112
120 // Starts off invalid, which is what we want. 113 // Starts off invalid, which is what we want.
121 PlatformHandle platform_handle; 114 PlatformHandle platform_handle;
122 // We take ownership of the handle, so we have to invalidate the one in 115 // We take ownership of the handle, so we have to invalidate the one in
123 // |platform_handles|. 116 // |platform_handles|.
124 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); 117 std::swap(platform_handle, *platform_handles);
125 118
126 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be 119 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be
127 // closed even if creation fails. 120 // closed even if creation fails.
128 scoped_refptr<PlatformSharedBuffer> shared_buffer( 121 scoped_refptr<PlatformSharedBuffer> shared_buffer(
129 internal::g_platform_support->CreateSharedBufferFromHandle( 122 internal::g_platform_support->CreateSharedBufferFromHandle(
130 num_bytes, ScopedPlatformHandle(platform_handle))); 123 serialization->num_bytes, ScopedPlatformHandle(platform_handle)));
131 if (!shared_buffer) { 124 if (!shared_buffer) {
132 LOG(ERROR) 125 LOG(ERROR)
133 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; 126 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)";
134 return nullptr; 127 return nullptr;
135 } 128 }
136 129
137 return CreateInternal(std::move(shared_buffer)); 130 return CreateInternal(std::move(shared_buffer));
138 } 131 }
139 132
140 SharedBufferDispatcher::SharedBufferDispatcher( 133 Dispatcher::Type SharedBufferDispatcher::GetType() const {
141 scoped_refptr<PlatformSharedBuffer> shared_buffer) 134 return Type::SHARED_BUFFER;
142 : shared_buffer_(shared_buffer) {
143 DCHECK(shared_buffer_);
144 } 135 }
145 136
146 SharedBufferDispatcher::~SharedBufferDispatcher() { 137 MojoResult SharedBufferDispatcher::Close() {
147 } 138 base::AutoLock lock(lock_);
148 139 if (!shared_buffer_ || in_transit_)
149 // static
150 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
151 const MojoDuplicateBufferHandleOptions* in_options,
152 MojoDuplicateBufferHandleOptions* out_options) {
153 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags =
154 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE;
155 static const MojoDuplicateBufferHandleOptions kDefaultOptions = {
156 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)),
157 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
158
159 *out_options = kDefaultOptions;
160 if (!in_options)
161 return MOJO_RESULT_OK;
162
163 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options);
164 if (!reader.is_valid())
165 return MOJO_RESULT_INVALID_ARGUMENT; 140 return MOJO_RESULT_INVALID_ARGUMENT;
166 141
167 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags, 142 shared_buffer_ = nullptr;
168 reader))
169 return MOJO_RESULT_OK;
170 if ((reader.options().flags & ~kKnownFlags))
171 return MOJO_RESULT_UNIMPLEMENTED;
172 out_options->flags = reader.options().flags;
173
174 // Checks for fields beyond |flags|:
175
176 // (Nothing here yet.)
177
178 return MOJO_RESULT_OK; 143 return MOJO_RESULT_OK;
179 } 144 }
180 145
181 void SharedBufferDispatcher::CloseImplNoLock() { 146 MojoResult SharedBufferDispatcher::DuplicateBufferHandle(
182 lock().AssertAcquired();
183 DCHECK(shared_buffer_);
184 shared_buffer_ = nullptr;
185 }
186
187 scoped_refptr<Dispatcher>
188 SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
189 lock().AssertAcquired();
190 DCHECK(shared_buffer_);
191 return CreateInternal(std::move(shared_buffer_));
192 }
193
194 MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
195 const MojoDuplicateBufferHandleOptions* options, 147 const MojoDuplicateBufferHandleOptions* options,
196 scoped_refptr<Dispatcher>* new_dispatcher) { 148 scoped_refptr<Dispatcher>* new_dispatcher) {
197 lock().AssertAcquired();
198
199 MojoDuplicateBufferHandleOptions validated_options; 149 MojoDuplicateBufferHandleOptions validated_options;
200 MojoResult result = ValidateDuplicateOptions(options, &validated_options); 150 MojoResult result = ValidateDuplicateOptions(options, &validated_options);
201 if (result != MOJO_RESULT_OK) 151 if (result != MOJO_RESULT_OK)
202 return result; 152 return result;
203 153
204 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. 154 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|.
155 base::AutoLock lock(lock_);
156 if (in_transit_)
157 return MOJO_RESULT_INVALID_ARGUMENT;
205 *new_dispatcher = CreateInternal(shared_buffer_); 158 *new_dispatcher = CreateInternal(shared_buffer_);
206 return MOJO_RESULT_OK; 159 return MOJO_RESULT_OK;
207 } 160 }
208 161
209 MojoResult SharedBufferDispatcher::MapBufferImplNoLock( 162 MojoResult SharedBufferDispatcher::MapBuffer(
210 uint64_t offset, 163 uint64_t offset,
211 uint64_t num_bytes, 164 uint64_t num_bytes,
212 MojoMapBufferFlags flags, 165 MojoMapBufferFlags flags,
213 scoped_ptr<PlatformSharedBufferMapping>* mapping) { 166 scoped_ptr<PlatformSharedBufferMapping>* mapping) {
214 lock().AssertAcquired();
215 DCHECK(shared_buffer_);
216
217 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) 167 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
218 return MOJO_RESULT_INVALID_ARGUMENT; 168 return MOJO_RESULT_INVALID_ARGUMENT;
219 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) 169 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
220 return MOJO_RESULT_INVALID_ARGUMENT; 170 return MOJO_RESULT_INVALID_ARGUMENT;
221 171
222 if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset), 172 base::AutoLock lock(lock_);
223 static_cast<size_t>(num_bytes))) 173 DCHECK(shared_buffer_);
174 if (in_transit_ ||
175 !shared_buffer_->IsValidMap(static_cast<size_t>(offset),
176 static_cast<size_t>(num_bytes))) {
224 return MOJO_RESULT_INVALID_ARGUMENT; 177 return MOJO_RESULT_INVALID_ARGUMENT;
178 }
225 179
226 DCHECK(mapping); 180 DCHECK(mapping);
227 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), 181 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset),
228 static_cast<size_t>(num_bytes)); 182 static_cast<size_t>(num_bytes));
229 if (!*mapping) 183 if (!*mapping)
230 return MOJO_RESULT_RESOURCE_EXHAUSTED; 184 return MOJO_RESULT_RESOURCE_EXHAUSTED;
231 185
232 return MOJO_RESULT_OK; 186 return MOJO_RESULT_OK;
233 } 187 }
234 188
235 void SharedBufferDispatcher::StartSerializeImplNoLock( 189 void SharedBufferDispatcher::StartSerialize(uint32_t* num_bytes,
236 size_t* max_size, 190 uint32_t* num_ports,
237 size_t* max_platform_handles) { 191 uint32_t* num_platform_handles) {
238 *max_size = sizeof(SerializedSharedBufferDispatcher); 192 *num_bytes = sizeof(SerializedSharedBufferDispatcher);
239 *max_platform_handles = 1; 193 *num_ports = 0;
194 *num_platform_handles = 1;
240 } 195 }
241 196
242 bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( 197 bool SharedBufferDispatcher::EndSerialize(void* destination,
243 void* destination, 198 ports::PortName* ports,
244 size_t* actual_size, 199 PlatformHandle* handles) {
245 PlatformHandleVector* platform_handles) {
246 DCHECK(shared_buffer_);
247
248 SerializedSharedBufferDispatcher* serialization = 200 SerializedSharedBufferDispatcher* serialization =
249 static_cast<SerializedSharedBufferDispatcher*>(destination); 201 static_cast<SerializedSharedBufferDispatcher*>(destination);
250 // If there's only one reference to |shared_buffer_|, then it's ours (and no 202 base::AutoLock lock(lock_);
251 // one else can make any more references to it), so we can just take its 203 serialization->num_bytes = shared_buffer_->GetNumBytes();
252 // handle. 204
253 ScopedPlatformHandle platform_handle( 205 handle_for_transit_ = shared_buffer_->DuplicatePlatformHandle();
254 shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle() 206 if (!handle_for_transit_.is_valid()) {
255 : shared_buffer_->DuplicatePlatformHandle());
256 if (!platform_handle.is_valid()) {
257 shared_buffer_ = nullptr; 207 shared_buffer_ = nullptr;
258 return false; 208 return false;
259 } 209 }
260 210 handles[0] = handle_for_transit_.get();
261 DCHECK(shared_buffer_->GetNumBytes() < std::numeric_limits<uint32_t>::max());
262 serialization->num_bytes =
263 static_cast<uint32_t>(shared_buffer_->GetNumBytes());
264 DCHECK(platform_handles->size() < std::numeric_limits<uint32_t>::max());
265 serialization->platform_handle_index =
266 static_cast<uint32_t>(platform_handles->size());
267 platform_handles->push_back(platform_handle.release());
268 *actual_size = sizeof(SerializedSharedBufferDispatcher);
269
270 shared_buffer_ = nullptr;
271
272 return true; 211 return true;
273 } 212 }
274 213
214 bool SharedBufferDispatcher::BeginTransit() {
215 base::AutoLock lock(lock_);
216 if (in_transit_)
217 return false;
218 in_transit_ = shared_buffer_ != nullptr;
219 return in_transit_;
220 }
221
222 void SharedBufferDispatcher::CompleteTransitAndClose() {
223 base::AutoLock lock(lock_);
224 in_transit_ = false;
225 shared_buffer_ = nullptr;
226 ignore_result(handle_for_transit_.release());
227 }
228
229 void SharedBufferDispatcher::CancelTransit() {
230 base::AutoLock lock(lock_);
231 in_transit_ = false;
232 handle_for_transit_.reset();
233 }
234
235 SharedBufferDispatcher::SharedBufferDispatcher(
236 scoped_refptr<PlatformSharedBuffer> shared_buffer)
237 : shared_buffer_(shared_buffer) {
238 DCHECK(shared_buffer_);
239 }
240
241 SharedBufferDispatcher::~SharedBufferDispatcher() {
242 DCHECK(!shared_buffer_ && !in_transit_);
243 }
244
245 // static
246 MojoResult SharedBufferDispatcher::ValidateDuplicateOptions(
247 const MojoDuplicateBufferHandleOptions* in_options,
248 MojoDuplicateBufferHandleOptions* out_options) {
249 const MojoDuplicateBufferHandleOptionsFlags kKnownFlags =
250 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE;
251 static const MojoDuplicateBufferHandleOptions kDefaultOptions = {
252 static_cast<uint32_t>(sizeof(MojoDuplicateBufferHandleOptions)),
253 MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE};
254
255 *out_options = kDefaultOptions;
256 if (!in_options)
257 return MOJO_RESULT_OK;
258
259 UserOptionsReader<MojoDuplicateBufferHandleOptions> reader(in_options);
260 if (!reader.is_valid())
261 return MOJO_RESULT_INVALID_ARGUMENT;
262
263 if (!OPTIONS_STRUCT_HAS_MEMBER(MojoDuplicateBufferHandleOptions, flags,
264 reader))
265 return MOJO_RESULT_OK;
266 if ((reader.options().flags & ~kKnownFlags))
267 return MOJO_RESULT_UNIMPLEMENTED;
268 out_options->flags = reader.options().flags;
269
270 // Checks for fields beyond |flags|:
271
272 // (Nothing here yet.)
273
274 return MOJO_RESULT_OK;
275 }
275 276
276 } // namespace edk 277 } // namespace edk
277 } // namespace mojo 278 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698