uringmachine 0.10 → 0.11.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/examples/bm_http_parse.rb +108 -35
  4. data/examples/bm_side_running.rb +83 -0
  5. data/examples/bm_sqlite.rb +1 -1
  6. data/ext/um/um.c +17 -1
  7. data/ext/um/um.h +30 -0
  8. data/ext/um/um_ext.c +2 -0
  9. data/ext/um/um_stream.c +372 -0
  10. data/ext/um/um_stream_class.c +121 -0
  11. data/lib/uringmachine/version.rb +1 -1
  12. data/lib/uringmachine.rb +20 -16
  13. data/test/test_stream.rb +133 -0
  14. data/test/test_um.rb +63 -0
  15. data/uringmachine.gemspec +1 -0
  16. data/vendor/liburing/.github/workflows/{build.yml → ci.yml} +107 -42
  17. data/vendor/liburing/.gitignore +1 -0
  18. data/vendor/liburing/CHANGELOG +10 -0
  19. data/vendor/liburing/README +5 -0
  20. data/vendor/liburing/configure +1 -1
  21. data/vendor/liburing/examples/Makefile +1 -0
  22. data/vendor/liburing/examples/helpers.c +25 -0
  23. data/vendor/liburing/examples/helpers.h +13 -0
  24. data/vendor/liburing/examples/io_uring-test.c +3 -0
  25. data/vendor/liburing/examples/proxy.c +1 -1
  26. data/vendor/liburing/examples/reg-wait.c +41 -6
  27. data/vendor/liburing/examples/send-zerocopy.c +79 -32
  28. data/vendor/liburing/examples/zcrx.c +436 -0
  29. data/vendor/liburing/liburing.spec +1 -1
  30. data/vendor/liburing/src/Makefile +0 -1
  31. data/vendor/liburing/src/arch/generic/syscall.h +2 -2
  32. data/vendor/liburing/src/arch/syscall-defs.h +2 -2
  33. data/vendor/liburing/src/include/liburing/io_uring.h +101 -17
  34. data/vendor/liburing/src/include/liburing.h +179 -59
  35. data/vendor/liburing/src/int_flags.h +4 -1
  36. data/vendor/liburing/src/liburing-ffi.map +14 -2
  37. data/vendor/liburing/src/liburing.map +9 -2
  38. data/vendor/liburing/src/queue.c +35 -30
  39. data/vendor/liburing/src/register.c +46 -15
  40. data/vendor/liburing/src/sanitize.c +6 -9
  41. data/vendor/liburing/src/setup.c +37 -71
  42. data/vendor/liburing/src/syscall.c +2 -2
  43. data/vendor/liburing/test/232c93d07b74.c +1 -0
  44. data/vendor/liburing/test/Makefile +9 -0
  45. data/vendor/liburing/test/accept-test.c +1 -0
  46. data/vendor/liburing/test/cmd-discard.c +16 -8
  47. data/vendor/liburing/test/connect.c +11 -7
  48. data/vendor/liburing/test/epwait.c +420 -0
  49. data/vendor/liburing/test/eventfd-ring.c +30 -5
  50. data/vendor/liburing/test/fallocate.c +1 -1
  51. data/vendor/liburing/test/fixed-hugepage.c +10 -7
  52. data/vendor/liburing/test/fixed-seg.c +187 -0
  53. data/vendor/liburing/test/helpers.c +121 -0
  54. data/vendor/liburing/test/helpers.h +13 -0
  55. data/vendor/liburing/test/init-mem.c +2 -0
  56. data/vendor/liburing/test/io_uring_passthrough.c +78 -62
  57. data/vendor/liburing/test/iopoll-overflow.c +5 -4
  58. data/vendor/liburing/test/iopoll.c +20 -10
  59. data/vendor/liburing/test/iowait.c +141 -0
  60. data/vendor/liburing/test/nvme.h +2 -0
  61. data/vendor/liburing/test/pipe-bug.c +11 -5
  62. data/vendor/liburing/test/pipe-eof.c +11 -1
  63. data/vendor/liburing/test/read-inc-file.c +150 -0
  64. data/vendor/liburing/test/read-write.c +21 -14
  65. data/vendor/liburing/test/recv-bundle-short-ooo.c +435 -0
  66. data/vendor/liburing/test/recv-multishot.c +2 -2
  67. data/vendor/liburing/test/reg-wait.c +449 -120
  68. data/vendor/liburing/test/regbuf-clone.c +53 -0
  69. data/vendor/liburing/test/resize-rings.c +25 -2
  70. data/vendor/liburing/test/rsrc_tags.c +67 -14
  71. data/vendor/liburing/test/send-zerocopy.c +52 -130
  72. data/vendor/liburing/test/sendmsg_iov_clean.c +216 -0
  73. data/vendor/liburing/test/socket-nb.c +158 -0
  74. data/vendor/liburing/test/sqwait.c +9 -11
  75. data/vendor/liburing/test/timeout.c +198 -0
  76. data/vendor/liburing/test/vec-regbuf.c +609 -0
  77. data/vendor/liburing/test/wait-timeout.c +1 -1
  78. data/vendor/liburing/test/wq-aff.c +5 -1
  79. data/vendor/liburing/test/zcrx.c +928 -0
  80. metadata +30 -4
  81. data/vendor/liburing/.github/workflows/codespell.yml +0 -25
  82. data/vendor/liburing/.github/workflows/shellcheck.yml +0 -20
