summaryrefslogtreecommitdiffstats
path: root/mysys/test_thr_mutex.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/test_thr_mutex.c')
-rw-r--r--mysys/test_thr_mutex.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/mysys/test_thr_mutex.c b/mysys/test_thr_mutex.c
new file mode 100644
index 00000000..00b1f5f4
--- /dev/null
+++ b/mysys/test_thr_mutex.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2008 Sun Microsystems, Inc
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
+
+/* Testing of deadlock detector */
+
+#include <my_global.h>
+#include <mysys_priv.h>
+
+
+int main(int argc __attribute__((unused)), char** argv)
+{
+ pthread_mutex_t LOCK_A, LOCK_B, LOCK_C, LOCK_D, LOCK_E, LOCK_F, LOCK_G;
+ pthread_mutex_t LOCK_H, LOCK_I;
+ MY_INIT(argv[0]);
+ DBUG_ENTER("main");
+
+ DBUG_PUSH("d:t:O,/tmp/trace");
+ printf("This program is testing the mutex deadlock detection.\n"
+ "It should print out different failures of wrong mutex usage"
+ "on stderr\n\n");
+
+ safe_mutex_deadlock_detector= 1;
+ pthread_mutex_init(&LOCK_A, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_B, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_C, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_D, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_E, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_F, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_G, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_H, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_I, MY_MUTEX_INIT_FAST);
+
+ printf("Testing A->B and B->A\n");
+ fflush(stdout);
+ pthread_mutex_lock(&LOCK_A);
+ pthread_mutex_lock(&LOCK_B);
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_B);
+
+ /* Test different (wrong) lock order */
+ pthread_mutex_lock(&LOCK_B);
+ pthread_mutex_lock(&LOCK_A); /* Should give warning */
+
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_B);
+
+ /* Check that we don't get another warning for same lock */
+ printf("Testing A->B and B->A again (should not give a warning)\n");
+ pthread_mutex_lock(&LOCK_B);
+ pthread_mutex_lock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_B);
+
+ /*
+ Test of ring with many mutex
+ We also unlock mutex in different orders to get the unlock code properly
+ tested.
+ */
+ printf("Testing A->C and C->D and D->A\n");
+ pthread_mutex_lock(&LOCK_A);
+ pthread_mutex_lock(&LOCK_C);
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_C);
+ pthread_mutex_lock(&LOCK_C);
+ pthread_mutex_lock(&LOCK_D);
+ pthread_mutex_unlock(&LOCK_D);
+ pthread_mutex_unlock(&LOCK_C);
+
+ pthread_mutex_lock(&LOCK_D);
+ pthread_mutex_lock(&LOCK_A); /* Should give warning */
+
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_D);
+
+ printf("Testing E -> F ; H -> I ; F -> H ; H -> I -> E\n");
+ fflush(stdout);
+
+ pthread_mutex_lock(&LOCK_E);
+ pthread_mutex_lock(&LOCK_F);
+ pthread_mutex_unlock(&LOCK_E);
+ pthread_mutex_unlock(&LOCK_F);
+ pthread_mutex_lock(&LOCK_H);
+ pthread_mutex_lock(&LOCK_I);
+ pthread_mutex_unlock(&LOCK_I);
+ pthread_mutex_unlock(&LOCK_H);
+ pthread_mutex_lock(&LOCK_F);
+ pthread_mutex_lock(&LOCK_H);
+ pthread_mutex_unlock(&LOCK_H);
+ pthread_mutex_unlock(&LOCK_F);
+
+ pthread_mutex_lock(&LOCK_H);
+ pthread_mutex_lock(&LOCK_I);
+ pthread_mutex_lock(&LOCK_E); /* Should give warning */
+
+ pthread_mutex_unlock(&LOCK_E);
+ pthread_mutex_unlock(&LOCK_I);
+ pthread_mutex_unlock(&LOCK_H);
+
+ printf("\nFollowing shouldn't give any warnings\n");
+ printf("Testing A->B and B->A without deadlock detection\n");
+ fflush(stdout);
+
+ /* Reinitialize mutex to get rid of old wrong usage markers */
+ pthread_mutex_destroy(&LOCK_A);
+ pthread_mutex_destroy(&LOCK_B);
+ pthread_mutex_init(&LOCK_A, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&LOCK_B, MY_MUTEX_INIT_FAST);
+
+ /* Start testing */
+ my_pthread_mutex_lock(&LOCK_A, MYF(MYF_NO_DEADLOCK_DETECTION));
+ pthread_mutex_lock(&LOCK_B);
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_B);
+
+ pthread_mutex_lock(&LOCK_A);
+ my_pthread_mutex_lock(&LOCK_B, MYF(MYF_NO_DEADLOCK_DETECTION));
+ pthread_mutex_unlock(&LOCK_A);
+ pthread_mutex_unlock(&LOCK_B);
+
+ printf("Testing A -> C ; B -> C ; A->B\n");
+ fflush(stdout);
+ pthread_mutex_lock(&LOCK_A);
+ pthread_mutex_lock(&LOCK_C);
+ pthread_mutex_unlock(&LOCK_C);
+ pthread_mutex_unlock(&LOCK_A);
+
+ pthread_mutex_lock(&LOCK_B);
+ pthread_mutex_lock(&LOCK_C);
+ pthread_mutex_unlock(&LOCK_C);
+ pthread_mutex_unlock(&LOCK_B);
+
+ pthread_mutex_lock(&LOCK_A);
+ pthread_mutex_lock(&LOCK_B);
+ pthread_mutex_unlock(&LOCK_B);
+ pthread_mutex_unlock(&LOCK_A);
+
+ /* Cleanup */
+ pthread_mutex_destroy(&LOCK_A);
+ pthread_mutex_destroy(&LOCK_B);
+ pthread_mutex_destroy(&LOCK_C);
+ pthread_mutex_destroy(&LOCK_D);
+ pthread_mutex_destroy(&LOCK_E);
+ pthread_mutex_destroy(&LOCK_F);
+ pthread_mutex_destroy(&LOCK_G);
+ pthread_mutex_destroy(&LOCK_H);
+ pthread_mutex_destroy(&LOCK_I);
+
+ my_end(MY_DONT_FREE_DBUG);
+ exit(0);
+}