futex_requeue.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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 <limits.h>
  9. #include "futextest.h"
  10. #include "kselftest_harness.h"
  11. #define timeout_ns 30000000
  12. #define WAKE_WAIT_US 10000
  13. volatile futex_t *f1;
  14. void *waiterfn(void *arg)
  15. {
  16. struct timespec to;
  17. to.tv_sec = 0;
  18. to.tv_nsec = timeout_ns;
  19. if (futex_wait(f1, *f1, &to, 0))
  20. printf("waiter failed errno %d\n", errno);
  21. return NULL;
  22. }
  23. TEST(requeue_single)
  24. {
  25. volatile futex_t _f1 = 0;
  26. volatile futex_t f2 = 0;
  27. pthread_t waiter[10];
  28. int res;
  29. f1 = &_f1;
  30. /*
  31. * Requeue a waiter from f1 to f2, and wake f2.
  32. */
  33. if (pthread_create(&waiter[0], NULL, waiterfn, NULL))
  34. ksft_exit_fail_msg("pthread_create failed\n");
  35. usleep(WAKE_WAIT_US);
  36. ksft_print_dbg_msg("Requeuing 1 futex from f1 to f2\n");
  37. res = futex_cmp_requeue(f1, 0, &f2, 0, 1, 0);
  38. if (res != 1)
  39. ksft_test_result_fail("futex_requeue simple returned: %d %s\n",
  40. res ? errno : res,
  41. res ? strerror(errno) : "");
  42. ksft_print_dbg_msg("Waking 1 futex at f2\n");
  43. res = futex_wake(&f2, 1, 0);
  44. if (res != 1) {
  45. ksft_test_result_fail("futex_requeue simple returned: %d %s\n",
  46. res ? errno : res,
  47. res ? strerror(errno) : "");
  48. } else {
  49. ksft_test_result_pass("futex_requeue simple succeeds\n");
  50. }
  51. }
  52. TEST(requeue_multiple)
  53. {
  54. volatile futex_t _f1 = 0;
  55. volatile futex_t f2 = 0;
  56. pthread_t waiter[10];
  57. int res, i;
  58. f1 = &_f1;
  59. /*
  60. * Create 10 waiters at f1. At futex_requeue, wake 3 and requeue 7.
  61. * At futex_wake, wake INT_MAX (should be exactly 7).
  62. */
  63. for (i = 0; i < 10; i++) {
  64. if (pthread_create(&waiter[i], NULL, waiterfn, NULL))
  65. ksft_exit_fail_msg("pthread_create failed\n");
  66. }
  67. usleep(WAKE_WAIT_US);
  68. ksft_print_dbg_msg("Waking 3 futexes at f1 and requeuing 7 futexes from f1 to f2\n");
  69. res = futex_cmp_requeue(f1, 0, &f2, 3, 7, 0);
  70. if (res != 10) {
  71. ksft_test_result_fail("futex_requeue many returned: %d %s\n",
  72. res ? errno : res,
  73. res ? strerror(errno) : "");
  74. }
  75. ksft_print_dbg_msg("Waking INT_MAX futexes at f2\n");
  76. res = futex_wake(&f2, INT_MAX, 0);
  77. if (res != 7) {
  78. ksft_test_result_fail("futex_requeue many returned: %d %s\n",
  79. res ? errno : res,
  80. res ? strerror(errno) : "");
  81. } else {
  82. ksft_test_result_pass("futex_requeue many succeeds\n");
  83. }
  84. }
  85. TEST_HARNESS_MAIN