test-ww_mutex.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Module-based API test facility for ww_mutexes
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, you can access it online at
  16. * http://www.gnu.org/licenses/gpl-2.0.html.
  17. */
  18. #include <linux/kernel.h>
  19. #include <linux/completion.h>
  20. #include <linux/kthread.h>
  21. #include <linux/module.h>
  22. #include <linux/ww_mutex.h>
  23. static DEFINE_WW_CLASS(ww_class);
  24. struct test_mutex {
  25. struct work_struct work;
  26. struct ww_mutex mutex;
  27. struct completion ready, go, done;
  28. unsigned int flags;
  29. };
  30. #define TEST_MTX_SPIN BIT(0)
  31. #define TEST_MTX_TRY BIT(1)
  32. #define TEST_MTX_CTX BIT(2)
  33. #define __TEST_MTX_LAST BIT(3)
  34. static void test_mutex_work(struct work_struct *work)
  35. {
  36. struct test_mutex *mtx = container_of(work, typeof(*mtx), work);
  37. complete(&mtx->ready);
  38. wait_for_completion(&mtx->go);
  39. if (mtx->flags & TEST_MTX_TRY) {
  40. while (!ww_mutex_trylock(&mtx->mutex))
  41. cpu_relax();
  42. } else {
  43. ww_mutex_lock(&mtx->mutex, NULL);
  44. }
  45. complete(&mtx->done);
  46. ww_mutex_unlock(&mtx->mutex);
  47. }
  48. static int __test_mutex(unsigned int flags)
  49. {
  50. #define TIMEOUT (HZ / 16)
  51. struct test_mutex mtx;
  52. struct ww_acquire_ctx ctx;
  53. int ret;
  54. ww_mutex_init(&mtx.mutex, &ww_class);
  55. ww_acquire_init(&ctx, &ww_class);
  56. INIT_WORK_ONSTACK(&mtx.work, test_mutex_work);
  57. init_completion(&mtx.ready);
  58. init_completion(&mtx.go);
  59. init_completion(&mtx.done);
  60. mtx.flags = flags;
  61. schedule_work(&mtx.work);
  62. wait_for_completion(&mtx.ready);
  63. ww_mutex_lock(&mtx.mutex, (flags & TEST_MTX_CTX) ? &ctx : NULL);
  64. complete(&mtx.go);
  65. if (flags & TEST_MTX_SPIN) {
  66. unsigned long timeout = jiffies + TIMEOUT;
  67. ret = 0;
  68. do {
  69. if (completion_done(&mtx.done)) {
  70. ret = -EINVAL;
  71. break;
  72. }
  73. cpu_relax();
  74. } while (time_before(jiffies, timeout));
  75. } else {
  76. ret = wait_for_completion_timeout(&mtx.done, TIMEOUT);
  77. }
  78. ww_mutex_unlock(&mtx.mutex);
  79. ww_acquire_fini(&ctx);
  80. if (ret) {
  81. pr_err("%s(flags=%x): mutual exclusion failure\n",
  82. __func__, flags);
  83. ret = -EINVAL;
  84. }
  85. flush_work(&mtx.work);
  86. destroy_work_on_stack(&mtx.work);
  87. return ret;
  88. #undef TIMEOUT
  89. }
  90. static int test_mutex(void)
  91. {
  92. int ret;
  93. int i;
  94. for (i = 0; i < __TEST_MTX_LAST; i++) {
  95. ret = __test_mutex(i);
  96. if (ret)
  97. return ret;
  98. }
  99. return 0;
  100. }
  101. static int __init test_ww_mutex_init(void)
  102. {
  103. int ret;
  104. ret = test_mutex();
  105. if (ret)
  106. return ret;
  107. return 0;
  108. }
  109. static void __exit test_ww_mutex_exit(void)
  110. {
  111. }
  112. module_init(test_ww_mutex_init);
  113. module_exit(test_ww_mutex_exit);
  114. MODULE_LICENSE("GPL");
  115. MODULE_AUTHOR("Intel Corporation");