poll-race.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include "../config-host.h"
  2. /* SPDX-License-Identifier: MIT */
  3. /*
  4. * Description: check that multiple receives on the same socket don't get
  5. * stalled if multiple wakers race with the socket readiness.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <pthread.h>
  11. #include <sys/socket.h>
  12. #include "liburing.h"
  13. #include "helpers.h"
  14. #define NREQS 64
  15. struct data {
  16. pthread_barrier_t barrier;
  17. int fd;
  18. };
  19. static void *thread(void *data)
  20. {
  21. struct data *d = data;
  22. char buf[64];
  23. int ret, i;
  24. pthread_barrier_wait(&d->barrier);
  25. for (i = 0; i < NREQS; i++) {
  26. ret = write(d->fd, buf, sizeof(buf));
  27. if (ret != 64)
  28. fprintf(stderr, "wrote short %d\n", ret);
  29. }
  30. return NULL;
  31. }
  32. static int test(struct io_uring *ring, struct data *d)
  33. {
  34. struct io_uring_sqe *sqe;
  35. struct io_uring_cqe *cqe;
  36. int fd[2], ret, i;
  37. char buf[64];
  38. pthread_t t;
  39. void *ret2;
  40. if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fd) < 0) {
  41. perror("socketpair");
  42. return T_EXIT_FAIL;
  43. }
  44. d->fd = fd[1];
  45. pthread_create(&t, NULL, thread, d);
  46. for (i = 0; i < NREQS; i++) {
  47. sqe = io_uring_get_sqe(ring);
  48. io_uring_prep_recv(sqe, fd[0], buf, sizeof(buf), 0);
  49. }
  50. pthread_barrier_wait(&d->barrier);
  51. ret = io_uring_submit(ring);
  52. if (ret != NREQS) {
  53. fprintf(stderr, "submit %d\n", ret);
  54. return T_EXIT_FAIL;
  55. }
  56. for (i = 0; i < NREQS; i++) {
  57. ret = io_uring_wait_cqe(ring, &cqe);
  58. if (ret) {
  59. fprintf(stderr, "cqe wait %d\n", ret);
  60. return T_EXIT_FAIL;
  61. }
  62. io_uring_cqe_seen(ring, cqe);
  63. }
  64. close(fd[0]);
  65. close(fd[1]);
  66. pthread_join(t, &ret2);
  67. return T_EXIT_PASS;
  68. }
  69. int main(int argc, char *argv[])
  70. {
  71. struct io_uring ring;
  72. struct data d;
  73. int i, ret;
  74. if (argc > 1)
  75. return T_EXIT_SKIP;
  76. pthread_barrier_init(&d.barrier, NULL, 2);
  77. io_uring_queue_init(NREQS, &ring, 0);
  78. for (i = 0; i < 1000; i++) {
  79. ret = test(&ring, &d);
  80. if (ret != T_EXIT_PASS) {
  81. fprintf(stderr, "Test failed\n");
  82. return T_EXIT_FAIL;
  83. }
  84. }
  85. return T_EXIT_PASS;
  86. }