test_sref_dirty_zeroes.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2014-2019 Richard Braun.
  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 3 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, see <http://www.gnu.org/licenses/>.
  16. *
  17. *
  18. * The purpose of this test module is to produce dirty zeroes and make
  19. * sure they're correctly processed. It is a stress test that never ends,
  20. * except on failure. Two threads are created. The first increments a
  21. * scalable reference counter, then signals the second that it can decrement
  22. * it. Since these threads are likely to run on different processors, a
  23. * good amount of dirty zeroes should be produced, as reported by regularly
  24. * printing the relevant event counters. Since the true number of references
  25. * can never drop to 0, the no-reference function should never be called,
  26. * and panics if it is.
  27. */
  28. #include <stddef.h>
  29. #include <stdio.h>
  30. #include <kern/condition.h>
  31. #include <kern/error.h>
  32. #include <kern/init.h>
  33. #include <kern/kmem.h>
  34. #include <kern/log.h>
  35. #include <kern/macros.h>
  36. #include <kern/mutex.h>
  37. #include <kern/panic.h>
  38. #include <kern/sref.h>
  39. #include <kern/syscnt.h>
  40. #include <kern/thread.h>
  41. #include <test/test.h>
  42. #include <vm/vm_kmem.h>
  43. static struct condition test_condition;
  44. static struct mutex test_lock;
  45. static struct sref_counter test_counter;
  46. static unsigned long test_transient_ref;
  47. static void
  48. test_inc(void *arg)
  49. {
  50. volatile unsigned long i;
  51. (void)arg;
  52. for (;;) {
  53. for (i = 0; i < 1000000; i++) {
  54. sref_counter_inc(&test_counter);
  55. mutex_lock(&test_lock);
  56. test_transient_ref++;
  57. condition_signal(&test_condition);
  58. while (test_transient_ref != 0) {
  59. condition_wait(&test_condition, &test_lock);
  60. }
  61. mutex_unlock(&test_lock);
  62. }
  63. printf("counter global value: %lu\n", test_counter.value);
  64. syscnt_info("sref_epoch", log_info);
  65. syscnt_info("sref_dirty_zero", log_info);
  66. syscnt_info("sref_true_zero", log_info);
  67. }
  68. }
  69. static void
  70. test_dec(void *arg)
  71. {
  72. (void)arg;
  73. for (;;) {
  74. mutex_lock(&test_lock);
  75. while (test_transient_ref == 0) {
  76. condition_wait(&test_condition, &test_lock);
  77. }
  78. test_transient_ref--;
  79. condition_signal(&test_condition);
  80. mutex_unlock(&test_lock);
  81. sref_counter_dec(&test_counter);
  82. }
  83. }
  84. static void
  85. test_noref(struct sref_counter *counter)
  86. {
  87. (void)counter;
  88. panic("0 references, page released\n");
  89. }
  90. void __init
  91. test_setup(void)
  92. {
  93. struct thread_attr attr;
  94. struct thread *thread;
  95. int error;
  96. condition_init(&test_condition);
  97. mutex_init(&test_lock);
  98. sref_counter_init(&test_counter, 1, NULL, test_noref);
  99. test_transient_ref = 0;
  100. thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_inc");
  101. thread_attr_set_detached(&attr);
  102. error = thread_create(&thread, &attr, test_inc, NULL);
  103. error_check(error, "thread_create");
  104. thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_dec");
  105. thread_attr_set_detached(&attr);
  106. error = thread_create(&thread, &attr, test_dec, NULL);
  107. error_check(error, "thread_create");
  108. }