data/test/test_um.rb CHANGED
@@ -1224,6 +1224,34 @@ class WaitTest < UMBaseTest
1224
1224
  ret = machine.read(rfd, buf, 8192)
1225
1225
  assert_equal msg.bytesize, ret
1226
1226
  assert_equal msg, buf
1227
+ ensure
1228
+ Process.wait(pid) rescue Errno::ECHILD
1229
+ end
1230
+
1231
+ def test_waitpid_any
1232
+ skip if UM.kernel_version < 607
1233
+
1234
+ msg = 'hello from child'
1235
+
1236
+ rfd, wfd = UM.pipe
1237
+ pid = fork do
1238
+ m = UM.new
1239
+ m.write(wfd, msg)
1240
+ m.close(wfd)
1241
+ exit 42
1242
+ end
1243
+
1244
+ ret = machine.waitpid(0, UM::WEXITED)
1245
+ assert_kind_of Array, ret
1246
+ assert_equal [pid, 42], ret
1247
+
1248
+ buf = +''
1249
+ ret = machine.read(rfd, buf, 8192)
1250
+ assert_equal msg.bytesize, ret
1251
+ assert_equal msg, buf
1252
+
1253
+ ensure
1254
+ Process.wait(pid) rescue Errno::ECHILD
1227
1255
  end
1228
1256
 
1229
1257
  def test_waitpid_bad_pid
@@ -1275,3 +1303,38 @@ class StatxTest < UMBaseTest
1275
1303
  assert_raises(Errno::ENOENT) { machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL) }
1276
1304
  end
1277
1305
  end
1306
+
1307
+ class ForkTest < UMBaseTest
1308
+ def test_fork
1309
+ parent_rfd, child_wfd = UM.pipe
1310
+ child_rfd, parent_wfd = UM.pipe
1311
+
1312
+ child_pid = fork do
1313
+ # we cannot use the same machine after fork
1314
+ m = UM.new
1315
+ buf = +''
1316
+ m.read(child_rfd, buf, 8192)
1317
+ m.write(child_wfd, buf, buf.bytesize)
1318
+ m.close(child_wfd)
1319
+ rescue Exception => e
1320
+ puts 'c' * 40
1321
+ p e
1322
+ puts e.backtrace.join("\n")
1323
+ end
1324
+
1325
+ ret = machine.write(parent_wfd, 'foo')
1326
+ assert_equal 3, ret
1327
+
1328
+ ret = machine.close(parent_wfd)
1329
+ assert_equal parent_wfd, ret
1330
+
1331
+ buf = +''
1332
+ ret = machine.read(parent_rfd, buf, 8192)
1333
+
1334
+ assert_equal 3, ret
1335
+ assert_equal 'foo', buf
1336
+ ensure
1337
+ Process.wait(child_pid) rescue Errno::ECHILD
1338
+ end
1339
+
1340
+ end
data/uringmachine.gemspec CHANGED
@@ -23,4 +23,5 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'rake-compiler', '1.2.9'
24
24
  s.add_development_dependency 'minitest', '5.25.4'
