pollfree.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: test pollfree wakeups
  5. */
  6. #include <fcntl.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include <sys/signalfd.h>
  12. #include <unistd.h>
  13. #include <stdlib.h>
  14. #include "liburing.h"
  15. #include "helpers.h"
  16. static int no_signalfd;
  17. static int child(int flags)
  18. {
  19. struct io_uring_sqe *sqe;
  20. struct io_uring ring;
  21. struct signalfd_siginfo si;
  22. static unsigned long index;
  23. sigset_t mask;
  24. int ret, fd;
  25. ret = io_uring_queue_init(4, &ring, flags);
  26. if (ret) {
  27. if (ret == -EINVAL)
  28. return 0;
  29. fprintf(stderr, "queue init failed %d\n", ret);
  30. return ret;
  31. }
  32. sigemptyset(&mask);
  33. sigaddset(&mask, SIGINT);
  34. fd = signalfd(-1, &mask, SFD_NONBLOCK);
  35. if (fd < 0) {
  36. no_signalfd = 1;
  37. perror("signalfd");
  38. return 1;
  39. }
  40. sqe = io_uring_get_sqe(&ring);
  41. io_uring_prep_read(sqe, fd, &si, sizeof(si), 0);
  42. sqe->user_data = 1;
  43. io_uring_submit(&ring);
  44. sqe = io_uring_get_sqe(&ring);
  45. io_uring_prep_read(sqe, fd, &si, sizeof(si), 0);
  46. sqe->user_data = 2;
  47. sqe->flags |= IOSQE_ASYNC;
  48. io_uring_submit(&ring);
  49. sqe = io_uring_get_sqe(&ring);
  50. io_uring_prep_read(sqe, fd, &si, sizeof(si), 0);
  51. sqe->user_data = 3;
  52. io_uring_submit(&ring);
  53. if (!(++index & 7))
  54. usleep(100);
  55. return 0;
  56. }
  57. static int run_test(int flags)
  58. {
  59. pid_t pid;
  60. int ret;
  61. pid = fork();
  62. if (pid < 0) {
  63. perror("fork");
  64. return 1;
  65. } else if (!pid) {
  66. ret = child(flags);
  67. _exit(ret);
  68. } else {
  69. int wstatus;
  70. pid_t childpid;
  71. do {
  72. childpid = waitpid(pid, &wstatus, 0);
  73. } while (childpid == (pid_t) -1 && (errno == EINTR));
  74. if (errno == ECHILD)
  75. wstatus = 0;
  76. return wstatus;
  77. }
  78. }
  79. static int test(int flags)
  80. {
  81. struct timeval start;
  82. int ret;
  83. gettimeofday(&start, NULL);
  84. do {
  85. ret = run_test(flags);
  86. if (ret) {
  87. fprintf(stderr, "test failed with flags %x\n", flags);
  88. return 1;
  89. }
  90. if (no_signalfd)
  91. break;
  92. } while (mtime_since_now(&start) < 2500);
  93. return 0;
  94. }
  95. int main(int argc, char *argv[])
  96. {
  97. int ret;
  98. if (argc > 1)
  99. return T_EXIT_SKIP;
  100. ret = test(0);
  101. if (ret) {
  102. fprintf(stderr, "test 0 failed: %d\n", ret);
  103. return ret;
  104. }
  105. if (no_signalfd)
  106. return T_EXIT_SKIP;
  107. ret = test(IORING_SETUP_SQPOLL);
  108. if (ret) {
  109. fprintf(stderr, "test SQPOLL failed: %d\n", ret);
  110. return ret;
  111. }
  112. ret = test(IORING_SETUP_COOP_TASKRUN);
  113. if (ret) {
  114. fprintf(stderr, "test COOP failed: %d\n", ret);
  115. return ret;
  116. }
  117. ret = test(IORING_SETUP_DEFER_TASKRUN|IORING_SETUP_SINGLE_ISSUER);
  118. if (ret) {
  119. fprintf(stderr, "test DEFER failed: %d\n", ret);
  120. return ret;
  121. }
  122. return T_EXIT_PASS;
  123. }