uringmachine 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. checksums.yaml +7 -0
  2. data/.github/dependabot.yml +12 -0
  3. data/.github/workflows/test.yml +35 -0
  4. data/.gitignore +59 -0
  5. data/.gitmodules +3 -0
  6. data/CHANGELOG.md +7 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +21 -0
  9. data/README.md +11 -0
  10. data/Rakefile +39 -0
  11. data/TODO.md +0 -0
  12. data/examples/echo_server.rb +52 -0
  13. data/examples/event_loop.rb +69 -0
  14. data/examples/fibers.rb +105 -0
  15. data/examples/http_server.rb +56 -0
  16. data/examples/http_server_multishot.rb +57 -0
  17. data/examples/http_server_simpler.rb +34 -0
  18. data/ext/um/extconf.rb +71 -0
  19. data/ext/um/iou.h +101 -0
  20. data/ext/um/op_ctx.c +138 -0
  21. data/ext/um/ring.c +755 -0
  22. data/ext/um/um.c +267 -0
  23. data/ext/um/um.h +97 -0
  24. data/ext/um/um_class.c +175 -0
  25. data/ext/um/um_ext.c +11 -0
  26. data/ext/um/um_op.c +87 -0
  27. data/ext/um/um_utils.c +23 -0
  28. data/lib/uringmachine/version.rb +3 -0
  29. data/lib/uringmachine.rb +8 -0
  30. data/test/helper.rb +70 -0
  31. data/test/test_iou.rb +876 -0
  32. data/test/test_um.rb +168 -0
  33. data/uringmachine.gemspec +27 -0
  34. data/vendor/liburing/.github/actions/codespell/stopwords +7 -0
  35. data/vendor/liburing/.github/pull_request_template.md +86 -0
  36. data/vendor/liburing/.github/workflows/build.yml +137 -0
  37. data/vendor/liburing/.github/workflows/codespell.yml +25 -0
  38. data/vendor/liburing/.github/workflows/shellcheck.yml +20 -0
  39. data/vendor/liburing/.gitignore +41 -0
  40. data/vendor/liburing/CHANGELOG +111 -0
  41. data/vendor/liburing/CITATION.cff +11 -0
  42. data/vendor/liburing/COPYING +502 -0
  43. data/vendor/liburing/COPYING.GPL +339 -0
  44. data/vendor/liburing/LICENSE +20 -0
  45. data/vendor/liburing/Makefile +96 -0
  46. data/vendor/liburing/Makefile.common +7 -0
  47. data/vendor/liburing/Makefile.quiet +11 -0
  48. data/vendor/liburing/README +106 -0
  49. data/vendor/liburing/SECURITY.md +6 -0
  50. data/vendor/liburing/configure +624 -0
  51. data/vendor/liburing/debian/README.Debian +7 -0
  52. data/vendor/liburing/debian/changelog +38 -0
  53. data/vendor/liburing/debian/control +39 -0
  54. data/vendor/liburing/debian/copyright +49 -0
  55. data/vendor/liburing/debian/liburing-dev.install +4 -0
  56. data/vendor/liburing/debian/liburing-dev.manpages +5 -0
  57. data/vendor/liburing/debian/liburing2.install +1 -0
  58. data/vendor/liburing/debian/liburing2.symbols +56 -0
  59. data/vendor/liburing/debian/patches/series +1 -0
  60. data/vendor/liburing/debian/rules +29 -0
  61. data/vendor/liburing/debian/source/format +1 -0
  62. data/vendor/liburing/debian/source/local-options +2 -0
  63. data/vendor/liburing/debian/source/options +1 -0
  64. data/vendor/liburing/debian/watch +3 -0
  65. data/vendor/liburing/examples/Makefile +53 -0
  66. data/vendor/liburing/examples/helpers.c +62 -0
  67. data/vendor/liburing/examples/helpers.h +7 -0
  68. data/vendor/liburing/examples/io_uring-close-test.c +123 -0
  69. data/vendor/liburing/examples/io_uring-cp.c +282 -0
  70. data/vendor/liburing/examples/io_uring-test.c +112 -0
  71. data/vendor/liburing/examples/io_uring-udp.c +403 -0
  72. data/vendor/liburing/examples/link-cp.c +193 -0
  73. data/vendor/liburing/examples/napi-busy-poll-client.c +509 -0
  74. data/vendor/liburing/examples/napi-busy-poll-server.c +450 -0
  75. data/vendor/liburing/examples/poll-bench.c +101 -0
  76. data/vendor/liburing/examples/proxy.c +2461 -0
  77. data/vendor/liburing/examples/proxy.h +102 -0
  78. data/vendor/liburing/examples/rsrc-update-bench.c +100 -0
  79. data/vendor/liburing/examples/send-zerocopy.c +658 -0
  80. data/vendor/liburing/examples/ucontext-cp.c +258 -0
  81. data/vendor/liburing/liburing-ffi.pc.in +12 -0
  82. data/vendor/liburing/liburing.pc.in +12 -0
  83. data/vendor/liburing/liburing.spec +66 -0
  84. data/vendor/liburing/make-debs.sh +55 -0
  85. data/vendor/liburing/src/Makefile +129 -0
  86. data/vendor/liburing/src/arch/aarch64/lib.h +47 -0
  87. data/vendor/liburing/src/arch/aarch64/syscall.h +91 -0
  88. data/vendor/liburing/src/arch/generic/lib.h +17 -0
  89. data/vendor/liburing/src/arch/generic/syscall.h +100 -0
  90. data/vendor/liburing/src/arch/riscv64/lib.h +48 -0
  91. data/vendor/liburing/src/arch/riscv64/syscall.h +100 -0
  92. data/vendor/liburing/src/arch/syscall-defs.h +94 -0
  93. data/vendor/liburing/src/arch/x86/lib.h +11 -0
  94. data/vendor/liburing/src/arch/x86/syscall.h +296 -0
  95. data/vendor/liburing/src/ffi.c +15 -0
  96. data/vendor/liburing/src/include/liburing/barrier.h +81 -0
  97. data/vendor/liburing/src/include/liburing/io_uring.h +818 -0
  98. data/vendor/liburing/src/include/liburing.h +1602 -0
  99. data/vendor/liburing/src/int_flags.h +11 -0
  100. data/vendor/liburing/src/lib.h +52 -0
  101. data/vendor/liburing/src/liburing-ffi.map +211 -0
  102. data/vendor/liburing/src/liburing.map +104 -0
  103. data/vendor/liburing/src/nolibc.c +55 -0
  104. data/vendor/liburing/src/queue.c +468 -0
  105. data/vendor/liburing/src/register.c +374 -0
  106. data/vendor/liburing/src/setup.c +689 -0
  107. data/vendor/liburing/src/setup.h +9 -0
  108. data/vendor/liburing/src/syscall.c +29 -0
  109. data/vendor/liburing/src/syscall.h +53 -0
  110. data/vendor/liburing/src/version.c +21 -0
  111. data/vendor/liburing/test/232c93d07b74.c +305 -0
  112. data/vendor/liburing/test/35fa71a030ca.c +329 -0
  113. data/vendor/liburing/test/500f9fbadef8.c +91 -0
  114. data/vendor/liburing/test/7ad0e4b2f83c.c +94 -0
  115. data/vendor/liburing/test/8a9973408177.c +107 -0
  116. data/vendor/liburing/test/917257daa0fe.c +54 -0
  117. data/vendor/liburing/test/Makefile +297 -0
  118. data/vendor/liburing/test/a0908ae19763.c +59 -0
  119. data/vendor/liburing/test/a4c0b3decb33.c +181 -0
  120. data/vendor/liburing/test/accept-link.c +255 -0
  121. data/vendor/liburing/test/accept-non-empty.c +256 -0
  122. data/vendor/liburing/test/accept-reuse.c +163 -0
  123. data/vendor/liburing/test/accept-test.c +83 -0
  124. data/vendor/liburing/test/accept.c +919 -0
  125. data/vendor/liburing/test/across-fork.c +284 -0
  126. data/vendor/liburing/test/b19062a56726.c +54 -0
  127. data/vendor/liburing/test/b5837bd5311d.c +78 -0
  128. data/vendor/liburing/test/bind-listen.c +408 -0
  129. data/vendor/liburing/test/buf-ring-nommap.c +123 -0
  130. data/vendor/liburing/test/buf-ring-put.c +83 -0
  131. data/vendor/liburing/test/buf-ring.c +473 -0
  132. data/vendor/liburing/test/ce593a6c480a.c +139 -0
  133. data/vendor/liburing/test/close-opath.c +123 -0
  134. data/vendor/liburing/test/config +14 -0
  135. data/vendor/liburing/test/connect-rep.c +204 -0
  136. data/vendor/liburing/test/connect.c +442 -0
  137. data/vendor/liburing/test/coredump.c +60 -0
  138. data/vendor/liburing/test/cq-full.c +97 -0
  139. data/vendor/liburing/test/cq-overflow.c +530 -0
  140. data/vendor/liburing/test/cq-peek-batch.c +103 -0
  141. data/vendor/liburing/test/cq-ready.c +95 -0
  142. data/vendor/liburing/test/cq-size.c +65 -0
  143. data/vendor/liburing/test/d4ae271dfaae.c +96 -0
  144. data/vendor/liburing/test/d77a67ed5f27.c +65 -0
  145. data/vendor/liburing/test/defer-taskrun.c +391 -0
  146. data/vendor/liburing/test/defer-tw-timeout.c +173 -0
  147. data/vendor/liburing/test/defer.c +319 -0
  148. data/vendor/liburing/test/double-poll-crash.c +195 -0
  149. data/vendor/liburing/test/drop-submit.c +94 -0
  150. data/vendor/liburing/test/eeed8b54e0df.c +120 -0
  151. data/vendor/liburing/test/empty-eownerdead.c +45 -0
  152. data/vendor/liburing/test/eploop.c +74 -0
  153. data/vendor/liburing/test/eventfd-disable.c +179 -0
  154. data/vendor/liburing/test/eventfd-reg.c +77 -0
  155. data/vendor/liburing/test/eventfd-ring.c +98 -0
  156. data/vendor/liburing/test/eventfd.c +113 -0
  157. data/vendor/liburing/test/evloop.c +73 -0
  158. data/vendor/liburing/test/exec-target.c +6 -0
  159. data/vendor/liburing/test/exit-no-cleanup.c +117 -0
  160. data/vendor/liburing/test/fadvise.c +202 -0
  161. data/vendor/liburing/test/fallocate.c +265 -0
  162. data/vendor/liburing/test/fc2a85cb02ef.c +132 -0
  163. data/vendor/liburing/test/fd-install.c +500 -0
  164. data/vendor/liburing/test/fd-pass.c +237 -0
  165. data/vendor/liburing/test/fdinfo.c +419 -0
  166. data/vendor/liburing/test/file-register.c +1189 -0
  167. data/vendor/liburing/test/file-update.c +231 -0
  168. data/vendor/liburing/test/file-verify.c +654 -0
  169. data/vendor/liburing/test/files-exit-hang-poll.c +114 -0
  170. data/vendor/liburing/test/files-exit-hang-timeout.c +137 -0
  171. data/vendor/liburing/test/fixed-buf-iter.c +115 -0
  172. data/vendor/liburing/test/fixed-buf-merge.c +101 -0
  173. data/vendor/liburing/test/fixed-hugepage.c +411 -0
  174. data/vendor/liburing/test/fixed-link.c +90 -0
  175. data/vendor/liburing/test/fixed-reuse.c +160 -0
  176. data/vendor/liburing/test/fpos.c +255 -0
  177. data/vendor/liburing/test/fsnotify.c +118 -0
  178. data/vendor/liburing/test/fsync.c +224 -0
  179. data/vendor/liburing/test/futex.c +571 -0
  180. data/vendor/liburing/test/hardlink.c +170 -0
  181. data/vendor/liburing/test/helpers.c +318 -0
  182. data/vendor/liburing/test/helpers.h +108 -0
  183. data/vendor/liburing/test/ignore-single-mmap.c +48 -0
  184. data/vendor/liburing/test/init-mem.c +164 -0
  185. data/vendor/liburing/test/io-cancel.c +561 -0
  186. data/vendor/liburing/test/io_uring_enter.c +264 -0
  187. data/vendor/liburing/test/io_uring_passthrough.c +482 -0
  188. data/vendor/liburing/test/io_uring_register.c +503 -0
  189. data/vendor/liburing/test/io_uring_setup.c +110 -0
  190. data/vendor/liburing/test/iopoll-leak.c +85 -0
  191. data/vendor/liburing/test/iopoll-overflow.c +118 -0
  192. data/vendor/liburing/test/iopoll.c +465 -0
  193. data/vendor/liburing/test/lfs-openat-write.c +119 -0
  194. data/vendor/liburing/test/lfs-openat.c +273 -0
  195. data/vendor/liburing/test/link-timeout.c +1108 -0
  196. data/vendor/liburing/test/link.c +497 -0
  197. data/vendor/liburing/test/link_drain.c +255 -0
  198. data/vendor/liburing/test/madvise.c +195 -0
  199. data/vendor/liburing/test/min-timeout-wait.c +354 -0
  200. data/vendor/liburing/test/min-timeout.c +233 -0
  201. data/vendor/liburing/test/mkdir.c +112 -0
  202. data/vendor/liburing/test/msg-ring-fd.c +331 -0
  203. data/vendor/liburing/test/msg-ring-flags.c +212 -0
  204. data/vendor/liburing/test/msg-ring-overflow.c +159 -0
  205. data/vendor/liburing/test/msg-ring.c +467 -0
  206. data/vendor/liburing/test/multicqes_drain.c +429 -0
  207. data/vendor/liburing/test/napi-test.c +215 -0
  208. data/vendor/liburing/test/napi-test.sh +48 -0
  209. data/vendor/liburing/test/no-mmap-inval.c +42 -0
  210. data/vendor/liburing/test/nolibc.c +62 -0
  211. data/vendor/liburing/test/nop-all-sizes.c +99 -0
  212. data/vendor/liburing/test/nop.c +177 -0
  213. data/vendor/liburing/test/nvme.h +169 -0
  214. data/vendor/liburing/test/ooo-file-unreg.c +82 -0
  215. data/vendor/liburing/test/open-close.c +261 -0
  216. data/vendor/liburing/test/open-direct-link.c +188 -0
  217. data/vendor/liburing/test/open-direct-pick.c +180 -0
  218. data/vendor/liburing/test/openat2.c +312 -0
  219. data/vendor/liburing/test/personality.c +204 -0
  220. data/vendor/liburing/test/pipe-bug.c +95 -0
  221. data/vendor/liburing/test/pipe-eof.c +83 -0
  222. data/vendor/liburing/test/pipe-reuse.c +105 -0
  223. data/vendor/liburing/test/poll-cancel-all.c +496 -0
  224. data/vendor/liburing/test/poll-cancel-ton.c +135 -0
  225. data/vendor/liburing/test/poll-cancel.c +228 -0
  226. data/vendor/liburing/test/poll-link.c +221 -0
  227. data/vendor/liburing/test/poll-many.c +230 -0
  228. data/vendor/liburing/test/poll-mshot-overflow.c +265 -0
  229. data/vendor/liburing/test/poll-mshot-update.c +323 -0
  230. data/vendor/liburing/test/poll-race-mshot.c +276 -0
  231. data/vendor/liburing/test/poll-race.c +105 -0
  232. data/vendor/liburing/test/poll-ring.c +48 -0
  233. data/vendor/liburing/test/poll-v-poll.c +353 -0
  234. data/vendor/liburing/test/poll.c +327 -0
  235. data/vendor/liburing/test/probe.c +135 -0
  236. data/vendor/liburing/test/read-before-exit.c +129 -0
  237. data/vendor/liburing/test/read-mshot-empty.c +153 -0
  238. data/vendor/liburing/test/read-mshot.c +404 -0
  239. data/vendor/liburing/test/read-write.c +1013 -0
  240. data/vendor/liburing/test/recv-msgall-stream.c +398 -0
  241. data/vendor/liburing/test/recv-msgall.c +263 -0
  242. data/vendor/liburing/test/recv-multishot.c +602 -0
  243. data/vendor/liburing/test/recvsend_bundle.c +691 -0
  244. data/vendor/liburing/test/reg-fd-only.c +131 -0
  245. data/vendor/liburing/test/reg-hint.c +56 -0
  246. data/vendor/liburing/test/reg-reg-ring.c +90 -0
  247. data/vendor/liburing/test/regbuf-merge.c +91 -0
  248. data/vendor/liburing/test/register-restrictions.c +633 -0
  249. data/vendor/liburing/test/rename.c +132 -0
  250. data/vendor/liburing/test/ring-leak.c +283 -0
  251. data/vendor/liburing/test/ring-leak2.c +249 -0
  252. data/vendor/liburing/test/ringbuf-read.c +196 -0
  253. data/vendor/liburing/test/ringbuf-status.c +242 -0
  254. data/vendor/liburing/test/rsrc_tags.c +461 -0
  255. data/vendor/liburing/test/runtests-loop.sh +16 -0
  256. data/vendor/liburing/test/runtests-quiet.sh +11 -0
  257. data/vendor/liburing/test/runtests.sh +168 -0
  258. data/vendor/liburing/test/rw_merge_test.c +98 -0
  259. data/vendor/liburing/test/self.c +91 -0
  260. data/vendor/liburing/test/send-zerocopy.c +971 -0
  261. data/vendor/liburing/test/send_recv.c +412 -0
  262. data/vendor/liburing/test/send_recvmsg.c +444 -0
  263. data/vendor/liburing/test/shared-wq.c +84 -0
  264. data/vendor/liburing/test/short-read.c +75 -0
  265. data/vendor/liburing/test/shutdown.c +165 -0
  266. data/vendor/liburing/test/sigfd-deadlock.c +88 -0
  267. data/vendor/liburing/test/single-issuer.c +169 -0
  268. data/vendor/liburing/test/skip-cqe.c +428 -0
  269. data/vendor/liburing/test/socket-getsetsock-cmd.c +346 -0
  270. data/vendor/liburing/test/socket-io-cmd.c +237 -0
  271. data/vendor/liburing/test/socket-rw-eagain.c +149 -0
  272. data/vendor/liburing/test/socket-rw-offset.c +149 -0
  273. data/vendor/liburing/test/socket-rw.c +137 -0
  274. data/vendor/liburing/test/socket.c +408 -0
  275. data/vendor/liburing/test/splice.c +512 -0
  276. data/vendor/liburing/test/sq-full-cpp.cc +45 -0
  277. data/vendor/liburing/test/sq-full.c +45 -0
  278. data/vendor/liburing/test/sq-poll-dup.c +211 -0
  279. data/vendor/liburing/test/sq-poll-kthread.c +169 -0
  280. data/vendor/liburing/test/sq-poll-share.c +138 -0
  281. data/vendor/liburing/test/sq-space_left.c +159 -0
  282. data/vendor/liburing/test/sqpoll-disable-exit.c +196 -0
  283. data/vendor/liburing/test/sqpoll-exec.c +132 -0
  284. data/vendor/liburing/test/sqpoll-exit-hang.c +78 -0
  285. data/vendor/liburing/test/sqpoll-sleep.c +69 -0
  286. data/vendor/liburing/test/statx.c +172 -0
  287. data/vendor/liburing/test/stdout.c +232 -0
  288. data/vendor/liburing/test/submit-and-wait.c +108 -0
  289. data/vendor/liburing/test/submit-link-fail.c +156 -0
  290. data/vendor/liburing/test/submit-reuse.c +237 -0
  291. data/vendor/liburing/test/symlink.c +117 -0
  292. data/vendor/liburing/test/sync-cancel.c +235 -0
  293. data/vendor/liburing/test/teardowns.c +58 -0
  294. data/vendor/liburing/test/test.h +36 -0
  295. data/vendor/liburing/test/thread-exit.c +143 -0
  296. data/vendor/liburing/test/timeout-new.c +256 -0
  297. data/vendor/liburing/test/timeout.c +1798 -0
  298. data/vendor/liburing/test/truncate.c +186 -0
  299. data/vendor/liburing/test/tty-write-dpoll.c +60 -0
  300. data/vendor/liburing/test/unlink.c +112 -0
  301. data/vendor/liburing/test/version.c +25 -0
  302. data/vendor/liburing/test/wait-timeout.c +287 -0
  303. data/vendor/liburing/test/waitid.c +373 -0
  304. data/vendor/liburing/test/wakeup-hang.c +162 -0
  305. data/vendor/liburing/test/wq-aff.c +146 -0
  306. data/vendor/liburing/test/xattr.c +442 -0
  307. metadata +412 -0