25
25
  s.add_development_dependency 'benchmark-ips', '2.14.0'
26
+ s.add_development_dependency 'http_parser.rb', '0.8.0'
26
27
  end
@@ -1,18 +1,44 @@
1
- name: Build test
1
+ name: CI
2
2
 
3
3
  on:
4
4
  # Trigger the workflow on push or pull requests.
5
5
  push:
6
6
  pull_request:
7
7
 
8
+
8
9
  jobs:
9
- build:
10
+ get_commit_list:
10
11
  runs-on: ubuntu-24.04
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Get commit list
18
+ id: get_commit_list
19
+ run: |
20
+ git config core.abbrev 12;
21
+ ( \
22
+ ( \
23
+ git log --pretty="%h" --reverse ${{github.event.commits[0].id}}^...${{github.sha}} || \
24
+ (printf "%s" ${{github.sha}} | head -c 12) \
25
+ ) | awk '{ print "id" NR "=" $1 }' \
26
+ ) > $GITHUB_OUTPUT;
27
+ echo "List of tested commits:" > $GITHUB_STEP_SUMMARY;
28
+ cat $GITHUB_OUTPUT >> $GITHUB_STEP_SUMMARY;
29
+
30
+ outputs:
31
+ commit_list: ${{ toJson(steps.*.outputs.*) }}
11
32
 
33
+
34
+ build:
35
+ needs: get_commit_list
36
+ runs-on: ubuntu-24.04
12
37
  strategy:
13
38
  fail-fast: false
14
39
  matrix:
15
- include:
40
+ commit: ${{ fromJson(needs.get_commit_list.outputs.commit_list) }}
41
+ build_args:
16
42
  # x86-64 gcc
17
43
  - arch: x86_64
18
44
  cc_pkg: gcc-x86-64-linux-gnu
@@ -120,46 +146,85 @@ jobs:
120
146
  sanitize: 0
121
147
 
122
148
  env:
123
- FLAGS: -g -O3 -Wall -Wextra -Werror -Wno-sign-compare ${{matrix.extra_flags}}
124
- SANITIZE: ${{matrix.sanitize}}
149
+ FLAGS: -g -O3 -Wall -Wextra -Werror -Wno-sign-compare ${{matrix.build_args.extra_flags}}
150
+ SANITIZE: ${{matrix.build_args.sanitize}}
125
151
 
126
152
  # Flags for building sources in src/ dir only.
127
- LIBURING_CFLAGS: ${{matrix.liburing_extra_flags}}
153
+ LIBURING_CFLAGS: ${{matrix.build_args.liburing_extra_flags}}
128
154
 
129
155
  steps:
