test_sref_dirty_zeroes.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2014 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/macros.h>
  35. #include <kern/mutex.h>
  36. #include <kern/panic.h>
  37. #include <kern/sref.h>
  38. #include <kern/syscnt.h>
  39. #include <kern/thread.h>
  40. #include <test/test.h>
  41. #include <vm/vm_kmem.h>
  42. static struct condition test_condition;
  43. static struct mutex test_lock;
  44. static struct sref_counter test_counter;
  45. static unsigned long test_transient_ref;
  46. static void
  47. test_inc(void *arg)
  48. {
  49. volatile unsigned long i;
  50. (void)arg;
  51. for (;;) {
  52. for (i = 0; i < 1000000; i++) {
  53. sref_counter_inc(&test_counter);
  54. mutex_lock(&test_lock);
  55. test_transient_ref++;
  56. condition_signal(&test_condition);
  57. while (test_transient_ref != 0) {
  58. condition_wait(&test_condition, &test_lock);
  59. }
  60. mutex_unlock(&test_lock);
  61. }
  62. printf("counter global value: %lu\n", test_counter.value);
  63. syscnt_info("sref_epoch");
  64. syscnt_info("sref_dirty_zero");
  65. syscnt_info("sref_true_zero");
  66. }
  67. }
  68. static void
  69. test_dec(void *arg)
  70. {
  71. (void)arg;
  72. for (;;) {
  73. mutex_lock(&test_lock);
  74. while (test_transient_ref == 0) {
  75. condition_wait(&test_condition, &test_lock);
  76. }
  77. test_transient_ref--;
  78. condition_signal(&test_condition);
  79. mutex_unlock(&test_lock);
  80. sref_counter_dec(&test_counter);
  81. }
  82. }
  83. static void
  84. test_noref(struct sref_counter *counter)
  85. {
  86. (void)counter;
  87. panic("0 references, page released\n");
  88. }
  89. void __init
  90. test_setup(void)
  91. {
  92. struct thread_attr attr;
  93. struct thread *thread;
  94. int error;
  95. condition_init(&test_condition);
  96. mutex_init(&test_lock);
  97. sref_counter_init(&test_counter, 1, NULL, test_noref);
  98. test_transient_ref = 0;
  99. thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_inc");
  100. thread_attr_set_detached(&attr);
  101. error = thread_create(&thread, &attr, test_inc, NULL);
  102. error_check(error, "thread_create");
  103. thread_attr_init(&attr, THREAD_KERNEL_PREFIX "test_dec");
  104. thread_attr_set_detached(&attr);
  105. error = thread_create(&thread, &attr, test_dec, NULL);
  106. error_check(error, "thread_create");
  107. }