Deadlock detection in a wait-for graph A wrapper for recursive deadlock_search() - prepares deadlock_arg structure, invokes deadlock_search(), increments statistics, notifies the victim. @param thd thread that is going to wait. Deadlock is detected if, while walking the graph, we reach a thread that is waiting on thd @param block
| 854 | @param max_depth search depth limit |
| 855 | */ |
| 856 | static int deadlock(WT_THD *thd, WT_THD *blocker, uint depth, |
| 857 | uint max_depth) |
| 858 | { |
| 859 | struct deadlock_arg arg= {thd, max_depth, 0, 0}; |
| 860 | int ret; |
| 861 | DBUG_ENTER("deadlock"); |
| 862 | DBUG_ASSERT(depth < 2); |
| 863 | ret= deadlock_search(&arg, blocker, depth); |
| 864 | if (ret == WT_DEPTH_EXCEEDED) |
| 865 | { |
| 866 | increment_cycle_stats(WT_CYCLE_STATS, max_depth == |
| 867 | *thd->deadlock_search_depth_long); |
| 868 | ret= WT_OK; |
| 869 | } |
| 870 | /* |
| 871 | if we started with depth==1, blocker was never considered for a victim |
| 872 | in deadlock_search(). Do it here. |
| 873 | */ |
| 874 | if (ret == WT_DEADLOCK && depth) |
| 875 | change_victim(blocker, &arg); |
| 876 | if (arg.last_locked_rc) |
| 877 | { |
| 878 | /* |
| 879 | Special return code if there's nobody to wait for. |
| 880 | |
| 881 | depth == 0 means that we start the search from thd (thd == blocker). |
| 882 | ret == WT_OK means that no cycle was found and |
| 883 | arg.last_locked_rc == thd->waiting_for. |
| 884 | and arg.last_locked_rc->owners.elements == 0 means that |
| 885 | (applying the rule above) thd->waiting_for->owners.elements == 0, |
| 886 | and thd doesn't have anybody to wait for. |
| 887 | */ |
| 888 | if (depth == 0 && ret == WT_OK && arg.last_locked_rc->owners.elements == 0) |
| 889 | { |
| 890 | DBUG_ASSERT(thd == blocker); |
| 891 | DBUG_ASSERT(arg.last_locked_rc == thd->waiting_for); |
| 892 | ret= WT_FREE_TO_GO; |
| 893 | } |
| 894 | rc_unlock(arg.last_locked_rc); |
| 895 | } |
| 896 | /* notify the victim, if appropriate */ |
| 897 | if (ret == WT_DEADLOCK && arg.victim != thd) |
| 898 | { |
| 899 | DBUG_PRINT("wt", ("killing %s", arg.victim->name)); |
| 900 | arg.victim->killed= 1; |
| 901 | mysql_cond_broadcast(&arg.victim->waiting_for->cond); |
| 902 | rc_unlock(arg.victim->waiting_for); |
| 903 | ret= WT_OK; |
| 904 | } |
| 905 | DBUG_RETURN(ret); |
| 906 | } |
| 907 | |
| 908 | |
| 909 | /** |
no test coverage detected