@@ -0,0 +1,450 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ /*
3
+ * Simple ping/pong backend which can use the io_uring NAPI support.
4
+ *
5
+ * Needs to be run as root because it sets SCHED_FIFO scheduling class,
6
+ * but will work without that.
7
+ *
8
+ * Example:
9
+ *
10
+ * sudo examples/napi-busy-poll-server -l -a 192.168.2.2 -n100000 \
11
+ * -p4444 -t10 -b -u
12
+ *
13
+ * will respond to 100k packages, using NAPI.
14
+ */
15
+ #include <ctype.h>
16
+ #include <errno.h>
17
+ #include <getopt.h>
18
+ #include <liburing.h>
19
+ #include <math.h>
20
+ #include <sched.h>
21
+ #include <stdio.h>
22
+ #include <stdlib.h>
23
+ #include <string.h>
24
+ #include <sys/types.h>
25
+ #include <sys/socket.h>
26
+ #include <time.h>
27
+ #include <unistd.h>
28
+ #include <arpa/inet.h>
29
+ #include <netdb.h>
30
+ #include <netinet/in.h>
31
+
32
+ #define MAXBUFLEN 100
33
+ #define PORTNOLEN 10
34
+ #define ADDRLEN 80
35
+ #define RINGSIZE 1024
36
+
37
+ #define printable(ch) (isprint((unsigned char)ch) ? ch : '#')
38
+
39
+ enum {
40
+ IOURING_RECV,
41
+ IOURING_SEND,
42
+ IOURING_RECVMSG,
43
+ IOURING_SENDMSG
44
+ };
45
+
46
+ struct ctx
47
+ {
48
+ struct io_uring ring;
49
+ union {
50
+ struct sockaddr_in6 saddr6;
51
+ struct sockaddr_in saddr;
52
+ };
53
+ struct iovec iov;
54
+ struct msghdr msg;
55
+
56
+ int sockfd;
57
+ int buffer_len;
58
+ int num_pings;
59
+ bool napi_check;
60
+
61
+ union {
62
+ char buffer[MAXBUFLEN];
63
+ struct timespec ts;
64
+ };
65
+ };
66
+
67
+ struct options
68
+ {
69
+ int num_pings;
70
+ __u32 timeout;
71
+
72
+ bool listen;
73
+ bool defer_tw;
74
+ bool sq_poll;
75
+ bool busy_loop;
76
+ bool prefer_busy_poll;
77
+ bool ipv6;
78
+
79
+ char port[PORTNOLEN];
80
+ char addr[ADDRLEN];
81
+ };
82
+
83
+ static struct options opt;
84
+
85
+ static struct option longopts[] =
86
+ {
87
+ {"address" , 1, NULL, 'a'},
88
+ {"busy" , 0, NULL, 'b'},
89
+ {"help" , 0, NULL, 'h'},
90
+ {"listen" , 0, NULL, 'l'},
91
+ {"num_pings", 1, NULL, 'n'},
92
+ {"port" , 1, NULL, 'p'},
93
+ {"prefer" , 1, NULL, 'u'},
94
+ {"sqpoll" , 0, NULL, 's'},
95
+ {"timeout" , 1, NULL, 't'},
96
+ {NULL , 0, NULL, 0 }
97
+ };
98
+
99
+ static void printUsage(const char *name)
100
+ {
101
+ fprintf(stderr,
102
+ "Usage: %s [-l|--listen] [-a|--address ip_address] [-p|--port port-no] [-s|--sqpoll]"
103
+ " [-b|--busy] [-n|--num pings] [-t|--timeout busy-poll-timeout] [-u|--prefer] [-6] [-h|--help]\n"
104
+ " --listen\n"
105
+ "-l : Server mode\n"
106
+ "--address\n"
107
+ "-a : remote or local ipv6 address\n"
108
+ "--busy\n"
109
+ "-b : busy poll io_uring instead of blocking.\n"
110
+ "--num_pings\n"
111
+ "-n : number of pings\n"
112
+ "--port\n"
113
+ "-p : port\n"
114
+ "--sqpoll\n"
115
+ "-s : Configure io_uring to use SQPOLL thread\n"
116
+ "--timeout\n"
117
+ "-t : Configure NAPI busy poll timeout"
118
+ "--prefer\n"
119
+ "-u : prefer NAPI busy poll\n"
120
+ "-6 : use IPV6\n"
121
+ "--help\n"
122
+ "-h : Display this usage message\n\n",
123
+ name);
124
+ }
125
+
126
+ static void printError(const char *msg, int opt)
127
+ {
128
+ if (msg && opt)
129
+ fprintf(stderr, "%s (-%c)\n", msg, printable(opt));
130
+ }
131
+
132
+ static void setProcessScheduler(void)
133
+ {
134
+ struct sched_param param;
135
+
136
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
137
+ if (sched_setscheduler(0, SCHED_FIFO, &param) < 0)
138
+ fprintf(stderr, "sched_setscheduler() failed: (%d) %s\n",
139
+ errno, strerror(errno));
140
+ }
141
+
142
+ static uint64_t encodeUserData(char type, int fd)
143
+ {
144
+ return (uint32_t)fd | ((__u64)type << 56);
145
+ }
146
+
147
+ static void decodeUserData(uint64_t data, char *type, int *fd)
148
+ {
149
+ *type = data >> 56;
150
+ *fd = data & 0xffffffffU;
151
+ }
152
+
153
+ static const char *opTypeToStr(char type)
154
+ {
155
+ const char *res;
156
+
157
+ switch (type) {
158
+ case IOURING_RECV:
159
+ res = "IOURING_RECV";
160
+ break;
161
+ case IOURING_SEND:
162
+ res = "IOURING_SEND";
163
+ break;
164
+ case IOURING_RECVMSG:
165
+ res = "IOURING_RECVMSG";
166
+ break;
167
+ case IOURING_SENDMSG:
168
+ res = "IOURING_SENDMSG";
169
+ break;
170
+ default:
171
+ res = "Unknown";
172
+ }
173
+
174
+ return res;
175
+ }
176
+
177
+ static void reportNapi(struct ctx *ctx)
178
+ {
179
+ unsigned int napi_id = 0;
180
+ socklen_t len = sizeof(napi_id);
181
+
182
+ getsockopt(ctx->sockfd, SOL_SOCKET, SO_INCOMING_NAPI_ID, &napi_id, &len);
183
+ if (napi_id)
184
+ printf(" napi id: %d\n", napi_id);
185
+ else
186
+ printf(" unassigned napi id\n");
187
+
188
+ ctx->napi_check = true;
189
+ }
190
+
191
+ static void sendPing(struct ctx *ctx)
192
+ {
193
+ struct io_uring_sqe *sqe = io_uring_get_sqe(&ctx->ring);
194
+
195
+ io_uring_prep_sendmsg(sqe, ctx->sockfd, &ctx->msg, 0);
196
+ sqe->user_data = encodeUserData(IOURING_SENDMSG, ctx->sockfd);
197
+ }
198
+
199
+ static void receivePing(struct ctx *ctx)
200
+ {
201
+ struct io_uring_sqe *sqe;
202
+
203
+ bzero(&ctx->msg, sizeof(struct msghdr));
204
+ if (opt.ipv6) {
205
+ ctx->msg.msg_name = &ctx->saddr6;
206
+ ctx->msg.msg_namelen = sizeof(struct sockaddr_in6);
207
+ } else {
208
+ ctx->msg.msg_name = &ctx->saddr;
209
+ ctx->msg.msg_namelen = sizeof(struct sockaddr_in);
210
+ }
211
+ ctx->iov.iov_base = ctx->buffer;
212
+ ctx->iov.iov_len = MAXBUFLEN;
213
+ ctx->msg.msg_iov = &ctx->iov;
214
+ ctx->msg.msg_iovlen = 1;
215
+
216
+ sqe = io_uring_get_sqe(&ctx->ring);
217
+ io_uring_prep_recvmsg(sqe, ctx->sockfd, &ctx->msg, 0);
218
+ sqe->user_data = encodeUserData(IOURING_RECVMSG, ctx->sockfd);
219
+ }
220
+
221
+ static void completion(struct ctx *ctx, struct io_uring_cqe *cqe)
222
+ {
223
+ char type;
224
+ int fd;
225
+ int res = cqe->res;
226
+
227
+ decodeUserData(cqe->user_data, &type, &fd);
228
+ if (res < 0) {
229
+ fprintf(stderr, "unexpected %s failure: (%d) %s\n",
230
+ opTypeToStr(type), -res, strerror(-res));
231
+ abort();
232
+ }
233
+
234
+ switch (type) {
235
+ case IOURING_SENDMSG:
236
+ receivePing(ctx);
237
+ --ctx->num_pings;
238
+ break;
239
+ case IOURING_RECVMSG:
240
+ ctx->iov.iov_len = res;
241
+ sendPing(ctx);
242
+ if (!ctx->napi_check)
243
+ reportNapi(ctx);
244
+ break;
245
+ default:
246
+ fprintf(stderr, "unexpected %s completion\n",
247
+ opTypeToStr(type));
248
+ abort();
249
+ break;
250
+ }
251
+ }
252
+
253
+ int main(int argc, char *argv[])
254
+ {
255
+ int flag;
256
+ struct ctx ctx;
257
+ struct __kernel_timespec *tsPtr;
258
+ struct __kernel_timespec ts;
259
+ struct io_uring_params params;
260
+ struct io_uring_napi napi;
261
+ int ret, af;
262
+
263
+ memset(&opt, 0, sizeof(struct options));
264
+
265
+ // Process flags.
266
+ while ((flag = getopt_long(argc, argv, ":lhs:bua:n:p:t:6d:", longopts, NULL)) != -1) {
267
+ switch (flag) {
268
+ case 'a':
269
+ strcpy(opt.addr, optarg);
270
+ break;
271
+ case 'b':
272
+ opt.busy_loop = true;
273
+ break;
274
+ case 'h':
275
+ printUsage(argv[0]);
276
+ exit(0);
277
+ break;
278
+ case 'l':
279
+ opt.listen = true;
280
+ break;
281
+ case 'n':
282
+ opt.num_pings = atoi(optarg) + 1;
283
+ break;
284
+ case 'p':
285
+ strcpy(opt.port, optarg);
286
+ break;
287
+ case 's':
288
+ opt.sq_poll = !!atoi(optarg);
289
+ break;
290
+ case 't':
291
+ opt.timeout = atoi(optarg);
292
+ break;
293
+ case 'u':
294
+ opt.prefer_busy_poll = true;
295
+ break;
296
+ case '6':
297
+ opt.ipv6 = true;
298
+ break;
299
+ case 'd':
300
+ opt.defer_tw = !!atoi(optarg);
301
+ break;
302
+ case ':':
303
+ printError("Missing argument", optopt);
304
+ printUsage(argv[0]);
305
+ exit(-1);
306
+ break;
307
+ case '?':
308
+ printError("Unrecognized option", optopt);
309
+ printUsage(argv[0]);
310
+ exit(-1);
311
+ break;
312
+
313
+ default:
314
+ fprintf(stderr, "Fatal: Unexpected case in CmdLineProcessor switch()\n");
315
+ exit(-1);
316
+ break;
317
+ }
318
+ }
319
+
320
+ if (strlen(opt.addr) == 0) {
321
+ fprintf(stderr, "address option is mandatory\n");
322
+ printUsage(argv[0]);
323
+ exit(1);
324
+ }
325
+
326
+ if (opt.ipv6) {
327
+ af = AF_INET6;
328
+ ctx.saddr6.sin6_port = htons(atoi(opt.port));
329
+ ctx.saddr6.sin6_family = AF_INET6;
330
+ } else {
331
+ af = AF_INET;
332
+ ctx.saddr.sin_port = htons(atoi(opt.port));
333
+ ctx.saddr.sin_family = AF_INET;
334
+ }
335
+
336
+ if (opt.ipv6)
337
+ ret = inet_pton(AF_INET6, opt.addr, &ctx.saddr6.sin6_addr);
338
+ else
339
+ ret = inet_pton(AF_INET, opt.addr, &ctx.saddr.sin_addr);
340
+ if (ret <= 0) {
341
+ fprintf(stderr, "inet_pton error for %s\n", optarg);
342
+ printUsage(argv[0]);
343
+ exit(1);
344
+ }
345
+
346
+ // Connect to server.
347
+ fprintf(stdout, "Listening %s : %s...\n", opt.addr, opt.port);
348
+
349
+ if ((ctx.sockfd = socket(af, SOCK_DGRAM, 0)) < 0) {
350
+ fprintf(stderr, "socket() failed: (%d) %s\n", errno, strerror(errno));
351
+ exit(1);
352
+ }
353
+
354
+ if (opt.ipv6)
355
+ ret = bind(ctx.sockfd, (struct sockaddr *)&ctx.saddr6, sizeof(struct sockaddr_in6));
356
+ else
357
+ ret = bind(ctx.sockfd, (struct sockaddr *)&ctx.saddr, sizeof(struct sockaddr_in));
358
+ if (ret < 0) {
359
+ fprintf(stderr, "bind() failed: (%d) %s\n", errno, strerror(errno));
360
+ exit(1);
361
+ }
362
+
363
+ // Setup ring.
364
+ memset(&params, 0, sizeof(params));
365
+ memset(&ts, 0, sizeof(ts));
366
+ memset(&napi, 0, sizeof(napi));
367
+
368
+ params.flags = IORING_SETUP_SINGLE_ISSUER;
369
+ if (opt.defer_tw) {
370
+ params.flags |= IORING_SETUP_DEFER_TASKRUN;
371
+ } else if (opt.sq_poll) {
372
+ params.flags = IORING_SETUP_SQPOLL;
373
+ params.sq_thread_idle = 50;
374
+ } else {
375
+ params.flags |= IORING_SETUP_COOP_TASKRUN;
376
+ }
377
+
378
+ ret = io_uring_queue_init_params(RINGSIZE, &ctx.ring, &params);
379
+ if (ret) {
380
+ fprintf(stderr, "io_uring_queue_init_params() failed: (%d) %s\n",
381
+ ret, strerror(-ret));
382
+ exit(1);
383
+ }
384
+
385
+ if (opt.timeout || opt.prefer_busy_poll) {
386
+ napi.prefer_busy_poll = opt.prefer_busy_poll;
387
+ napi.busy_poll_to = opt.timeout;
388
+
389
+ ret = io_uring_register_napi(&ctx.ring, &napi);
390
+ if (ret) {
391
+ fprintf(stderr, "io_uring_register_napi: %d\n", ret);
392
+ exit(1);
393
+ }
394
+ }
395
+
396
+ if (opt.busy_loop)
397
+ tsPtr = &ts;
398
+ else
399
+ tsPtr = NULL;
400
+
401
+ // Use realtime scheduler.
402
+ setProcessScheduler();
403
+
404
+ // Copy payload.
405
+ clock_gettime(CLOCK_REALTIME, &ctx.ts);
406
+
407
+ // Setup context.
408
+ ctx.napi_check = false;
409
+ ctx.buffer_len = sizeof(struct timespec);
410
+ ctx.num_pings = opt.num_pings;
411
+
412
+ // Receive initial message to get napi id.
413
+ receivePing(&ctx);
414
+
415
+ while (ctx.num_pings != 0) {
416
+ int res;
417
+ unsigned int num_completed = 0;
418
+ unsigned int head;
419
+ struct io_uring_cqe *cqe;
420
+
421
+ do {
422
+ res = io_uring_submit_and_wait_timeout(&ctx.ring, &cqe, 1, tsPtr, NULL);
423
+ if (res >= 0)
424
+ break;
425
+ else if (res == -ETIME)
426
+ continue;
427
+ fprintf(stderr, "submit_and_wait: %d\n", res);
428
+ exit(1);
429
+ } while (1);
430
+
431
+ io_uring_for_each_cqe(&ctx.ring, head, cqe) {
432
+ ++num_completed;
433
+ completion(&ctx, cqe);
434
+ }
435
+
436
+ if (num_completed)
437
+ io_uring_cq_advance(&ctx.ring, num_completed);
438
+ }
439
+
440
+ // Clean up.
441
+ if (opt.timeout || opt.prefer_busy_poll) {
442
+ ret = io_uring_unregister_napi(&ctx.ring, &napi);
443
+ if (ret)
444
+ fprintf(stderr, "io_uring_unregister_napi: %d\n", ret);
445
+ }
446
+
447
+ io_uring_queue_exit(&ctx.ring);
448
+ close(ctx.sockfd);
449
+ return 0;
450
+ }
@@ -0,0 +1,101 @@
1
+ /* SPDX-License-Identifier: MIT */
2
+ #include <errno.h>
3
+ #include <stdio.h>
4
+ #include <unistd.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <signal.h>
8
+ #include <poll.h>
9
+ #include <sys/time.h>
10
+ #include <sys/wait.h>
11
+
12
+ #include "liburing.h"
13
+
14
+ static char buf[4096];
15
+ static unsigned long runtime_ms = 10000;
16
+
17
+ static unsigned long gettimeofday_ms(void)
18
+ {
19
+ struct timeval tv;
20
+
21
+ gettimeofday(&tv, NULL);
22
+ return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
23
+ }
24
+
25
+ int main(void)
26
+ {
27
+ unsigned long tstop;
28
+ unsigned long nr_reqs = 0;
29
+ struct io_uring_cqe *cqe;
30
+ struct io_uring_sqe *sqe;
31
+ struct io_uring ring;
32
+ int pipe1[2];
33
+ int ret, i, qd = 32;
34
+
35
+ if (pipe(pipe1) != 0) {
36
+ perror("pipe");
37
+ return 1;
38
+ }
39
+
40
+ ret = io_uring_queue_init(1024, &ring, IORING_SETUP_SINGLE_ISSUER);
41
+ if (ret == -EINVAL) {
42
+ fprintf(stderr, "can't single\n");
43
+ ret = io_uring_queue_init(1024, &ring, 0);
44
+ }
45
+ if (ret) {
46
+ fprintf(stderr, "child: ring setup failed: %d\n", ret);
47
+ return 1;
48
+ }
49
+
50
+ ret = io_uring_register_files(&ring, pipe1, 2);
51
+ if (ret < 0) {
52
+ fprintf(stderr, "io_uring_register_files failed\n");
53
+ return 1;
54
+ }
55
+
56
+ ret = io_uring_register_ring_fd(&ring);
57
+ if (ret < 0) {
58
+ fprintf(stderr, "io_uring_register_ring_fd failed\n");
59
+ return 1;
60
+ }
61
+
62
+ tstop = gettimeofday_ms() + runtime_ms;
63
+ do {
64
+ for (i = 0; i < qd; i++) {
65
+ sqe = io_uring_get_sqe(&ring);
66
+ io_uring_prep_poll_add(sqe, 0, POLLIN);
67
+ sqe->flags |= IOSQE_FIXED_FILE;
68
+ sqe->user_data = 1;
69
+ }
70
+
71
+ ret = io_uring_submit(&ring);
72
+ if (ret != qd) {
73
+ fprintf(stderr, "child: sqe submit failed: %d\n", ret);
74
+ return 1;
75
+ }
76
+
77
+ ret = write(pipe1[1], buf, 1);
78
+ if (ret != 1) {
79
+ fprintf(stderr, "write failed %i\n", errno);
80
+ return 1;
81
+ }
82
+ ret = read(pipe1[0], buf, 1);
83
+ if (ret != 1) {
84
+ fprintf(stderr, "read failed %i\n", errno);
85
+ return 1;
86
+ }
87
+
88
+ for (i = 0; i < qd; i++) {
89
+ ret = io_uring_wait_cqe(&ring, &cqe);
90
+ if (ret < 0) {
91
+ fprintf(stderr, "child: wait completion %d\n", ret);
92
+ break;
93
+ }
94
+ io_uring_cqe_seen(&ring, cqe);
95
+ nr_reqs++;
96
+ }
97
+ } while (gettimeofday_ms() < tstop);
98
+
99
+ fprintf(stderr, "requests/s: %lu\n", nr_reqs * 1000UL / runtime_ms);
100
+ return 0;
101
+ }