You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
12 KiB

26 years ago
26 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
26 years ago
26 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
26 years ago
26 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
26 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
26 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
26 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
26 years ago
26 years ago
26 years ago
26 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
A follow-up to the patch for bug #56405 "Deadlock in the MDL deadlock detector". This patch addresses performance regression in OLTP_RO/MyISAM test on Windows introduced by the fix for bug #56405. Thus it makes original patch acceptable as a solution for bug #56585 "Slowdown of readonly sysbench benchmarks (e.g point_select) on Windows 5.5". With this patch, MySQL will use native Windows condition variables and reader-writer locks if they are supported by the OS. This speeds up MyISAM and the effect comes mostly from using native rwlocks. Native conditions improve scalability with higher number of concurrent users in other situations, e.g for prlocks. Benchmark numbers for this patch as measured on Win2008R2 quad core machine are attached to the bug report. ( direct link http://bugs.mysql.com/file.php?id=15883 ) Note that currently we require at least Windows7/WS2008R2 for reader-writer locks, even though native rwlock is available also on Vista. Reason is that "trylock" APIs are missing on Vista, and trylock is used in the server (in a single place in query cache). While this patch could have been written differently, to enable the native rwlock optimization also on Vista/WS2008 (e.g using native locks everywhere but portable implementation in query cache), this would come at the expense of the code clarity, as it would introduce a new "try-able" rwlock type, to handle Vista case. Another way to improve performance for the special case (OLTP_RO/MYISAM/Vista) would be to eliminate "trylock" usage from server, but this is outside of the scope here. Native conditions variables are used beginning with Vista though the effect of using condition variables alone is not measurable in this benchmark. But when used together with native rwlocks on Win7, native conditions improve performance in high-concurrency OLTP_RO/MyISAM (128 and more sysbench users).
15 years ago
26 years ago
26 years ago
26 years ago
26 years ago
26 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
A better fix for bug #56405 "Deadlock in the MDL deadlock detector" that doesn't introduce bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors". Deadlock could have occurred when workload containing a mix of DML, DDL and FLUSH TABLES statements affecting the same set of tables was executed in a heavily concurrent environment. This deadlock occurred when several connections tried to perform deadlock detection in the metadata locking subsystem. The first connection started traversing wait-for graph, encountered a sub-graph representing a wait for flush, acquired LOCK_open and dived into sub-graph inspection. Then it encountered sub-graph corresponding to wait for metadata lock and blocked while trying to acquire a rd-lock on MDL_lock::m_rwlock, since some,other thread had a wr-lock on it. When this wr-lock was released it could have happened (if there was another pending wr-lock against this rwlock) that the rd-lock from the first connection was left unsatisfied but at the same time the new rd-lock request from the second connection sneaked in and was satisfied (for this to be possible the second rd-request should come exactly after the wr-lock is released but before pending the wr-lock manages to grab rwlock, which is possible both on Linux and in our own rwlock implementation). If this second connection continued traversing the wait-for graph and encountered a sub-graph representing a wait for flush it tried to acquire LOCK_open and thus the deadlock was created. The previous patch tried to workaround this problem by not allowing the deadlock detector to lock LOCK_open mutex if some other thread doing deadlock detection already owns it and current search depth is greater than 0. Instead deadlock was reported. As a result it has introduced bug #56715. This patch solves this problem in a different way. It introduces a new rw_pr_lock_t implementation to be used by MDL subsystem instead of one based on Linux rwlocks or our own rwlock implementation. This new implementation never allows situation in which an rwlock is rd-locked and there is a blocked pending rd-lock. Thus the situation which has caused this bug becomes impossible with this implementation. Due to fact that this implementation is optimized for wr-lock/unlock scenario which is most common in the MDL subsystem it doesn't introduce noticeable performance regressions in sysbench tests. Moreover it significantly improves situation for POINT_SELECT test when many connections are used. No test case is provided as this bug is very hard to repeat in MTR environment but is repeatable with the help of RQG tests. This patch also doesn't include a test for bug #56715 "Concurrent transactions + FLUSH result in sporadical unwarranted deadlock errors" as it takes too much time to be run as part of normal test-suite runs.
15 years ago
  1. /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation; version 2 of the License.
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License
  10. along with this program; if not, write to the Free Software
  11. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
  12. /* Synchronization - readers / writer thread locks */
  13. #include "mysys_priv.h"
  14. #if defined(NEED_MY_RW_LOCK)
  15. #include <errno.h>
  16. #ifdef _WIN32
  17. static BOOL have_srwlock= FALSE;
  18. /* Prototypes and function pointers for windows functions */
  19. typedef VOID (WINAPI* srw_func) (PSRWLOCK SRWLock);
  20. typedef BOOL (WINAPI* srw_bool_func) (PSRWLOCK SRWLock);
  21. static srw_func my_InitializeSRWLock;
  22. static srw_func my_AcquireSRWLockExclusive;
  23. static srw_func my_ReleaseSRWLockExclusive;
  24. static srw_func my_AcquireSRWLockShared;
  25. static srw_func my_ReleaseSRWLockShared;
  26. static srw_bool_func my_TryAcquireSRWLockExclusive;
  27. static srw_bool_func my_TryAcquireSRWLockShared;
  28. /**
  29. Check for presence of Windows slim reader writer lock function.
  30. Load function pointers.
  31. */
  32. static void check_srwlock_availability(void)
  33. {
  34. HMODULE module= GetModuleHandle("kernel32");
  35. my_InitializeSRWLock= (srw_func) GetProcAddress(module,
  36. "InitializeSRWLock");
  37. my_AcquireSRWLockExclusive= (srw_func) GetProcAddress(module,
  38. "AcquireSRWLockExclusive");
  39. my_AcquireSRWLockShared= (srw_func) GetProcAddress(module,
  40. "AcquireSRWLockShared");
  41. my_ReleaseSRWLockExclusive= (srw_func) GetProcAddress(module,
  42. "ReleaseSRWLockExclusive");
  43. my_ReleaseSRWLockShared= (srw_func) GetProcAddress(module,
  44. "ReleaseSRWLockShared");
  45. my_TryAcquireSRWLockExclusive= (srw_bool_func) GetProcAddress(module,
  46. "TryAcquireSRWLockExclusive");
  47. my_TryAcquireSRWLockShared= (srw_bool_func) GetProcAddress(module,
  48. "TryAcquireSRWLockShared");
  49. /*
  50. We currently require TryAcquireSRWLockExclusive. This API is missing on
  51. Vista, this means SRWLock are only used starting with Win7.
  52. If "trylock" usage for rwlocks is eliminated from server codebase (it is used
  53. in a single place currently, in query cache), then SRWLock can be enabled on
  54. Vista too. In this case condition below needs to be changed to e.g check
  55. for my_InitializeSRWLock.
  56. */
  57. if (my_TryAcquireSRWLockExclusive)
  58. have_srwlock= TRUE;
  59. }
  60. static int srw_init(my_rw_lock_t *rwp)
  61. {
  62. my_InitializeSRWLock(&rwp->srwlock);
  63. rwp->have_exclusive_srwlock = FALSE;
  64. return 0;
  65. }
  66. static int srw_rdlock(my_rw_lock_t *rwp)
  67. {
  68. my_AcquireSRWLockShared(&rwp->srwlock);
  69. return 0;
  70. }
  71. static int srw_tryrdlock(my_rw_lock_t *rwp)
  72. {
  73. if (!my_TryAcquireSRWLockShared(&rwp->srwlock))
  74. return EBUSY;
  75. return 0;
  76. }
  77. static int srw_wrlock(my_rw_lock_t *rwp)
  78. {
  79. my_AcquireSRWLockExclusive(&rwp->srwlock);
  80. rwp->have_exclusive_srwlock= TRUE;
  81. return 0;
  82. }
  83. static int srw_trywrlock(my_rw_lock_t *rwp)
  84. {
  85. if (!my_TryAcquireSRWLockExclusive(&rwp->srwlock))
  86. return EBUSY;
  87. rwp->have_exclusive_srwlock= TRUE;
  88. return 0;
  89. }
  90. static int srw_unlock(my_rw_lock_t *rwp)
  91. {
  92. if (rwp->have_exclusive_srwlock)
  93. {
  94. rwp->have_exclusive_srwlock= FALSE;
  95. my_ReleaseSRWLockExclusive(&rwp->srwlock);
  96. }
  97. else
  98. {
  99. my_ReleaseSRWLockShared(&rwp->srwlock);
  100. }
  101. return 0;
  102. }
  103. #endif /*_WIN32 */
  104. /*
  105. Source base from Sun Microsystems SPILT, simplified for MySQL use
  106. -- Joshua Chamas
  107. Some cleanup and additional code by Monty
  108. */
  109. /*
  110. * Multithreaded Demo Source
  111. *
  112. * Copyright (C) 1995 by Sun Microsystems, Inc.
  113. * All rights reserved.
  114. *
  115. * This file is a product of SunSoft, Inc. and is provided for
  116. * unrestricted use provided that this legend is included on all
  117. * media and as a part of the software program in whole or part.
  118. * Users may copy, modify or distribute this file at will.
  119. *
  120. * THIS FILE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
  121. * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  122. * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  123. *
  124. * This file is provided with no support and without any obligation on the
  125. * part of SunSoft, Inc. to assist in its use, correction, modification or
  126. * enhancement.
  127. *
  128. * SUNSOFT AND SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT
  129. * TO THE INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
  130. * FILE OR ANY PART THEREOF.
  131. *
  132. * IN NO EVENT WILL SUNSOFT OR SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
  133. * LOST REVENUE OR PROFITS OR OTHER SPECIAL, INDIRECT AND CONSEQUENTIAL
  134. * DAMAGES, EVEN IF THEY HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
  135. * DAMAGES.
  136. *
  137. * SunSoft, Inc.
  138. * 2550 Garcia Avenue
  139. * Mountain View, California 94043
  140. */
  141. int my_rw_init(my_rw_lock_t *rwp)
  142. {
  143. pthread_condattr_t cond_attr;
  144. #ifdef _WIN32
  145. /*
  146. Once initialization is used here rather than in my_init(), in order to
  147. - avoid my_init() pitfalls- (undefined order in which initialization should
  148. run)
  149. - be potentially useful C++ (static constructors)
  150. - just to simplify the API.
  151. Also, the overhead is of my_pthread_once is very small.
  152. */
  153. static my_pthread_once_t once_control= MY_PTHREAD_ONCE_INIT;
  154. my_pthread_once(&once_control, check_srwlock_availability);
  155. if (have_srwlock)
  156. return srw_init(rwp);
  157. #endif
  158. pthread_mutex_init( &rwp->lock, MY_MUTEX_INIT_FAST);
  159. pthread_condattr_init( &cond_attr );
  160. pthread_cond_init( &rwp->readers, &cond_attr );
  161. pthread_cond_init( &rwp->writers, &cond_attr );
  162. pthread_condattr_destroy(&cond_attr);
  163. rwp->state = 0;
  164. rwp->waiters = 0;
  165. #ifdef SAFE_MUTEX
  166. rwp->write_thread = 0;
  167. #endif
  168. return(0);
  169. }
  170. int my_rw_destroy(my_rw_lock_t *rwp)
  171. {
  172. #ifdef _WIN32
  173. if (have_srwlock)
  174. return 0; /* no destroy function */
  175. #endif
  176. DBUG_ASSERT(rwp->state == 0);
  177. pthread_mutex_destroy( &rwp->lock );
  178. pthread_cond_destroy( &rwp->readers );
  179. pthread_cond_destroy( &rwp->writers );
  180. return(0);
  181. }
  182. int my_rw_rdlock(my_rw_lock_t *rwp)
  183. {
  184. #ifdef _WIN32
  185. if (have_srwlock)
  186. return srw_rdlock(rwp);
  187. #endif
  188. pthread_mutex_lock(&rwp->lock);
  189. /* active or queued writers */
  190. while (( rwp->state < 0 ) || rwp->waiters)
  191. pthread_cond_wait( &rwp->readers, &rwp->lock);
  192. rwp->state++;
  193. pthread_mutex_unlock(&rwp->lock);
  194. return(0);
  195. }
  196. int my_rw_tryrdlock(my_rw_lock_t *rwp)
  197. {
  198. int res;
  199. #ifdef _WIN32
  200. if (have_srwlock)
  201. return srw_tryrdlock(rwp);
  202. #endif
  203. pthread_mutex_lock(&rwp->lock);
  204. if ((rwp->state < 0 ) || rwp->waiters)
  205. res= EBUSY; /* Can't get lock */
  206. else
  207. {
  208. res=0;
  209. rwp->state++;
  210. }
  211. pthread_mutex_unlock(&rwp->lock);
  212. return(res);
  213. }
  214. int my_rw_wrlock(my_rw_lock_t *rwp)
  215. {
  216. #ifdef _WIN32
  217. if (have_srwlock)
  218. return srw_wrlock(rwp);
  219. #endif
  220. pthread_mutex_lock(&rwp->lock);
  221. rwp->waiters++; /* another writer queued */
  222. my_rw_lock_assert_not_write_owner(rwp);
  223. while (rwp->state)
  224. pthread_cond_wait(&rwp->writers, &rwp->lock);
  225. rwp->state = -1;
  226. rwp->waiters--;
  227. #ifdef SAFE_MUTEX
  228. rwp->write_thread= pthread_self();
  229. #endif
  230. pthread_mutex_unlock(&rwp->lock);
  231. return(0);
  232. }
  233. int my_rw_trywrlock(my_rw_lock_t *rwp)
  234. {
  235. int res;
  236. #ifdef _WIN32
  237. if (have_srwlock)
  238. return srw_trywrlock(rwp);
  239. #endif
  240. pthread_mutex_lock(&rwp->lock);
  241. if (rwp->state)
  242. res= EBUSY; /* Can't get lock */
  243. else
  244. {
  245. res=0;
  246. rwp->state = -1;
  247. #ifdef SAFE_MUTEX
  248. rwp->write_thread= pthread_self();
  249. #endif
  250. }
  251. pthread_mutex_unlock(&rwp->lock);
  252. return(res);
  253. }
  254. int my_rw_unlock(my_rw_lock_t *rwp)
  255. {
  256. #ifdef _WIN32
  257. if (have_srwlock)
  258. return srw_unlock(rwp);
  259. #endif
  260. DBUG_PRINT("rw_unlock",
  261. ("state: %d waiters: %d", rwp->state, rwp->waiters));
  262. pthread_mutex_lock(&rwp->lock);
  263. DBUG_ASSERT(rwp->state != 0);
  264. if (rwp->state == -1) /* writer releasing */
  265. {
  266. my_rw_lock_assert_write_owner(rwp);
  267. rwp->state= 0; /* mark as available */
  268. #ifdef SAFE_MUTEX
  269. rwp->write_thread= 0;
  270. #endif
  271. if ( rwp->waiters ) /* writers queued */
  272. pthread_cond_signal( &rwp->writers );
  273. else
  274. pthread_cond_broadcast( &rwp->readers );
  275. }
  276. else
  277. {
  278. if ( --rwp->state == 0 && /* no more readers */
  279. rwp->waiters)
  280. pthread_cond_signal( &rwp->writers );
  281. }
  282. pthread_mutex_unlock( &rwp->lock );
  283. return(0);
  284. }
  285. #endif /* defined(NEED_MY_RW_LOCK) */
  286. int rw_pr_init(rw_pr_lock_t *rwlock)
  287. {
  288. pthread_mutex_init(&rwlock->lock, NULL);
  289. pthread_cond_init(&rwlock->no_active_readers, NULL);
  290. rwlock->active_readers= 0;
  291. rwlock->writers_waiting_readers= 0;
  292. rwlock->active_writer= FALSE;
  293. #ifdef SAFE_MUTEX
  294. rwlock->writer_thread= 0;
  295. #endif
  296. return 0;
  297. }
  298. int rw_pr_destroy(rw_pr_lock_t *rwlock)
  299. {
  300. pthread_cond_destroy(&rwlock->no_active_readers);
  301. pthread_mutex_destroy(&rwlock->lock);
  302. return 0;
  303. }
  304. int rw_pr_rdlock(rw_pr_lock_t *rwlock)
  305. {
  306. pthread_mutex_lock(&rwlock->lock);
  307. /*
  308. The fact that we were able to acquire 'lock' mutex means
  309. that there are no active writers and we can acquire rd-lock.
  310. Increment active readers counter to prevent requests for
  311. wr-lock from succeeding and unlock mutex.
  312. */
  313. rwlock->active_readers++;
  314. pthread_mutex_unlock(&rwlock->lock);
  315. return 0;
  316. }
  317. int rw_pr_wrlock(rw_pr_lock_t *rwlock)
  318. {
  319. pthread_mutex_lock(&rwlock->lock);
  320. if (rwlock->active_readers != 0)
  321. {
  322. /* There are active readers. We have to wait until they are gone. */
  323. rwlock->writers_waiting_readers++;
  324. while (rwlock->active_readers != 0)
  325. pthread_cond_wait(&rwlock->no_active_readers, &rwlock->lock);
  326. rwlock->writers_waiting_readers--;
  327. }
  328. /*
  329. We own 'lock' mutex so there is no active writers.
  330. Also there are no active readers.
  331. This means that we can grant wr-lock.
  332. Not releasing 'lock' mutex until unlock will block
  333. both requests for rd and wr-locks.
  334. Set 'active_writer' flag to simplify unlock.
  335. Thanks to the fact wr-lock/unlock in the absence of
  336. contention from readers is essentially mutex lock/unlock
  337. with a few simple checks make this rwlock implementation
  338. wr-lock optimized.
  339. */
  340. rwlock->active_writer= TRUE;
  341. #ifdef SAFE_MUTEX
  342. rwlock->writer_thread= pthread_self();
  343. #endif
  344. return 0;
  345. }
  346. int rw_pr_unlock(rw_pr_lock_t *rwlock)
  347. {
  348. if (rwlock->active_writer)
  349. {
  350. /* We are unlocking wr-lock. */
  351. #ifdef SAFE_MUTEX
  352. rwlock->writer_thread= 0;
  353. #endif
  354. rwlock->active_writer= FALSE;
  355. if (rwlock->writers_waiting_readers)
  356. {
  357. /*
  358. Avoid expensive cond signal in case when there is no contention
  359. or it is wr-only.
  360. Note that from view point of performance it would be better to
  361. signal on the condition variable after unlocking mutex (as it
  362. reduces number of contex switches).
  363. Unfortunately this would mean that such rwlock can't be safely
  364. used by MDL subsystem, which relies on the fact that it is OK
  365. to destroy rwlock once it is in unlocked state.
  366. */
  367. pthread_cond_signal(&rwlock->no_active_readers);
  368. }
  369. pthread_mutex_unlock(&rwlock->lock);
  370. }
  371. else
  372. {
  373. /* We are unlocking rd-lock. */
  374. pthread_mutex_lock(&rwlock->lock);
  375. rwlock->active_readers--;
  376. if (rwlock->active_readers == 0 &&
  377. rwlock->writers_waiting_readers)
  378. {
  379. /*
  380. If we are last reader and there are waiting
  381. writers wake them up.
  382. */
  383. pthread_cond_signal(&rwlock->no_active_readers);
  384. }
  385. pthread_mutex_unlock(&rwlock->lock);
  386. }
  387. return 0;
  388. }