| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/wait_set_dispatcher.h" | 5 #include "mojo/edk/system/wait_set_dispatcher.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "mojo/edk/system/configuration.h" | 10 #include "mojo/edk/system/configuration.h" |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 dispatcher->RemoveAwakable(true, this, cookie, nullptr); | 190 dispatcher->RemoveAwakable(true, this, cookie, nullptr); |
| 191 } | 191 } |
| 192 return MOJO_RESULT_INVALID_ARGUMENT; | 192 return MOJO_RESULT_INVALID_ARGUMENT; |
| 193 } | 193 } |
| 194 | 194 |
| 195 DCHECK(entries_.find(cookie) != entries_.end()); | 195 DCHECK(entries_.find(cookie) != entries_.end()); |
| 196 DCHECK_EQ(entries_[cookie].get(), entry); | 196 DCHECK_EQ(entries_[cookie].get(), entry); |
| 197 | 197 |
| 198 if (result == MOJO_RESULT_ALREADY_EXISTS) { | 198 if (result == MOJO_RESULT_ALREADY_EXISTS) { |
| 199 // It was added, but the wait condition is already satisfied. | 199 // It was added, but the wait condition is already satisfied. |
| 200 AddPossiblyTriggeredNoLock(entry, Entry::TriggerState::POSSIBLY_SATISFIED); | 200 AddPossiblyTriggeredNoLock(entry, Entry::TriggerState::SATISFIED); |
| 201 } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { | 201 } else if (result == MOJO_RESULT_FAILED_PRECONDITION) { |
| 202 // The condition is never-satisfiable. Leave a zombie entry (i.e., leave | 202 AddPossiblyTriggeredNoLock(entry, Entry::TriggerState::UNSATISFIABLE); |
| 203 // |dispatcher| null). | |
| 204 mutex().Unlock(); | |
| 205 return MOJO_RESULT_OK; | |
| 206 } else if (result != MOJO_RESULT_OK) { | 203 } else if (result != MOJO_RESULT_OK) { |
| 207 size_t num_erased = entries_.erase(cookie); | 204 size_t num_erased = entries_.erase(cookie); |
| 208 DCHECK_EQ(num_erased, 1u); | 205 DCHECK_EQ(num_erased, 1u); |
| 209 mutex().Unlock(); | 206 mutex().Unlock(); |
| 210 return result; | 207 return result; |
| 211 } | 208 } |
| 212 | 209 |
| 213 // Update the entry to actually have the dispatcher. | 210 // Update the entry to actually have the dispatcher. |
| 214 entry->dispatcher = std::move(dispatcher); | 211 entry->dispatcher = std::move(dispatcher); |
| 215 | 212 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 UserPointer<uint32_t> max_results) { | 250 UserPointer<uint32_t> max_results) { |
| 254 MutexLocker locker(&mutex()); | 251 MutexLocker locker(&mutex()); |
| 255 if (is_closed_no_lock()) | 252 if (is_closed_no_lock()) |
| 256 return MOJO_RESULT_INVALID_ARGUMENT; | 253 return MOJO_RESULT_INVALID_ARGUMENT; |
| 257 | 254 |
| 258 // TODO(vtl) | 255 // TODO(vtl) |
| 259 NOTIMPLEMENTED(); | 256 NOTIMPLEMENTED(); |
| 260 return MOJO_RESULT_UNIMPLEMENTED; | 257 return MOJO_RESULT_UNIMPLEMENTED; |
| 261 } | 258 } |
| 262 | 259 |
| 263 bool WaitSetDispatcher::Awake(uint64_t context, | 260 void WaitSetDispatcher::Awake(uint64_t context, |
| 264 AwakeReason reason, | 261 AwakeReason reason, |
| 265 const HandleSignalsState& signals_state) { | 262 const HandleSignalsState& signals_state) { |
| 266 MutexLocker locker(&mutex()); | 263 MutexLocker locker(&mutex()); |
| 267 | 264 |
| 268 if (is_closed_no_lock()) { | 265 if (is_closed_no_lock()) { |
| 269 // See |CloseImplNoLock()|: This case may occur while we're unlocked in | 266 // See |CloseImplNoLock()|: This case may occur while we're unlocked in |
| 270 // |CloseImplNoLock()| (after that, we will have been removed from all the | 267 // |CloseImplNoLock()| (after that, we will have been removed from all the |
| 271 // awakable lists, so |Awake()| should no longer be called). We may as well | 268 // awakable lists, so |Awake()| should no longer be called). |
| 272 // return false here, which will automatically remove ourselves from the | 269 return; |
| 273 // awakable list (|CloseImplNoLock()| will call |RemoveAwakable()| anyway, | |
| 274 // but that's OK). | |
| 275 return false; | |
| 276 } | 270 } |
| 277 | 271 |
| 278 auto it = entries_.find(context); | 272 auto it = entries_.find(context); |
| 279 DCHECK(it != entries_.end()); | 273 DCHECK(it != entries_.end()); |
| 280 const auto& entry = it->second; | 274 const auto& entry = it->second; |
| 275 // We should only ever get at most one "closed" (cancelled). |
| 276 DCHECK_NE(static_cast<int>(entry->trigger_state), |
| 277 static_cast<int>(Entry::TriggerState::CLOSED)); |
| 281 switch (reason) { | 278 switch (reason) { |
| 282 case AwakeReason::SATISFIED: | 279 case AwakeReason::SATISFIED: |
| 283 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { | 280 case AwakeReason::UNSATISFIABLE: |
| 284 AddPossiblyTriggeredNoLock(entry.get(), | 281 // We shouldn't see these since we're used as a persistent |Awakable|. |
| 285 Entry::TriggerState::POSSIBLY_SATISFIED); | 282 NOTREACHED(); |
| 283 // Fall through. |
| 284 case AwakeReason::CHANGED: |
| 285 if (signals_state.satisfies(entry->signals)) { |
| 286 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { |
| 287 AddPossiblyTriggeredNoLock(entry.get(), |
| 288 Entry::TriggerState::SATISFIED); |
| 289 } else { |
| 290 entry->trigger_state = Entry::TriggerState::SATISFIED; |
| 291 } |
| 292 } else if (!signals_state.can_satisfy(entry->signals)) { |
| 293 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { |
| 294 AddPossiblyTriggeredNoLock(entry.get(), |
| 295 Entry::TriggerState::UNSATISFIABLE); |
| 296 } else { |
| 297 entry->trigger_state = Entry::TriggerState::UNSATISFIABLE; |
| 298 } |
| 299 } else { |
| 300 if (entry->trigger_state != Entry::TriggerState::NOT_TRIGGERED) |
| 301 RemovePossiblyTriggeredNoLock(entry.get()); |
| 286 } | 302 } |
| 287 return true; | 303 break; |
| 288 case AwakeReason::UNSATISFIABLE: | |
| 289 // Never satisfiable. | |
| 290 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { | |
| 291 AddPossiblyTriggeredNoLock(entry.get(), | |
| 292 Entry::TriggerState::NEVER_SATISFIABLE); | |
| 293 } else { | |
| 294 if (entry->trigger_state == Entry::TriggerState::POSSIBLY_SATISFIED) { | |
| 295 entry->trigger_state = Entry::TriggerState::NEVER_SATISFIABLE; | |
| 296 } else { | |
| 297 // It's possible to get repeated "never satisfiable" triggers, but we | |
| 298 // shouldn't get anything after "closed". | |
| 299 DCHECK_NE(static_cast<int>(entry->trigger_state), | |
| 300 static_cast<int>(Entry::TriggerState::CLOSED)); | |
| 301 } | |
| 302 } | |
| 303 // Due to some action on some other thread, it may become satisfiable | |
| 304 // again, so continue to be awoken. | |
| 305 return true; | |
| 306 case AwakeReason::CANCELLED: | 304 case AwakeReason::CANCELLED: |
| 307 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { | 305 if (entry->trigger_state == Entry::TriggerState::NOT_TRIGGERED) { |
| 308 AddPossiblyTriggeredNoLock(entry.get(), Entry::TriggerState::CLOSED); | 306 AddPossiblyTriggeredNoLock(entry.get(), Entry::TriggerState::CLOSED); |
| 309 } else { | 307 } else { |
| 310 // We should only ever get at most one "closed". | |
| 311 DCHECK_NE(static_cast<int>(entry->trigger_state), | |
| 312 static_cast<int>(Entry::TriggerState::CLOSED)); | |
| 313 entry->trigger_state = Entry::TriggerState::CLOSED; | 308 entry->trigger_state = Entry::TriggerState::CLOSED; |
| 314 } | 309 } |
| 315 entry->dispatcher = nullptr; | 310 entry->dispatcher = nullptr; |
| 316 return false; | 311 break; |
| 317 } | 312 } |
| 318 return false; | |
| 319 } | 313 } |
| 320 | 314 |
| 321 void WaitSetDispatcher::AddPossiblyTriggeredNoLock( | 315 void WaitSetDispatcher::AddPossiblyTriggeredNoLock( |
| 322 Entry* entry, | 316 Entry* entry, |
| 323 Entry::TriggerState new_trigger_state) { | 317 Entry::TriggerState new_trigger_state) { |
| 324 DCHECK_EQ(static_cast<int>(entry->trigger_state), | 318 DCHECK_EQ(static_cast<int>(entry->trigger_state), |
| 325 static_cast<int>(Entry::TriggerState::NOT_TRIGGERED)); | 319 static_cast<int>(Entry::TriggerState::NOT_TRIGGERED)); |
| 326 DCHECK(!entry->possibly_triggered_previous); | 320 DCHECK(!entry->possibly_triggered_previous); |
| 327 DCHECK(!entry->possibly_triggered_next); | 321 DCHECK(!entry->possibly_triggered_next); |
| 328 DCHECK_NE(static_cast<int>(new_trigger_state), | 322 DCHECK_NE(static_cast<int>(new_trigger_state), |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 entry->possibly_triggered_next->possibly_triggered_previous = | 360 entry->possibly_triggered_next->possibly_triggered_previous = |
| 367 entry->possibly_triggered_previous; | 361 entry->possibly_triggered_previous; |
| 368 } | 362 } |
| 369 | 363 |
| 370 entry->possibly_triggered_previous = nullptr; | 364 entry->possibly_triggered_previous = nullptr; |
| 371 entry->possibly_triggered_next = nullptr; | 365 entry->possibly_triggered_next = nullptr; |
| 372 } | 366 } |
| 373 | 367 |
| 374 } // namespace system | 368 } // namespace system |
| 375 } // namespace mojo | 369 } // namespace mojo |
| OLD | NEW |