dscr_default_test.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * POWER Data Stream Control Register (DSCR) default test
  4. *
  5. * This test modifies the system wide default DSCR through
  6. * it's sysfs interface and then verifies that all threads
  7. * see the correct changed DSCR value immediately.
  8. *
  9. * Copyright 2012, Anton Blanchard, IBM Corporation.
  10. * Copyright 2015, Anshuman Khandual, IBM Corporation.
  11. */
  12. #define _GNU_SOURCE
  13. #include "dscr.h"
  14. #include <pthread.h>
  15. #include <semaphore.h>
  16. #include <unistd.h>
  17. static void *dscr_default_lockstep_writer(void *arg)
  18. {
  19. sem_t *reader_sem = (sem_t *)arg;
  20. sem_t *writer_sem = (sem_t *)arg + 1;
  21. unsigned long expected_dscr = 0;
  22. for (int i = 0; i < COUNT; i++) {
  23. FAIL_IF_EXIT(sem_wait(writer_sem));
  24. set_default_dscr(expected_dscr);
  25. expected_dscr = (expected_dscr + 1) % DSCR_MAX;
  26. FAIL_IF_EXIT(sem_post(reader_sem));
  27. }
  28. return NULL;
  29. }
  30. int dscr_default_lockstep_test(void)
  31. {
  32. pthread_t writer;
  33. sem_t rw_semaphores[2];
  34. sem_t *reader_sem = &rw_semaphores[0];
  35. sem_t *writer_sem = &rw_semaphores[1];
  36. unsigned long expected_dscr = 0;
  37. SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
  38. FAIL_IF(sem_init(reader_sem, 0, 0));
  39. FAIL_IF(sem_init(writer_sem, 0, 1)); /* writer starts first */
  40. FAIL_IF(bind_to_cpu(BIND_CPU_ANY) < 0);
  41. FAIL_IF(pthread_create(&writer, NULL, dscr_default_lockstep_writer, (void *)rw_semaphores));
  42. for (int i = 0; i < COUNT ; i++) {
  43. FAIL_IF(sem_wait(reader_sem));
  44. FAIL_IF(get_dscr() != expected_dscr);
  45. FAIL_IF(get_dscr_usr() != expected_dscr);
  46. expected_dscr = (expected_dscr + 1) % DSCR_MAX;
  47. FAIL_IF(sem_post(writer_sem));
  48. }
  49. FAIL_IF(pthread_join(writer, NULL));
  50. FAIL_IF(sem_destroy(reader_sem));
  51. FAIL_IF(sem_destroy(writer_sem));
  52. return 0;
  53. }
  54. struct random_thread_args {
  55. pthread_t thread_id;
  56. unsigned long *expected_system_dscr;
  57. pthread_rwlock_t *rw_lock;
  58. pthread_barrier_t *barrier;
  59. };
  60. static void *dscr_default_random_thread(void *in)
  61. {
  62. struct random_thread_args *args = (struct random_thread_args *)in;
  63. unsigned long *expected_dscr_p = args->expected_system_dscr;
  64. pthread_rwlock_t *rw_lock = args->rw_lock;
  65. int err;
  66. srand(gettid());
  67. err = pthread_barrier_wait(args->barrier);
  68. FAIL_IF_EXIT(err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD);
  69. for (int i = 0; i < COUNT; i++) {
  70. unsigned long expected_dscr;
  71. unsigned long current_dscr;
  72. unsigned long current_dscr_usr;
  73. FAIL_IF_EXIT(pthread_rwlock_rdlock(rw_lock));
  74. expected_dscr = *expected_dscr_p;
  75. current_dscr = get_dscr();
  76. current_dscr_usr = get_dscr_usr();
  77. FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
  78. FAIL_IF_EXIT(current_dscr != expected_dscr);
  79. FAIL_IF_EXIT(current_dscr_usr != expected_dscr);
  80. if (rand() % 10 == 0) {
  81. unsigned long next_dscr;
  82. FAIL_IF_EXIT(pthread_rwlock_wrlock(rw_lock));
  83. next_dscr = (*expected_dscr_p + 1) % DSCR_MAX;
  84. set_default_dscr(next_dscr);
  85. *expected_dscr_p = next_dscr;
  86. FAIL_IF_EXIT(pthread_rwlock_unlock(rw_lock));
  87. }
  88. }
  89. pthread_exit((void *)0);
  90. }
  91. int dscr_default_random_test(void)
  92. {
  93. struct random_thread_args threads[THREADS];
  94. unsigned long expected_system_dscr = 0;
  95. pthread_rwlockattr_t rwlock_attr;
  96. pthread_rwlock_t rw_lock;
  97. pthread_barrier_t barrier;
  98. SKIP_IF(!have_hwcap2(PPC_FEATURE2_DSCR));
  99. FAIL_IF(pthread_rwlockattr_setkind_np(&rwlock_attr,
  100. PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP));
  101. FAIL_IF(pthread_rwlock_init(&rw_lock, &rwlock_attr));
  102. FAIL_IF(pthread_barrier_init(&barrier, NULL, THREADS));
  103. set_default_dscr(expected_system_dscr);
  104. for (int i = 0; i < THREADS; i++) {
  105. threads[i].expected_system_dscr = &expected_system_dscr;
  106. threads[i].rw_lock = &rw_lock;
  107. threads[i].barrier = &barrier;
  108. FAIL_IF(pthread_create(&threads[i].thread_id, NULL,
  109. dscr_default_random_thread, (void *)&threads[i]));
  110. }
  111. for (int i = 0; i < THREADS; i++)
  112. FAIL_IF(pthread_join(threads[i].thread_id, NULL));
  113. FAIL_IF(pthread_barrier_destroy(&barrier));
  114. FAIL_IF(pthread_rwlock_destroy(&rw_lock));
  115. return 0;
  116. }
  117. int main(int argc, char *argv[])
  118. {
  119. unsigned long orig_dscr_default = 0;
  120. int err = 0;
  121. if (have_hwcap2(PPC_FEATURE2_DSCR))
  122. orig_dscr_default = get_default_dscr();
  123. err |= test_harness(dscr_default_lockstep_test, "dscr_default_lockstep_test");
  124. err |= test_harness(dscr_default_random_test, "dscr_default_random_test");
  125. if (have_hwcap2(PPC_FEATURE2_DSCR))
  126. set_default_dscr(orig_dscr_default);
  127. return err;
  128. }