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

Side by Side Diff: mojo/system/message_in_transit.cc

Issue 260823002: Mojo: Small fixes/cleanup to MessageInTransit, before I factor out the secondary buffer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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
« no previous file with comments | « mojo/system/message_in_transit.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/system/message_in_transit.h" 5 #include "mojo/system/message_in_transit.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <new> 9 #include <new>
10 10
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/aligned_memory.h"
14 #include "mojo/system/constants.h" 13 #include "mojo/system/constants.h"
15 14
16 namespace mojo { 15 namespace mojo {
17 namespace system { 16 namespace system {
18 17
19 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 18 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
20 MessageInTransit::kTypeMessagePipeEndpoint; 19 MessageInTransit::kTypeMessagePipeEndpoint;
21 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 20 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
22 MessageInTransit::kTypeMessagePipe; 21 MessageInTransit::kTypeMessagePipe;
23 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type 22 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::Type
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 98
100 return true; 99 return true;
101 } 100 }
102 101
103 MessageInTransit::MessageInTransit(Type type, 102 MessageInTransit::MessageInTransit(Type type,
104 Subtype subtype, 103 Subtype subtype,
105 uint32_t num_bytes, 104 uint32_t num_bytes,
106 uint32_t num_handles, 105 uint32_t num_handles,
107 const void* bytes) 106 const void* bytes)
108 : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)), 107 : main_buffer_size_(RoundUpMessageAlignment(sizeof(Header) + num_bytes)),
109 main_buffer_(base::AlignedAlloc(main_buffer_size_, kMessageAlignment)), 108 main_buffer_(static_cast<char*>(base::AlignedAlloc(main_buffer_size_,
110 secondary_buffer_size_(0), 109 kMessageAlignment))),
111 secondary_buffer_(NULL) { 110 secondary_buffer_size_(0) {
112 DCHECK_LE(num_bytes, kMaxMessageNumBytes); 111 DCHECK_LE(num_bytes, kMaxMessageNumBytes);
113 DCHECK_LE(num_handles, kMaxMessageNumHandles); 112 DCHECK_LE(num_handles, kMaxMessageNumHandles);
114 113
115 // |total_size| is updated below, from the other values. 114 // |total_size| is updated below, from the other values.
116 header()->type = type; 115 header()->type = type;
117 header()->subtype = subtype; 116 header()->subtype = subtype;
118 header()->source_id = kInvalidEndpointId; 117 header()->source_id = kInvalidEndpointId;
119 header()->destination_id = kInvalidEndpointId; 118 header()->destination_id = kInvalidEndpointId;
120 header()->num_bytes = num_bytes; 119 header()->num_bytes = num_bytes;
121 header()->num_handles = num_handles; 120 header()->num_handles = num_handles;
122 // Note: If dispatchers are subsequently attached (in particular, if 121 // Note: If dispatchers are subsequently attached (in particular, if
123 // |num_handles| is nonzero), then |total_size| will have to be adjusted. 122 // |num_handles| is nonzero), then |total_size| will have to be adjusted.
124 UpdateTotalSize(); 123 UpdateTotalSize();
125 124
126 if (bytes) { 125 if (bytes) {
127 memcpy(MessageInTransit::bytes(), bytes, num_bytes); 126 memcpy(MessageInTransit::bytes(), bytes, num_bytes);
128 memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0, 127 memset(static_cast<char*>(MessageInTransit::bytes()) + num_bytes, 0,
129 main_buffer_size_ - sizeof(Header) - num_bytes); 128 main_buffer_size_ - sizeof(Header) - num_bytes);
130 } else { 129 } else {
131 memset(MessageInTransit::bytes(), 0, main_buffer_size_ - sizeof(Header)); 130 memset(MessageInTransit::bytes(), 0, main_buffer_size_ - sizeof(Header));
132 } 131 }
133 } 132 }
134 133
135 // TODO(vtl): Do I really want/need to copy the secondary buffer here, or should 134 // TODO(vtl): Do I really want/need to copy the secondary buffer here, or should
136 // I just create (deserialize) the dispatchers right away? 135 // I just create (deserialize) the dispatchers right away?
137 MessageInTransit::MessageInTransit(const View& message_view) 136 MessageInTransit::MessageInTransit(const View& message_view)
138 : main_buffer_size_(message_view.main_buffer_size()), 137 : main_buffer_size_(message_view.main_buffer_size()),
139 main_buffer_(base::AlignedAlloc(main_buffer_size_, kMessageAlignment)), 138 main_buffer_(static_cast<char*>(base::AlignedAlloc(main_buffer_size_,
139 kMessageAlignment))),
140 secondary_buffer_size_(message_view.secondary_buffer_size()), 140 secondary_buffer_size_(message_view.secondary_buffer_size()),
141 secondary_buffer_(secondary_buffer_size_ ? 141 secondary_buffer_(secondary_buffer_size_ ?
142 base::AlignedAlloc(secondary_buffer_size_, 142 static_cast<char*>(
143 kMessageAlignment) : NULL) { 143 base::AlignedAlloc(secondary_buffer_size_,
144 kMessageAlignment)) : NULL) {
144 DCHECK_GE(main_buffer_size_, sizeof(Header)); 145 DCHECK_GE(main_buffer_size_, sizeof(Header));
145 DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); 146 DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
146 147
147 memcpy(main_buffer_, message_view.main_buffer(), main_buffer_size_); 148 memcpy(main_buffer_.get(), message_view.main_buffer(), main_buffer_size_);
148 memcpy(secondary_buffer_, message_view.secondary_buffer(), 149 memcpy(secondary_buffer_.get(), message_view.secondary_buffer(),
149 secondary_buffer_size_); 150 secondary_buffer_size_);
150 151
151 DCHECK_EQ(main_buffer_size_, 152 DCHECK_EQ(main_buffer_size_,
152 RoundUpMessageAlignment(sizeof(Header) + num_bytes())); 153 RoundUpMessageAlignment(sizeof(Header) + num_bytes()));
153 } 154 }
154 155
155 MessageInTransit::~MessageInTransit() { 156 MessageInTransit::~MessageInTransit() {
156 base::AlignedFree(main_buffer_);
157 base::AlignedFree(secondary_buffer_); // Okay if null.
158
159 if (dispatchers_) { 157 if (dispatchers_) {
160 for (size_t i = 0; i < dispatchers_->size(); i++) { 158 for (size_t i = 0; i < dispatchers_->size(); i++) {
161 if (!(*dispatchers_)[i]) 159 if (!(*dispatchers_)[i])
162 continue; 160 continue;
163 161
164 DCHECK((*dispatchers_)[i]->HasOneRef()); 162 DCHECK((*dispatchers_)[i]->HasOneRef());
165 (*dispatchers_)[i]->Close(); 163 (*dispatchers_)[i]->Close();
166 } 164 }
167 } 165 }
168 166
169 if (platform_handles_) { 167 if (platform_handles_) {
170 for (size_t i = 0; i < platform_handles_->size(); i++) 168 for (size_t i = 0; i < platform_handles_->size(); i++)
171 (*platform_handles_)[i].CloseIfNecessary(); 169 (*platform_handles_)[i].CloseIfNecessary();
172 } 170 }
173 171
174 #ifndef NDEBUG 172 #ifndef NDEBUG
175 main_buffer_size_ = 0;
176 main_buffer_ = NULL;
177 secondary_buffer_size_ = 0; 173 secondary_buffer_size_ = 0;
178 secondary_buffer_ = NULL;
179 dispatchers_.reset(); 174 dispatchers_.reset();
180 platform_handles_.reset(); 175 platform_handles_.reset();
181 #endif 176 #endif
182 } 177 }
183 178
184 // static 179 // static
185 bool MessageInTransit::GetNextMessageSize(const void* buffer, 180 bool MessageInTransit::GetNextMessageSize(const void* buffer,
186 size_t buffer_size, 181 size_t buffer_size,
187 size_t* next_message_size) { 182 size_t* next_message_size) {
188 DCHECK(next_message_size); 183 DCHECK(next_message_size);
(...skipping 20 matching lines...) Expand all
209 dispatchers_ = dispatchers.Pass(); 204 dispatchers_ = dispatchers.Pass();
210 #ifndef NDEBUG 205 #ifndef NDEBUG
211 for (size_t i = 0; i < dispatchers_->size(); i++) 206 for (size_t i = 0; i < dispatchers_->size(); i++)
212 DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef()); 207 DCHECK(!(*dispatchers_)[i] || (*dispatchers_)[i]->HasOneRef());
213 #endif 208 #endif
214 } 209 }
215 210
216 void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) { 211 void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) {
217 DCHECK(channel); 212 DCHECK(channel);
218 DCHECK(!secondary_buffer_); 213 DCHECK(!secondary_buffer_);
219 CHECK_EQ(num_handles(),
220 dispatchers_ ? dispatchers_->size() : static_cast<size_t>(0));
221 214
222 if (!num_handles()) 215 const size_t num_handles = dispatchers_ ? dispatchers_->size() : 0;
216 if (!num_handles)
223 return; 217 return;
224 218
225 // The offset to the start of the (Mojo) handle table. 219 // The offset to the start of the (Mojo) handle table.
226 // TODO(vtl): Add a header to the secondary buffer. 220 // TODO(vtl): Add a header to the secondary buffer.
227 const size_t handle_table_start_offset = 0; 221 const size_t handle_table_start_offset = 0;
228 // The offset to the start of the serialized dispatcher data. 222 // The offset to the start of the serialized dispatcher data.
229 const size_t serialized_dispatcher_start_offset = 223 const size_t serialized_dispatcher_start_offset =
230 handle_table_start_offset + num_handles() * sizeof(HandleTableEntry); 224 handle_table_start_offset + num_handles * sizeof(HandleTableEntry);
231 // The size of the secondary buffer we'll add to this as we go along). 225 // The estimated size of the secondary buffer. We compute this estimate below.
232 size_t size = serialized_dispatcher_start_offset; 226 // It must be at least as big as the (eventual) actual size.
227 size_t estimated_size = serialized_dispatcher_start_offset;
233 size_t num_platform_handles = 0; 228 size_t num_platform_handles = 0;
234 #if DCHECK_IS_ON 229 #if DCHECK_IS_ON
235 std::vector<size_t> all_max_sizes(num_handles()); 230 std::vector<size_t> all_max_sizes(num_handles);
236 std::vector<size_t> all_max_platform_handles(num_handles()); 231 std::vector<size_t> all_max_platform_handles(num_handles);
237 #endif 232 #endif
238 for (size_t i = 0; i < num_handles(); i++) { 233 for (size_t i = 0; i < num_handles; i++) {
239 if (Dispatcher* dispatcher = (*dispatchers_)[i].get()) { 234 if (Dispatcher* dispatcher = (*dispatchers_)[i].get()) {
240 size_t max_size = 0; 235 size_t max_size = 0;
241 size_t max_platform_handles = 0; 236 size_t max_platform_handles = 0;
242 Dispatcher::MessageInTransitAccess::StartSerialize( 237 Dispatcher::MessageInTransitAccess::StartSerialize(
243 dispatcher, channel, &max_size, &max_platform_handles); 238 dispatcher, channel, &max_size, &max_platform_handles);
244 239
245 DCHECK_LE(max_size, kMaxSerializedDispatcherSize); 240 DCHECK_LE(max_size, kMaxSerializedDispatcherSize);
246 size += RoundUpMessageAlignment(max_size); 241 estimated_size += RoundUpMessageAlignment(max_size);
247 DCHECK_LE(size, kMaxSecondaryBufferSize); 242 DCHECK_LE(estimated_size, kMaxSecondaryBufferSize);
248 243
249 DCHECK_LE(max_platform_handles, 244 DCHECK_LE(max_platform_handles,
250 kMaxSerializedDispatcherPlatformHandles); 245 kMaxSerializedDispatcherPlatformHandles);
251 num_platform_handles += max_platform_handles; 246 num_platform_handles += max_platform_handles;
252 DCHECK_LE(num_platform_handles, kMaxPlatformHandles); 247 DCHECK_LE(num_platform_handles, kMaxPlatformHandles);
253 248
254 #if DCHECK_IS_ON 249 #if DCHECK_IS_ON
255 all_max_sizes[i] = max_size; 250 all_max_sizes[i] = max_size;
256 all_max_platform_handles[i] = max_platform_handles; 251 all_max_platform_handles[i] = max_platform_handles;
257 #endif 252 #endif
258 } 253 }
259 } 254 }
260 255
261 secondary_buffer_ = base::AlignedAlloc(size, kMessageAlignment); 256 secondary_buffer_.reset(static_cast<char*>(
262 secondary_buffer_size_ = static_cast<uint32_t>(size); 257 base::AlignedAlloc(estimated_size, kMessageAlignment)));
263 // Entirely clear out the secondary buffer, since then we won't have to worry 258 // Entirely clear out the secondary buffer, since then we won't have to worry
264 // about clearing padding or unused space (e.g., if a dispatcher fails to 259 // about clearing padding or unused space (e.g., if a dispatcher fails to
265 // serialize). 260 // serialize).
266 memset(secondary_buffer_, 0, size); 261 memset(secondary_buffer_.get(), 0, estimated_size);
267 262
268 if (num_platform_handles > 0) { 263 if (num_platform_handles > 0) {
269 DCHECK(!platform_handles_); 264 DCHECK(!platform_handles_);
270 platform_handles_.reset(new std::vector<embedder::PlatformHandle>()); 265 platform_handles_.reset(new std::vector<embedder::PlatformHandle>());
271 } 266 }
272 267
273 HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>( 268 HandleTableEntry* handle_table = reinterpret_cast<HandleTableEntry*>(
274 static_cast<char*>(secondary_buffer_) + handle_table_start_offset); 269 secondary_buffer_.get() + handle_table_start_offset);
275 size_t current_offset = serialized_dispatcher_start_offset; 270 size_t current_offset = serialized_dispatcher_start_offset;
276 for (size_t i = 0; i < num_handles(); i++) { 271 for (size_t i = 0; i < num_handles; i++) {
277 Dispatcher* dispatcher = (*dispatchers_)[i].get(); 272 Dispatcher* dispatcher = (*dispatchers_)[i].get();
278 if (!dispatcher) { 273 if (!dispatcher) {
279 COMPILE_ASSERT(Dispatcher::kTypeUnknown == 0, 274 COMPILE_ASSERT(Dispatcher::kTypeUnknown == 0,
280 value_of_Dispatcher_kTypeUnknown_must_be_zero); 275 value_of_Dispatcher_kTypeUnknown_must_be_zero);
281 continue; 276 continue;
282 } 277 }
283 278
284 #if DCHECK_IS_ON 279 #if DCHECK_IS_ON
285 size_t old_platform_handles_size = 280 size_t old_platform_handles_size =
286 platform_handles_ ? platform_handles_->size() : 0; 281 platform_handles_ ? platform_handles_->size() : 0;
287 #endif 282 #endif
288 283
289 void* destination = static_cast<char*>(secondary_buffer_) + current_offset; 284 void* destination = secondary_buffer_.get() + current_offset;
290 size_t actual_size = 0; 285 size_t actual_size = 0;
291 if (Dispatcher::MessageInTransitAccess::EndSerializeAndClose( 286 if (Dispatcher::MessageInTransitAccess::EndSerializeAndClose(
292 dispatcher, channel, destination, &actual_size, 287 dispatcher, channel, destination, &actual_size,
293 platform_handles_.get())) { 288 platform_handles_.get())) {
294 handle_table[i].type = static_cast<int32_t>(dispatcher->GetType()); 289 handle_table[i].type = static_cast<int32_t>(dispatcher->GetType());
295 handle_table[i].offset = static_cast<uint32_t>(current_offset); 290 handle_table[i].offset = static_cast<uint32_t>(current_offset);
296 handle_table[i].size = static_cast<uint32_t>(actual_size); 291 handle_table[i].size = static_cast<uint32_t>(actual_size);
297 292
298 #if DCHECK_IS_ON 293 #if DCHECK_IS_ON
299 DCHECK_LE(actual_size, all_max_sizes[i]); 294 DCHECK_LE(actual_size, all_max_sizes[i]);
300 DCHECK_LE(platform_handles_ ? (platform_handles_->size() - 295 DCHECK_LE(platform_handles_ ? (platform_handles_->size() -
301 old_platform_handles_size) : 0, 296 old_platform_handles_size) : 0,
302 all_max_platform_handles[i]); 297 all_max_platform_handles[i]);
303 #endif 298 #endif
304 } else { 299 } else {
305 // Nothing to do on failure, since |secondary_buffer_| was cleared, and 300 // Nothing to do on failure, since |secondary_buffer_| was cleared, and
306 // |kTypeUnknown| is zero. The handle was simply closed. 301 // |kTypeUnknown| is zero. The handle was simply closed.
307 LOG(ERROR) << "Failed to serialize handle to remote message pipe"; 302 LOG(ERROR) << "Failed to serialize handle to remote message pipe";
308 } 303 }
309 304
310 current_offset += RoundUpMessageAlignment(actual_size); 305 current_offset += RoundUpMessageAlignment(actual_size);
311 DCHECK_LE(current_offset, size); 306 DCHECK_LE(current_offset, estimated_size);
312 DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0, 307 DCHECK_LE(platform_handles_ ? platform_handles_->size() : 0,
313 num_platform_handles); 308 num_platform_handles);
314 } 309 }
315 310
311 // There's no aligned realloc, so it's no good way to release unused space (if
darin (slow to review) 2014/05/01 04:13:50 would it be worth trying to invent an aligned real
312 // we overshot our estimated space requirements).
313 secondary_buffer_size_ = current_offset;
314
315 // The dispatchers (which we "owned") were closed. We can dispose of them now.
316 dispatchers_.reset();
317
318 // Update the sizes in the message header.
316 UpdateTotalSize(); 319 UpdateTotalSize();
317 } 320 }
318 321
319 // Note: The message's secondary buffer should have been checked by calling 322 // Note: The message's secondary buffer should have been checked by calling
320 // |View::IsValid()| (on the |View|) first. 323 // |View::IsValid()| (on the |View|) first.
321 void MessageInTransit::DeserializeDispatchers(Channel* channel) { 324 void MessageInTransit::DeserializeDispatchers(Channel* channel) {
322 DCHECK(!dispatchers_); 325 DCHECK(!dispatchers_);
323 326
324 // Already checked by |View::IsValid()|: 327 // Already checked by |View::IsValid()|:
325 DCHECK_LE(num_handles(), kMaxMessageNumHandles); 328 DCHECK_LE(num_handles(), kMaxMessageNumHandles);
326 329
327 if (!num_handles()) 330 if (!num_handles())
328 return; 331 return;
329 332
330 dispatchers_.reset( 333 dispatchers_.reset(
331 new std::vector<scoped_refptr<Dispatcher> >(num_handles())); 334 new std::vector<scoped_refptr<Dispatcher> >(num_handles()));
332 335
333 size_t handle_table_size = num_handles() * sizeof(HandleTableEntry); 336 size_t handle_table_size = num_handles() * sizeof(HandleTableEntry);
334 // Already checked by |View::IsValid()|: 337 // Already checked by |View::IsValid()|:
335 DCHECK_LE(handle_table_size, secondary_buffer_size_); 338 DCHECK_LE(handle_table_size, secondary_buffer_size_);
336 339
337 const HandleTableEntry* handle_table = 340 const HandleTableEntry* handle_table =
338 static_cast<const HandleTableEntry*>(secondary_buffer_); 341 reinterpret_cast<const HandleTableEntry*>(secondary_buffer_.get());
339 for (size_t i = 0; i < num_handles(); i++) { 342 for (size_t i = 0; i < num_handles(); i++) {
340 size_t offset = handle_table[i].offset; 343 size_t offset = handle_table[i].offset;
341 size_t size = handle_table[i].size; 344 size_t size = handle_table[i].size;
342 // Already checked by |View::IsValid()|: 345 // Already checked by |View::IsValid()|:
343 DCHECK_EQ(offset % kMessageAlignment, 0u); 346 DCHECK_EQ(offset % kMessageAlignment, 0u);
344 DCHECK_LE(offset, secondary_buffer_size_); 347 DCHECK_LE(offset, secondary_buffer_size_);
345 DCHECK_LE(offset + size, secondary_buffer_size_); 348 DCHECK_LE(offset + size, secondary_buffer_size_);
346 349
347 const void* source = static_cast<const char*>(secondary_buffer_) + offset; 350 const void* source = secondary_buffer_.get() + offset;
348 (*dispatchers_)[i] = Dispatcher::MessageInTransitAccess::Deserialize( 351 (*dispatchers_)[i] = Dispatcher::MessageInTransitAccess::Deserialize(
349 channel, handle_table[i].type, source, size); 352 channel, handle_table[i].type, source, size);
350 } 353 }
351 } 354 }
352 355
353 // Validates the secondary buffer. Returns null on success, or a human-readable 356 // Validates the secondary buffer. Returns null on success, or a human-readable
354 // error message on error. 357 // error message on error.
355 // static 358 // static
356 const char* MessageInTransit::ValidateSecondaryBuffer( 359 const char* MessageInTransit::ValidateSecondaryBuffer(
357 size_t num_handles, 360 size_t num_handles,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 407
405 void MessageInTransit::UpdateTotalSize() { 408 void MessageInTransit::UpdateTotalSize() {
406 DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u); 409 DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
407 DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u); 410 DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u);
408 header()->total_size = 411 header()->total_size =
409 static_cast<uint32_t>(main_buffer_size_ + secondary_buffer_size_); 412 static_cast<uint32_t>(main_buffer_size_ + secondary_buffer_size_);
410 } 413 }
411 414
412 } // namespace system 415 } // namespace system
413 } // namespace mojo 416 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/system/message_in_transit.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698