130
- - name: Checkout source
131
- uses: actions/checkout@v4
132
-
133
- - name: Install Compilers
134
- run: |
135
- if [[ "${{matrix.cc_pkg}}" == "clang" ]]; then \
136
- wget https://apt.llvm.org/llvm.sh -O /tmp/llvm.sh; \
137
- sudo apt-get purge --auto-remove llvm python3-lldb-14 llvm-14 -y; \
138
- sudo bash /tmp/llvm.sh 17; \
139
- sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-17 400; \
140
- sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-17 400; \
141
- else \
142
- sudo apt-get update -y; \
143
- sudo apt-get install -y ${{matrix.cc_pkg}} ${{matrix.cxx_pkg}}; \
144
- fi;
145
-
146
- - name: Display compiler versions
147
- run: |
148
- ${{matrix.cc}} --version;
149
- ${{matrix.cxx}} --version;
150
-
151
- - name: Build
152
- if: ${{matrix.sanitizer == '0'}}
153
- run: |
154
- ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}};
155
- make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";
156
-
157
- - name: Build
158
- if: ${{matrix.sanitizer == '1'}}
159
- run: |
160
- ./configure --cc=${{matrix.cc}} --cxx=${{matrix.cxx}} --enable-sanitizer;
161
- make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";
162
-
163
- - name: Test install command
164
- run: |
165
- sudo make install;
156
+ - name: Checkout source
157
+ uses: actions/checkout@v4
158
+ with:
159
+ fetch-depth: 0
160
+
161
+ - name: Checkout commit
162
+ run: |
163
+ git checkout ${{ matrix.commit }};
164
+
165
+ - name: Install Compilers
166
+ run: |
167
+ sudo apt-get update -y;
168
+ sudo apt-get install -y ${{matrix.build_args.cc_pkg}} ${{matrix.build_args.cxx_pkg}};
169
+
170
+ - name: Display compiler versions
171
+ run: |
172
+ ${{matrix.build_args.cc}} --version;
173
+ ${{matrix.build_args.cxx}} --version;
174
+
175
+ - name: Build
176
+ if: ${{matrix.build_args.sanitize == '0'}}
177
+ run: |
178
+ ./configure --cc=${{matrix.build_args.cc}} --cxx=${{matrix.build_args.cxx}};
179
+ make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";
180
+
181
+ - name: Build
182
+ if: ${{matrix.build_args.sanitize == '1'}}
183
+ run: |
184
+ ./configure --cc=${{matrix.build_args.cc}} --cxx=${{matrix.build_args.cxx}} --enable-sanitizer;
185
+ make -j$(nproc) V=1 CPPFLAGS="-Werror" CFLAGS="$FLAGS" CXXFLAGS="$FLAGS";
186
+
187
+ - name: Test install command
188
+ run: |
189
+ sudo make install;
190
+
191
+
192
+ codespell:
193
+ needs: get_commit_list
194
+ runs-on: ubuntu-24.04
195
+ strategy:
196
+ matrix:
197
+ commit: ${{ fromJson(needs.get_commit_list.outputs.commit_list) }}
198
+
199
+ steps:
200
+ - name: Checkout source
201
+ uses: actions/checkout@v4
202
+
203
+ - name: Install codespell
204
+ run: |
205
+ sudo apt-get update -y
206
+ sudo apt-get install -y codespell
207
+
208
+ - name: Display codespell version
209
+ run: codespell --version
210
+
211
+ - name: Execute codespell
212
+ run: codespell --ignore-words=.github/actions/codespell/stopwords .
213
+
214
+
215
+ shellcheck:
216
+ needs: get_commit_list
217
+ runs-on: ubuntu-24.04
218
+ strategy:
219
+ matrix:
220
+ commit: ${{ fromJson(needs.get_commit_list.outputs.commit_list) }}
221
+
222
+ steps:
223
+ - name: Checkout source
224
+ uses: actions/checkout@v4
225
+
226
+ - name: Display shellcheck version
227
+ run: shellcheck --version
228
+
229
+ - name: Shellcheck execution
230
+ run: shellcheck test/runtest*.sh
@@ -28,6 +28,7 @@
28
28
  /examples/rsrc-update-bench
29
29
  /examples/kdigest
30
30
  /examples/reg-wait
31
+ /examples/zcrx
31
32
 
