futex_wait.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright Collabora Ltd., 2021
  4. *
  5. * futex cmp requeue test by André Almeida <andrealmeid@collabora.com>
  6. */
  7. #include <pthread.h>
  8. #include <sys/shm.h>
  9. #include <sys/mman.h>
  10. #include <fcntl.h>
  11. #include "logging.h"
  12. #include "futextest.h"
  13. #define TEST_NAME "futex-wait"
  14. #define timeout_ns 30000000
  15. #define WAKE_WAIT_US 10000
  16. #define SHM_PATH "futex_shm_file"
  17. void *futex;
  18. void usage(char *prog)
  19. {
  20. printf("Usage: %s\n", prog);
  21. printf(" -c Use color\n");
  22. printf(" -h Display this help message\n");
  23. printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n",
  24. VQUIET, VCRITICAL, VINFO);
  25. }
  26. static void *waiterfn(void *arg)
  27. {
  28. struct timespec to;
  29. unsigned int flags = 0;
  30. if (arg)
  31. flags = *((unsigned int *) arg);
  32. to.tv_sec = 0;
  33. to.tv_nsec = timeout_ns;
  34. if (futex_wait(futex, 0, &to, flags))
  35. printf("waiter failed errno %d\n", errno);
  36. return NULL;
  37. }
  38. int main(int argc, char *argv[])
  39. {
  40. int res, ret = RET_PASS, fd, c, shm_id;
  41. u_int32_t f_private = 0, *shared_data;
  42. unsigned int flags = FUTEX_PRIVATE_FLAG;
  43. pthread_t waiter;
  44. void *shm;
  45. futex = &f_private;
  46. while ((c = getopt(argc, argv, "cht:v:")) != -1) {
  47. switch (c) {
  48. case 'c':
  49. log_color(1);
  50. break;
  51. case 'h':
  52. usage(basename(argv[0]));
  53. exit(0);
  54. case 'v':
  55. log_verbosity(atoi(optarg));
  56. break;
  57. default:
  58. usage(basename(argv[0]));
  59. exit(1);
  60. }
  61. }
  62. ksft_print_header();
  63. ksft_set_plan(3);
  64. ksft_print_msg("%s: Test futex_wait\n", basename(argv[0]));
  65. /* Testing a private futex */
  66. info("Calling private futex_wait on futex: %p\n", futex);
  67. if (pthread_create(&waiter, NULL, waiterfn, (void *) &flags))
  68. error("pthread_create failed\n", errno);
  69. usleep(WAKE_WAIT_US);
  70. info("Calling private futex_wake on futex: %p\n", futex);
  71. res = futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
  72. if (res != 1) {
  73. ksft_test_result_fail("futex_wake private returned: %d %s\n",
  74. errno, strerror(errno));
  75. ret = RET_FAIL;
  76. } else {
  77. ksft_test_result_pass("futex_wake private succeeds\n");
  78. }
  79. /* Testing an anon page shared memory */
  80. shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
  81. if (shm_id < 0) {
  82. perror("shmget");
  83. exit(1);
  84. }
  85. shared_data = shmat(shm_id, NULL, 0);
  86. *shared_data = 0;
  87. futex = shared_data;
  88. info("Calling shared (page anon) futex_wait on futex: %p\n", futex);
  89. if (pthread_create(&waiter, NULL, waiterfn, NULL))
  90. error("pthread_create failed\n", errno);
  91. usleep(WAKE_WAIT_US);
  92. info("Calling shared (page anon) futex_wake on futex: %p\n", futex);
  93. res = futex_wake(futex, 1, 0);
  94. if (res != 1) {
  95. ksft_test_result_fail("futex_wake shared (page anon) returned: %d %s\n",
  96. errno, strerror(errno));
  97. ret = RET_FAIL;
  98. } else {
  99. ksft_test_result_pass("futex_wake shared (page anon) succeeds\n");
  100. }
  101. /* Testing a file backed shared memory */
  102. fd = open(SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  103. if (fd < 0) {
  104. perror("open");
  105. exit(1);
  106. }
  107. if (ftruncate(fd, sizeof(f_private))) {
  108. perror("ftruncate");
  109. exit(1);
  110. }
  111. shm = mmap(NULL, sizeof(f_private), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  112. if (shm == MAP_FAILED) {
  113. perror("mmap");
  114. exit(1);
  115. }
  116. memcpy(shm, &f_private, sizeof(f_private));
  117. futex = shm;
  118. info("Calling shared (file backed) futex_wait on futex: %p\n", futex);
  119. if (pthread_create(&waiter, NULL, waiterfn, NULL))
  120. error("pthread_create failed\n", errno);
  121. usleep(WAKE_WAIT_US);
  122. info("Calling shared (file backed) futex_wake on futex: %p\n", futex);
  123. res = futex_wake(shm, 1, 0);
  124. if (res != 1) {
  125. ksft_test_result_fail("futex_wake shared (file backed) returned: %d %s\n",
  126. errno, strerror(errno));
  127. ret = RET_FAIL;
  128. } else {
  129. ksft_test_result_pass("futex_wake shared (file backed) succeeds\n");
  130. }
  131. /* Freeing resources */
  132. shmdt(shared_data);
  133. munmap(shm, sizeof(f_private));
  134. remove(SHM_PATH);
  135. close(fd);
  136. ksft_print_cnts();
  137. return ret;
  138. }