| 8696 | */ |
| 8697 | |
| 8698 | void |
| 8699 | wait_for_commit::wakeup_subsequent_commits2(int wakeup_error) |
| 8700 | { |
| 8701 | wait_for_commit *waiter; |
| 8702 | |
| 8703 | if (unlikely(wakeup_blocked)) |
| 8704 | return; |
| 8705 | |
| 8706 | mysql_mutex_lock(&LOCK_wait_commit); |
| 8707 | wakeup_subsequent_commits_running= true; |
| 8708 | waiter= subsequent_commits_list; |
| 8709 | subsequent_commits_list= NULL; |
| 8710 | mysql_mutex_unlock(&LOCK_wait_commit); |
| 8711 | |
| 8712 | while (waiter) |
| 8713 | { |
| 8714 | /* |
| 8715 | Important: we must grab the next pointer before waking up the waiter; |
| 8716 | once the wakeup is done, the field could be invalidated at any time. |
| 8717 | */ |
| 8718 | wait_for_commit *next= waiter->next_subsequent_commit; |
| 8719 | waiter->wakeup(wakeup_error); |
| 8720 | waiter= next; |
| 8721 | } |
| 8722 | |
| 8723 | /* |
| 8724 | We need a full memory barrier between walking the list above, and clearing |
| 8725 | the flag wakeup_subsequent_commits_running below. This barrier is needed |
| 8726 | to ensure that no other thread will start to modify the list pointers |
| 8727 | before we are done traversing the list. |
| 8728 | |
| 8729 | But wait_for_commit::wakeup() does a full memory barrier already (it locks |
| 8730 | a mutex), so no extra explicit barrier is needed here. |
| 8731 | */ |
| 8732 | wakeup_subsequent_commits_running= false; |
| 8733 | DBUG_EXECUTE_IF("inject_wakeup_subsequent_commits_sleep", my_sleep(21000);); |
| 8734 | } |
| 8735 | |
| 8736 | |
| 8737 | /* Cancel a previously registered wait for another THD to commit before us. */ |