32
33
  /test/*.t
33
34
  /test/*.dmesg
@@ -1,4 +1,14 @@
1
+ liburing-2.9 release
2
+
3
+ - Add support for ring resizing
4
+ - Add support for registered waits
5
+ - Test additions and improvements
6
+ - Fix bug with certain ring setups with SQE128 set not fully closing
7
+ the ring after io_uring_queue_exit(3) had been called.
8
+ - Various man page fixes and updates
9
+
1
10
  liburing-2.8 release
11
+
2
12
  - Add support for incrementally/partially consumed provided buffers,
3
13
  usable with the provided buffer ring support.
4
14
  - Add support for foo_and_wait_min_timeout(), where it's possible to
@@ -63,6 +63,11 @@ Building liburing
63
63
  #
64
64
  make -j$(nproc);
65
65
 
66
+ #
67
+ # Build liburing.pc
68
+ #
69
+ make liburing.pc
70
+
66
71
  #
67
72
  # Install liburing (headers, shared/static libs, and manpage).
68
73
  #
@@ -114,7 +114,7 @@ fatal() {
114
114
 
115
115
  # Print result for each configuration test
116
116
  print_config() {
117
- printf "%-30s%s\n" "$1" "$2"
117
+ printf "%-35s%s\n" "$1" "$2"
118
118
  }
119
119
 
120
120
  # Default CFLAGS
@@ -32,6 +32,7 @@ example_srcs := \
32
32
  send-zerocopy.c \
33
33
  rsrc-update-bench.c \
34
34
  proxy.c \
35
+ zcrx.c \
35
36
  kdigest.c
36
37
 
37
38
  all_targets :=
@@ -9,6 +9,7 @@
9
9
  #include <sys/socket.h>
10
10
  #include <sys/time.h>
11
11
  #include <unistd.h>
12
+ #include <stdarg.h>
12
13
 
13
14
  #include "helpers.h"
14
15
 
@@ -60,3 +61,27 @@ int setup_listening_socket(int port, int ipv6)
60
61
 
61
62
  return fd;
62
63
  }
64
+
65
+ void *aligned_alloc(size_t alignment, size_t size)
66
+ {
67
+ void *ret;
68
+
69
+ if (posix_memalign(&ret, alignment, size))
70
+ return NULL;
71
+
72
+ return ret;
73
+ }
74
+
75
+ void t_error(int status, int errnum, const char *format, ...)
76
+ {
77
+ va_list args;
78
+ va_start(args, format);
79
+
80
+ vfprintf(stderr, format, args);
81
+ if (errnum)
82
+ fprintf(stderr, ": %s", strerror(errnum));
83
+
84
+ fprintf(stderr, "\n");
85
+ va_end(args);
86
+ exit(status);
87
+ }
@@ -2,6 +2,19 @@
2
2
  #ifndef LIBURING_EX_HELPERS_H
3
3
  #define LIBURING_EX_HELPERS_H
4
4
 
5
+ #include <stddef.h>
6
+
7
+ #define T_ALIGN_UP(v, align) (((v) + (align) - 1) & ~((align) - 1))
8
+
5
9
  int setup_listening_socket(int port, int ipv6);
6
10
 
11
+ /*
12
+ * Some Android versions lack aligned_alloc in stdlib.h.
13
+ * To avoid making large changes in tests, define a helper
14
+ * function that wraps posix_memalign as our own aligned_alloc.
15
+ */
16
+ void *aligned_alloc(size_t alignment, size_t size);
17
+
18
+ void t_error(int status, int errnum, const char *format, ...);
19
+
7
20
  #endif
@@ -108,5 +108,8 @@ int main(int argc, char *argv[])
108
108
  (unsigned long) fsize);
109
109
  close(fd);
110
110
  io_uring_queue_exit(&ring);
111
+ for (i = 0; i < QD; i++)
112
+ free(iovecs[i].iov_base);
113
+ free(iovecs);
111
114
  return 0;
112
115
  }
@@ -1354,7 +1354,7 @@ start_close:
1354
1354
  if (recv_done_res(cqe->res))
1355
1355
  goto start_close;
1356
1356
  if (is_sink || !ocd->pending_send)
1357
- __submit_receive(ring, c, &c->cd[0], c->in_fd);
1357
+ __submit_receive(ring, c, cd, cqe_to_fd(cqe));
1358
1358
  }
1359
1359
 
