| OLD | NEW |
| 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 <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 11 #include "mojo/edk/embedder/embedder_internal.h" |
| 11 #include "mojo/edk/embedder/platform_support.h" | 12 #include "mojo/edk/embedder/platform_support.h" |
| 12 #include "mojo/edk/system/channel.h" | |
| 13 #include "mojo/edk/system/configuration.h" | 13 #include "mojo/edk/system/configuration.h" |
| 14 #include "mojo/edk/system/memory.h" | 14 #include "mojo/edk/system/memory.h" |
| 15 #include "mojo/edk/system/options_validation.h" | 15 #include "mojo/edk/system/options_validation.h" |
| 16 #include "mojo/public/c/system/macros.h" | 16 #include "mojo/public/c/system/macros.h" |
| 17 | 17 |
| 18 namespace mojo { | 18 namespace mojo { |
| 19 namespace system { | 19 namespace system { |
| 20 | 20 |
| 21 namespace { | 21 namespace { |
| 22 | 22 |
| 23 struct SerializedSharedBufferDispatcher { | 23 struct MOJO_ALIGNAS(8) SerializedSharedBufferDispatcher { |
| 24 size_t num_bytes; | 24 size_t num_bytes; |
| 25 size_t platform_handle_index; | 25 size_t platform_handle_index; |
| 26 }; | 26 }; |
| 27 | 27 |
| 28 } // namespace | 28 } // namespace |
| 29 | 29 |
| 30 // static | 30 // static |
| 31 const MojoCreateSharedBufferOptions | 31 const MojoCreateSharedBufferOptions |
| 32 SharedBufferDispatcher::kDefaultCreateOptions = { | 32 SharedBufferDispatcher::kDefaultCreateOptions = { |
| 33 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), | 33 static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 *result = CreateInternal(shared_buffer.Pass()); | 80 *result = CreateInternal(shared_buffer.Pass()); |
| 81 return MOJO_RESULT_OK; | 81 return MOJO_RESULT_OK; |
| 82 } | 82 } |
| 83 | 83 |
| 84 Dispatcher::Type SharedBufferDispatcher::GetType() const { | 84 Dispatcher::Type SharedBufferDispatcher::GetType() const { |
| 85 return Type::SHARED_BUFFER; | 85 return Type::SHARED_BUFFER; |
| 86 } | 86 } |
| 87 | 87 |
| 88 // static | 88 // static |
| 89 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( | 89 scoped_refptr<SharedBufferDispatcher> SharedBufferDispatcher::Deserialize( |
| 90 Channel* channel, | |
| 91 const void* source, | 90 const void* source, |
| 92 size_t size, | 91 size_t size, |
| 93 embedder::PlatformHandleVector* platform_handles) { | 92 embedder::PlatformHandleVector* platform_handles) { |
| 94 DCHECK(channel); | |
| 95 | 93 |
| 96 if (size != sizeof(SerializedSharedBufferDispatcher)) { | 94 if (size != sizeof(SerializedSharedBufferDispatcher)) { |
| 97 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; | 95 LOG(ERROR) << "Invalid serialized shared buffer dispatcher (bad size)"; |
| 98 return nullptr; | 96 return nullptr; |
| 99 } | 97 } |
| 100 | 98 |
| 101 const SerializedSharedBufferDispatcher* serialization = | 99 const SerializedSharedBufferDispatcher* serialization = |
| 102 static_cast<const SerializedSharedBufferDispatcher*>(source); | 100 static_cast<const SerializedSharedBufferDispatcher*>(source); |
| 103 size_t num_bytes = serialization->num_bytes; | 101 size_t num_bytes = serialization->num_bytes; |
| 104 size_t platform_handle_index = serialization->platform_handle_index; | 102 size_t platform_handle_index = serialization->platform_handle_index; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 117 | 115 |
| 118 // Starts off invalid, which is what we want. | 116 // Starts off invalid, which is what we want. |
| 119 embedder::PlatformHandle platform_handle; | 117 embedder::PlatformHandle platform_handle; |
| 120 // We take ownership of the handle, so we have to invalidate the one in | 118 // We take ownership of the handle, so we have to invalidate the one in |
| 121 // |platform_handles|. | 119 // |platform_handles|. |
| 122 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); | 120 std::swap(platform_handle, (*platform_handles)[platform_handle_index]); |
| 123 | 121 |
| 124 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be | 122 // Wrapping |platform_handle| in a |ScopedPlatformHandle| means that it'll be |
| 125 // closed even if creation fails. | 123 // closed even if creation fails. |
| 126 scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer( | 124 scoped_refptr<embedder::PlatformSharedBuffer> shared_buffer( |
| 127 channel->platform_support()->CreateSharedBufferFromHandle( | 125 embedder::internal::g_platform_support->CreateSharedBufferFromHandle( |
| 128 num_bytes, embedder::ScopedPlatformHandle(platform_handle))); | 126 num_bytes, embedder::ScopedPlatformHandle(platform_handle))); |
| 129 if (!shared_buffer) { | 127 if (!shared_buffer) { |
| 130 LOG(ERROR) | 128 LOG(ERROR) |
| 131 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; | 129 << "Invalid serialized shared buffer dispatcher (invalid num_bytes?)"; |
| 132 return nullptr; | 130 return nullptr; |
| 133 } | 131 } |
| 134 | 132 |
| 135 return CreateInternal(shared_buffer.Pass()); | 133 return CreateInternal(shared_buffer.Pass()); |
| 136 } | 134 } |
| 137 | 135 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 out_options->flags = reader.options().flags; | 168 out_options->flags = reader.options().flags; |
| 171 | 169 |
| 172 // Checks for fields beyond |flags|: | 170 // Checks for fields beyond |flags|: |
| 173 | 171 |
| 174 // (Nothing here yet.) | 172 // (Nothing here yet.) |
| 175 | 173 |
| 176 return MOJO_RESULT_OK; | 174 return MOJO_RESULT_OK; |
| 177 } | 175 } |
| 178 | 176 |
| 179 void SharedBufferDispatcher::CloseImplNoLock() { | 177 void SharedBufferDispatcher::CloseImplNoLock() { |
| 180 mutex().AssertHeld(); | 178 lock().AssertAcquired(); |
| 181 DCHECK(shared_buffer_); | 179 DCHECK(shared_buffer_); |
| 182 shared_buffer_ = nullptr; | 180 shared_buffer_ = nullptr; |
| 183 } | 181 } |
| 184 | 182 |
| 185 scoped_refptr<Dispatcher> | 183 scoped_refptr<Dispatcher> |
| 186 SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { | 184 SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() { |
| 187 mutex().AssertHeld(); | 185 lock().AssertAcquired(); |
| 188 DCHECK(shared_buffer_); | 186 DCHECK(shared_buffer_); |
| 189 return CreateInternal(shared_buffer_.Pass()); | 187 return CreateInternal(shared_buffer_.Pass()); |
| 190 } | 188 } |
| 191 | 189 |
| 192 MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock( | 190 MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock( |
| 193 UserPointer<const MojoDuplicateBufferHandleOptions> options, | 191 UserPointer<const MojoDuplicateBufferHandleOptions> options, |
| 194 scoped_refptr<Dispatcher>* new_dispatcher) { | 192 scoped_refptr<Dispatcher>* new_dispatcher) { |
| 195 mutex().AssertHeld(); | 193 lock().AssertAcquired(); |
| 196 | 194 |
| 197 MojoDuplicateBufferHandleOptions validated_options; | 195 MojoDuplicateBufferHandleOptions validated_options; |
| 198 MojoResult result = ValidateDuplicateOptions(options, &validated_options); | 196 MojoResult result = ValidateDuplicateOptions(options, &validated_options); |
| 199 if (result != MOJO_RESULT_OK) | 197 if (result != MOJO_RESULT_OK) |
| 200 return result; | 198 return result; |
| 201 | 199 |
| 202 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. | 200 // Note: Since this is "duplicate", we keep our ref to |shared_buffer_|. |
| 203 *new_dispatcher = CreateInternal(shared_buffer_); | 201 *new_dispatcher = CreateInternal(shared_buffer_); |
| 204 return MOJO_RESULT_OK; | 202 return MOJO_RESULT_OK; |
| 205 } | 203 } |
| 206 | 204 |
| 207 MojoResult SharedBufferDispatcher::MapBufferImplNoLock( | 205 MojoResult SharedBufferDispatcher::MapBufferImplNoLock( |
| 208 uint64_t offset, | 206 uint64_t offset, |
| 209 uint64_t num_bytes, | 207 uint64_t num_bytes, |
| 210 MojoMapBufferFlags flags, | 208 MojoMapBufferFlags flags, |
| 211 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { | 209 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { |
| 212 mutex().AssertHeld(); | 210 lock().AssertAcquired(); |
| 213 DCHECK(shared_buffer_); | 211 DCHECK(shared_buffer_); |
| 214 | 212 |
| 215 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 213 if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
| 216 return MOJO_RESULT_INVALID_ARGUMENT; | 214 return MOJO_RESULT_INVALID_ARGUMENT; |
| 217 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) | 215 if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max())) |
| 218 return MOJO_RESULT_INVALID_ARGUMENT; | 216 return MOJO_RESULT_INVALID_ARGUMENT; |
| 219 | 217 |
| 220 if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset), | 218 if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset), |
| 221 static_cast<size_t>(num_bytes))) | 219 static_cast<size_t>(num_bytes))) |
| 222 return MOJO_RESULT_INVALID_ARGUMENT; | 220 return MOJO_RESULT_INVALID_ARGUMENT; |
| 223 | 221 |
| 224 DCHECK(mapping); | 222 DCHECK(mapping); |
| 225 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), | 223 *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset), |
| 226 static_cast<size_t>(num_bytes)); | 224 static_cast<size_t>(num_bytes)); |
| 227 if (!*mapping) | 225 if (!*mapping) |
| 228 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 226 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
| 229 | 227 |
| 230 return MOJO_RESULT_OK; | 228 return MOJO_RESULT_OK; |
| 231 } | 229 } |
| 232 | 230 |
| 233 void SharedBufferDispatcher::StartSerializeImplNoLock( | 231 void SharedBufferDispatcher::StartSerializeImplNoLock( |
| 234 Channel* /*channel*/, | |
| 235 size_t* max_size, | 232 size_t* max_size, |
| 236 size_t* max_platform_handles) { | 233 size_t* max_platform_handles) { |
| 237 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 234 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
| 238 *max_size = sizeof(SerializedSharedBufferDispatcher); | 235 *max_size = sizeof(SerializedSharedBufferDispatcher); |
| 239 *max_platform_handles = 1; | 236 *max_platform_handles = 1; |
| 240 } | 237 } |
| 241 | 238 |
| 242 bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( | 239 bool SharedBufferDispatcher::EndSerializeAndCloseImplNoLock( |
| 243 Channel* /*channel*/, | |
| 244 void* destination, | 240 void* destination, |
| 245 size_t* actual_size, | 241 size_t* actual_size, |
| 246 embedder::PlatformHandleVector* platform_handles) { | 242 embedder::PlatformHandleVector* platform_handles) { |
| 247 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 243 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
| 248 DCHECK(shared_buffer_); | 244 DCHECK(shared_buffer_); |
| 249 | 245 |
| 250 SerializedSharedBufferDispatcher* serialization = | 246 SerializedSharedBufferDispatcher* serialization = |
| 251 static_cast<SerializedSharedBufferDispatcher*>(destination); | 247 static_cast<SerializedSharedBufferDispatcher*>(destination); |
| 252 // If there's only one reference to |shared_buffer_|, then it's ours (and no | 248 // If there's only one reference to |shared_buffer_|, then it's ours (and no |
| 253 // one else can make any more references to it), so we can just take its | 249 // one else can make any more references to it), so we can just take its |
| 254 // handle. | 250 // handle. |
| 255 embedder::ScopedPlatformHandle platform_handle( | 251 embedder::ScopedPlatformHandle platform_handle( |
| 256 shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle() | 252 shared_buffer_->HasOneRef() ? shared_buffer_->PassPlatformHandle() |
| 257 : shared_buffer_->DuplicatePlatformHandle()); | 253 : shared_buffer_->DuplicatePlatformHandle()); |
| 258 if (!platform_handle.is_valid()) { | 254 if (!platform_handle.is_valid()) { |
| 259 shared_buffer_ = nullptr; | 255 shared_buffer_ = nullptr; |
| 260 return false; | 256 return false; |
| 261 } | 257 } |
| 262 | 258 |
| 263 serialization->num_bytes = shared_buffer_->GetNumBytes(); | 259 serialization->num_bytes = shared_buffer_->GetNumBytes(); |
| 264 serialization->platform_handle_index = platform_handles->size(); | 260 serialization->platform_handle_index = platform_handles->size(); |
| 265 platform_handles->push_back(platform_handle.release()); | 261 platform_handles->push_back(platform_handle.release()); |
| 266 *actual_size = sizeof(SerializedSharedBufferDispatcher); | 262 *actual_size = sizeof(SerializedSharedBufferDispatcher); |
| 267 | 263 |
| 268 shared_buffer_ = nullptr; | 264 shared_buffer_ = nullptr; |
| 269 | 265 |
| 270 return true; | 266 return true; |
| 271 } | 267 } |
| 272 | 268 |
| 269 |
| 273 } // namespace system | 270 } // namespace system |
| 274 } // namespace mojo | 271 } // namespace mojo |
| OLD | NEW |