eventfd-disable.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: test disable/enable notifications through eventfd
  5. *
  6. */
  7. #include <errno.h>
  8. #include <stdio.h>
  9. #include <unistd.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <fcntl.h>
  13. #include <poll.h>
  14. #include <sys/eventfd.h>
  15. #include "liburing.h"
  16. #include "helpers.h"
  17. static int test(bool defer)
  18. {
  19. struct io_uring_params p = {};
  20. struct io_uring_sqe *sqe;
  21. struct io_uring_cqe *cqe;
  22. struct io_uring ring;
  23. uint64_t ptr;
  24. struct iovec vec = {
  25. .iov_base = &ptr,
  26. .iov_len = sizeof(ptr)
  27. };
  28. int ret, evfd, i;
  29. if (defer)
  30. p.flags |= IORING_SETUP_SINGLE_ISSUER |
  31. IORING_SETUP_DEFER_TASKRUN;
  32. ret = io_uring_queue_init_params(64, &ring, &p);
  33. if (ret) {
  34. fprintf(stderr, "ring setup failed: %d\n", ret);
  35. return T_EXIT_FAIL;
  36. }
  37. evfd = eventfd(0, EFD_CLOEXEC);
  38. if (evfd < 0) {
  39. perror("eventfd");
  40. return T_EXIT_FAIL;
  41. }
  42. ret = io_uring_register_eventfd(&ring, evfd);
  43. if (ret) {
  44. fprintf(stderr, "failed to register evfd: %d\n", ret);
  45. return T_EXIT_FAIL;
  46. }
  47. if (!io_uring_cq_eventfd_enabled(&ring)) {
  48. fprintf(stderr, "eventfd disabled\n");
  49. return T_EXIT_FAIL;
  50. }
  51. ret = io_uring_cq_eventfd_toggle(&ring, false);
  52. if (ret) {
  53. fprintf(stdout, "Skipping, CQ flags not available!\n");
  54. return T_EXIT_SKIP;
  55. }
  56. sqe = io_uring_get_sqe(&ring);
  57. io_uring_prep_readv(sqe, evfd, &vec, 1, 0);
  58. sqe->user_data = 1;
  59. ret = io_uring_submit(&ring);
  60. if (ret != 1) {
  61. fprintf(stderr, "submit: %d\n", ret);
  62. return T_EXIT_FAIL;
  63. }
  64. for (i = 0; i < 63; i++) {
  65. sqe = io_uring_get_sqe(&ring);
  66. io_uring_prep_nop(sqe);
  67. sqe->user_data = 2;
  68. }
  69. ret = io_uring_submit(&ring);
  70. if (ret != 63) {
  71. fprintf(stderr, "submit: %d\n", ret);
  72. return T_EXIT_FAIL;
  73. }
  74. for (i = 0; i < 63; i++) {
  75. ret = io_uring_wait_cqe(&ring, &cqe);
  76. if (ret) {
  77. fprintf(stderr, "wait: %d\n", ret);
  78. return T_EXIT_FAIL;
  79. }
  80. switch (cqe->user_data) {
  81. case 1: /* eventfd */
  82. fprintf(stderr, "eventfd unexpected: %d\n", (int)ptr);
  83. return T_EXIT_FAIL;
  84. case 2:
  85. if (cqe->res) {
  86. fprintf(stderr, "nop: %d\n", cqe->res);
  87. return T_EXIT_FAIL;
  88. }
  89. break;
  90. }
  91. io_uring_cqe_seen(&ring, cqe);
  92. }
  93. ret = io_uring_cq_eventfd_toggle(&ring, true);
  94. if (ret) {
  95. fprintf(stderr, "io_uring_cq_eventfd_toggle: %d\n", ret);
  96. return T_EXIT_FAIL;
  97. }
  98. sqe = io_uring_get_sqe(&ring);
  99. io_uring_prep_nop(sqe);
  100. sqe->user_data = 2;
  101. ret = io_uring_submit(&ring);
  102. if (ret != 1) {
  103. fprintf(stderr, "submit: %d\n", ret);
  104. return T_EXIT_FAIL;
  105. }
  106. for (i = 0; i < 2; i++) {
  107. ret = io_uring_wait_cqe(&ring, &cqe);
  108. if (ret) {
  109. fprintf(stderr, "wait: %d\n", ret);
  110. return T_EXIT_FAIL;
  111. }
  112. switch (cqe->user_data) {
  113. case 1: /* eventfd */
  114. if (cqe->res != sizeof(ptr)) {
  115. fprintf(stderr, "read res: %d\n", cqe->res);
  116. return T_EXIT_FAIL;
  117. }
  118. if (ptr != 1) {
  119. fprintf(stderr, "eventfd: %d\n", (int)ptr);
  120. return T_EXIT_FAIL;
  121. }
  122. break;
  123. case 2:
  124. if (cqe->res) {
  125. fprintf(stderr, "nop: %d\n", cqe->res);
  126. return T_EXIT_FAIL;
  127. }
  128. break;
  129. }
  130. io_uring_cqe_seen(&ring, cqe);
  131. }
  132. io_uring_queue_exit(&ring);
  133. close(evfd);
  134. return T_EXIT_PASS;
  135. }
  136. int main(int argc, char *argv[])
  137. {
  138. int ret;
  139. if (argc > 1)
  140. return T_EXIT_SKIP;
  141. ret = test(false);
  142. if (ret != T_EXIT_PASS) {
  143. fprintf(stderr, "%s: test(false) failed\n", argv[0]);
  144. return ret;
  145. }
  146. if (t_probe_defer_taskrun()) {
  147. ret = test(true);
  148. if (ret != T_EXIT_PASS) {
  149. fprintf(stderr, "%s: test(true) failed\n", argv[0]);
  150. return ret;
  151. }
  152. }
  153. return ret;
  154. }