1360
1360
  /*
@@ -13,6 +13,8 @@
13
13
  #include <sys/time.h>
14
14
  #include <liburing.h>
15
15
 
16
+ #include "helpers.h"
17
+
16
18
  static unsigned long long mtime_since(const struct timeval *s,
17
19
  const struct timeval *e)
18
20
  {
@@ -38,6 +40,20 @@ static unsigned long long mtime_since_now(struct timeval *tv)
38
40
  return mtime_since(tv, &end);
39
41
  }
40
42
 
43
+ static int register_memory(struct io_uring *ring, void *ptr, size_t size)
44
+ {
45
+ struct io_uring_region_desc rd = {};
46
+ struct io_uring_mem_region_reg mr = {};
47
+
48
+ rd.user_addr = (__u64)(unsigned long)ptr;
49
+ rd.size = size;
50
+ rd.flags = IORING_MEM_REGION_TYPE_USER;
51
+ mr.region_uptr = (__u64)(unsigned long)&rd;
52
+ mr.flags = IORING_MEM_REGION_REG_WAIT_ARG;
53
+
54
+ return io_uring_register_region(ring, &mr);
55
+ }
56
+
41
57
  int main(int argc, char *argv[])
42
58
  {
43
59
  struct io_uring_reg_wait *reg;
@@ -48,30 +64,43 @@ int main(int argc, char *argv[])
48
64
  unsigned long msec;
49
65
  struct timeval tv;
50
66
  int ret, fds[2];
67
+ int page_size;
51
68
 
52
69
  if (argc > 1) {
53
70
  fprintf(stdout, "%s: takes no arguments\n", argv[0]);
54
71
  return 0;
55
72
  }
56
73
 
74
+ page_size = sysconf(_SC_PAGESIZE);
75
+ if (page_size < 0) {
76
+ fprintf(stderr, "sysconf(_SC_PAGESIZE) failed\n");
77
+ return 1;
78
+ }
79
+
57
80
  if (pipe(fds) < 0) {
58
81
  perror("pipe");
59
82
  return 1;
60
83
  }
61
84
 
62
- ret = io_uring_queue_init(8, &ring, 0);
85
+ ret = io_uring_queue_init(8, &ring, IORING_SETUP_R_DISABLED);
63
86
  if (ret) {
64
87
  fprintf(stderr, "Queue init: %d\n", ret);
65
88
  return 1;
66
89
  }
67
90
 
68
91
  /*
69
- * Setup wait region. We'll use 32 here, but 64 is probably a more
70
- * logical value, as it'll pin a page regardless of size. 64 is the
71
- * max value on a 4k page size architecture.
92
+ * Setup a region we'll use to pass wait arguments. It should be
93
+ * page aligned, we're using only first two wait entries here and
94
+ * the rest of the memory can be reused for other purposes.
72
95
  */
73
- reg = io_uring_setup_reg_wait(&ring, 32, &ret);
96
+ reg = aligned_alloc(page_size, page_size);
74
97
  if (!reg) {
98
+ fprintf(stderr, "allocation failed\n");
99
+ return 1;
100
+ }
101
+
102
+ ret = register_memory(&ring, reg, page_size);
103
+ if (ret) {
75
104
  if (ret == -EINVAL) {
76
105
  fprintf(stderr, "Kernel doesn't support registered waits\n");
77
106
  return 1;
@@ -80,6 +109,12 @@ int main(int argc, char *argv[])
80
109
  return 1;
81
110
  }
82
111
 
112
+ ret = io_uring_enable_rings(&ring);
113
+ if (ret) {
114
+ fprintf(stderr, "io_uring_enable_rings failure %i\n", ret);
115
+ return 1;
116
+ }
117
+
83
118
  /*
84
119
  * Setup two distinct wait regions. Index 0 will be a 1 second wait,
85
120
  * and region 2 is a short wait using min_wait_usec as well. Neither
@@ -154,6 +189,6 @@ int main(int argc, char *argv[])
154
189
  * Cleanup after ourselves
155
190
  */
156
191
  io_uring_queue_exit(&ring);
157
- io_uring_free_reg_wait(reg, 32);
192
+ free(reg);
158
193
  return 0;
159
194
  }