OLD | NEW |
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/core_impl.h" | 5 #include "mojo/system/core_impl.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "mojo/system/dispatcher.h" | 10 #include "mojo/system/dispatcher.h" |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 entries[i]->busy = true; | 237 entries[i]->busy = true; |
238 | 238 |
239 // Try to take the lock. | 239 // Try to take the lock. |
240 if (!entries[i]->dispatcher->lock().Try()) { | 240 if (!entries[i]->dispatcher->lock().Try()) { |
241 // Unset the busy flag (since it won't be unset below). | 241 // Unset the busy flag (since it won't be unset below). |
242 entries[i]->busy = false; | 242 entries[i]->busy = false; |
243 error_result = MOJO_RESULT_BUSY; | 243 error_result = MOJO_RESULT_BUSY; |
244 break; | 244 break; |
245 } | 245 } |
246 | 246 |
| 247 // We shouldn't race with things that close dispatchers, since closing can |
| 248 // only take place either under |handle_table_lock_| or when the handle is |
| 249 // marked as busy. |
| 250 DCHECK(!entries[i]->dispatcher->is_closed_no_lock()); |
| 251 |
247 // Hang on to the pointer to the dispatcher (which we'll need to release | 252 // Hang on to the pointer to the dispatcher (which we'll need to release |
248 // the lock without going through the handle table). | 253 // the lock without going through the handle table). |
249 dispatchers[i] = entries[i]->dispatcher; | 254 dispatchers[i] = entries[i]->dispatcher; |
250 } | 255 } |
251 if (i < num_handles) { | 256 if (i < num_handles) { |
252 DCHECK_NE(error_result, MOJO_RESULT_INTERNAL); | 257 DCHECK_NE(error_result, MOJO_RESULT_INTERNAL); |
253 | 258 |
254 // Unset the busy flags and release the locks. | 259 // Unset the busy flags and release the locks. |
255 for (uint32_t j = 0; j < i; j++) { | 260 for (uint32_t j = 0; j < i; j++) { |
256 DCHECK(entries[j]->busy); | 261 DCHECK(entries[j]->busy); |
(...skipping 17 matching lines...) Expand all Loading... |
274 | 279 |
275 if (rv == MOJO_RESULT_OK) { | 280 if (rv == MOJO_RESULT_OK) { |
276 base::AutoLock locker(handle_table_lock_); | 281 base::AutoLock locker(handle_table_lock_); |
277 | 282 |
278 // Succeeded, so the handles should be removed from the handle table. (The | 283 // Succeeded, so the handles should be removed from the handle table. (The |
279 // transferring to new dispatchers/closing must have already been done.) | 284 // transferring to new dispatchers/closing must have already been done.) |
280 for (uint32_t i = 0; i < num_handles; i++) { | 285 for (uint32_t i = 0; i < num_handles; i++) { |
281 HandleTableMap::iterator it = handle_table_.find(handles[i]); | 286 HandleTableMap::iterator it = handle_table_.find(handles[i]); |
282 DCHECK(it != handle_table_.end()); | 287 DCHECK(it != handle_table_.end()); |
283 DCHECK(it->second.busy); | 288 DCHECK(it->second.busy); |
| 289 it->second.busy = false; // For the sake of a |DCHECK()|. |
284 handle_table_.erase(it); | 290 handle_table_.erase(it); |
285 } | 291 } |
286 } else { | 292 } else { |
287 base::AutoLock locker(handle_table_lock_); | 293 base::AutoLock locker(handle_table_lock_); |
288 | 294 |
289 // Failed, so the handles should go back to their normal state. | 295 // Failed, so the handles should go back to their normal state. |
290 for (uint32_t i = 0; i < num_handles; i++) { | 296 for (uint32_t i = 0; i < num_handles; i++) { |
291 HandleTableMap::iterator it = handle_table_.find(handles[i]); | 297 HandleTableMap::iterator it = handle_table_.find(handles[i]); |
292 DCHECK(it != handle_table_.end()); | 298 DCHECK(it != handle_table_.end()); |
293 DCHECK(it->second.busy); | 299 DCHECK(it->second.busy); |
294 it->second.busy = false; | 300 it->second.busy = false; |
295 } | 301 } |
296 } | 302 } |
297 | 303 |
298 return rv; | 304 return rv; |
299 } | 305 } |
300 | 306 |
301 MojoResult CoreImpl::ReadMessage( | 307 MojoResult CoreImpl::ReadMessage( |
302 MojoHandle handle, | 308 MojoHandle handle, |
303 void* bytes, uint32_t* num_bytes, | 309 void* bytes, uint32_t* num_bytes, |
304 MojoHandle* handles, uint32_t* num_handles, | 310 MojoHandle* handles, uint32_t* num_handles, |
305 MojoReadMessageFlags flags) { | 311 MojoReadMessageFlags flags) { |
306 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); | 312 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(handle)); |
307 if (!dispatcher.get()) | 313 if (!dispatcher.get()) |
308 return MOJO_RESULT_INVALID_ARGUMENT; | 314 return MOJO_RESULT_INVALID_ARGUMENT; |
309 | 315 |
310 uint32_t max_num_dispatchers = 0; | |
311 if (num_handles) { | 316 if (num_handles) { |
312 if (!VerifyUserPointer<uint32_t>(num_handles, 1)) | 317 if (!VerifyUserPointer<uint32_t>(num_handles, 1)) |
313 return MOJO_RESULT_INVALID_ARGUMENT; | 318 return MOJO_RESULT_INVALID_ARGUMENT; |
314 if (!VerifyUserPointer<MojoHandle>(handles, *num_handles)) | 319 if (!VerifyUserPointer<MojoHandle>(handles, *num_handles)) |
315 return MOJO_RESULT_INVALID_ARGUMENT; | 320 return MOJO_RESULT_INVALID_ARGUMENT; |
316 max_num_dispatchers = *num_handles; | |
317 } | 321 } |
318 | 322 |
319 // Easy case: won't receive any handles. | 323 // Easy case: won't receive any handles. |
320 if (max_num_dispatchers == 0) | 324 if (!num_handles || *num_handles == 0) |
321 return dispatcher->ReadMessage(bytes, num_bytes, 0, NULL, flags); | 325 return dispatcher->ReadMessage(bytes, num_bytes, 0, NULL, flags); |
322 | 326 |
323 std::vector<scoped_refptr<Dispatcher> > dispatchers; | 327 std::vector<scoped_refptr<Dispatcher> > dispatchers; |
324 MojoResult rv = dispatcher->ReadMessage(bytes, num_bytes, | 328 MojoResult rv = dispatcher->ReadMessage(bytes, num_bytes, |
325 max_num_dispatchers, &dispatchers, | 329 &dispatchers, num_handles, |
326 flags); | 330 flags); |
327 if (!dispatchers.empty()) { | 331 if (!dispatchers.empty()) { |
328 DCHECK_EQ(rv, MOJO_RESULT_OK); | 332 DCHECK_EQ(rv, MOJO_RESULT_OK); |
329 | 333 DCHECK(num_handles); |
330 *num_handles = static_cast<uint32_t>(dispatchers.size()); | 334 DCHECK_LE(dispatchers.size(), static_cast<size_t>(*num_handles)); |
331 DCHECK_LE(*num_handles, max_num_dispatchers); | |
332 | 335 |
333 base::AutoLock locker(handle_table_lock_); | 336 base::AutoLock locker(handle_table_lock_); |
334 | 337 |
335 for (size_t i = 0; i < dispatchers.size(); i++) { | 338 for (size_t i = 0; i < dispatchers.size(); i++) { |
336 // TODO(vtl): What should we do if we hit the maximum handle table size | 339 // TODO(vtl): What should we do if we hit the maximum handle table size |
337 // here? Currently, we'll just fill in those handles with | 340 // here? Currently, we'll just fill in those handles with |
338 // |MOJO_HANDLE_INVALID| (and return success anyway). | 341 // |MOJO_HANDLE_INVALID| (and return success anyway). |
339 handles[i] = AddDispatcherNoLock(dispatchers[i]); | 342 handles[i] = AddDispatcherNoLock(dispatchers[i]); |
340 } | 343 } |
341 } | 344 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be | 437 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be |
435 // destroyed, but this would still be required if the waiter were in TLS.) | 438 // destroyed, but this would still be required if the waiter were in TLS.) |
436 for (i = 0; i < num_added; i++) | 439 for (i = 0; i < num_added; i++) |
437 dispatchers[i]->RemoveWaiter(&waiter); | 440 dispatchers[i]->RemoveWaiter(&waiter); |
438 | 441 |
439 return rv; | 442 return rv; |
440 } | 443 } |
441 | 444 |
442 } // namespace system | 445 } // namespace system |
443 } // namespace mojo | 446 } // namespace mojo |
OLD | NEW |