uringmachine 0.8.2 → 0.11

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 (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/TODO.md +0 -1
  4. data/examples/bm_side_running.rb +83 -0
  5. data/examples/bm_sqlite.rb +1 -1
  6. data/ext/um/um.c +66 -4
  7. data/ext/um/um.h +36 -0
  8. data/ext/um/um_class.c +6 -0
  9. data/ext/um/um_const.c +36 -0
  10. data/ext/um/um_ext.c +2 -0
  11. data/ext/um/um_stream.c +344 -0
  12. data/ext/um/um_stream_class.c +140 -0
  13. data/ext/um/um_utils.c +4 -0
  14. data/lib/uringmachine/actor.rb +1 -1
  15. data/lib/uringmachine/version.rb +1 -1
  16. data/lib/uringmachine.rb +35 -17
  17. data/test/test_fiber.rb +23 -3
  18. data/test/test_stream.rb +133 -0
  19. data/test/test_um.rb +109 -2
  20. data/uringmachine.gemspec +0 -2
  21. data/vendor/liburing/.github/workflows/{build.yml → ci.yml} +107 -42
  22. data/vendor/liburing/.gitignore +1 -0
  23. data/vendor/liburing/CHANGELOG +10 -0
  24. data/vendor/liburing/README +5 -0
  25. data/vendor/liburing/configure +1 -1
  26. data/vendor/liburing/examples/Makefile +1 -0
  27. data/vendor/liburing/examples/helpers.c +25 -0
  28. data/vendor/liburing/examples/helpers.h +13 -0
  29. data/vendor/liburing/examples/io_uring-test.c +3 -0
  30. data/vendor/liburing/examples/proxy.c +1 -1
  31. data/vendor/liburing/examples/reg-wait.c +41 -6
  32. data/vendor/liburing/examples/send-zerocopy.c +79 -32
  33. data/vendor/liburing/examples/zcrx.c +436 -0
  34. data/vendor/liburing/liburing.spec +1 -1
  35. data/vendor/liburing/src/Makefile +0 -1
  36. data/vendor/liburing/src/arch/generic/syscall.h +2 -2
  37. data/vendor/liburing/src/arch/syscall-defs.h +2 -2
  38. data/vendor/liburing/src/include/liburing/io_uring.h +101 -17
  39. data/vendor/liburing/src/include/liburing.h +179 -59
  40. data/vendor/liburing/src/int_flags.h +4 -1
  41. data/vendor/liburing/src/liburing-ffi.map +14 -2
  42. data/vendor/liburing/src/liburing.map +9 -2
  43. data/vendor/liburing/src/queue.c +35 -30
  44. data/vendor/liburing/src/register.c +46 -15
  45. data/vendor/liburing/src/sanitize.c +6 -9
  46. data/vendor/liburing/src/setup.c +37 -71
  47. data/vendor/liburing/src/syscall.c +2 -2
  48. data/vendor/liburing/test/232c93d07b74.c +1 -0
  49. data/vendor/liburing/test/Makefile +9 -0
  50. data/vendor/liburing/test/accept-test.c +1 -0
  51. data/vendor/liburing/test/cmd-discard.c +16 -8
  52. data/vendor/liburing/test/connect.c +11 -7
  53. data/vendor/liburing/test/epwait.c +420 -0
  54. data/vendor/liburing/test/eventfd-ring.c +30 -5
  55. data/vendor/liburing/test/fallocate.c +1 -1
  56. data/vendor/liburing/test/fixed-hugepage.c +10 -7
  57. data/vendor/liburing/test/fixed-seg.c +187 -0
  58. data/vendor/liburing/test/helpers.c +121 -0
  59. data/vendor/liburing/test/helpers.h +13 -0
  60. data/vendor/liburing/test/init-mem.c +2 -0
  61. data/vendor/liburing/test/io_uring_passthrough.c +78 -62
  62. data/vendor/liburing/test/iopoll-overflow.c +5 -4
  63. data/vendor/liburing/test/iopoll.c +20 -10
  64. data/vendor/liburing/test/iowait.c +141 -0
  65. data/vendor/liburing/test/nvme.h +2 -0
  66. data/vendor/liburing/test/pipe-bug.c +11 -5
  67. data/vendor/liburing/test/pipe-eof.c +11 -1
  68. data/vendor/liburing/test/read-inc-file.c +150 -0
  69. data/vendor/liburing/test/read-write.c +21 -14
  70. data/vendor/liburing/test/recv-bundle-short-ooo.c +435 -0
  71. data/vendor/liburing/test/recv-multishot.c +2 -2
  72. data/vendor/liburing/test/reg-wait.c +449 -120
  73. data/vendor/liburing/test/regbuf-clone.c +53 -0
  74. data/vendor/liburing/test/resize-rings.c +25 -2
  75. data/vendor/liburing/test/rsrc_tags.c +67 -14
  76. data/vendor/liburing/test/send-zerocopy.c +52 -130
  77. data/vendor/liburing/test/sendmsg_iov_clean.c +216 -0
  78. data/vendor/liburing/test/socket-nb.c +158 -0
  79. data/vendor/liburing/test/sqwait.c +9 -11
  80. data/vendor/liburing/test/timeout.c +198 -0
  81. data/vendor/liburing/test/vec-regbuf.c +609 -0
  82. data/vendor/liburing/test/wait-timeout.c +1 -1
  83. data/vendor/liburing/test/wq-aff.c +5 -1
  84. data/vendor/liburing/test/zcrx.c +928 -0
  85. metadata +16 -32
  86. data/vendor/liburing/.github/workflows/codespell.yml +0 -25
  87. data/vendor/liburing/.github/workflows/shellcheck.yml +0 -20
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class StreamBaseTest < UMBaseTest
6
+ def setup
7
+ super
8
+ @rfd, @wfd = UM.pipe
9
+ @stream = UM::Stream.new(@machine, @rfd)
10
+ end
11
+ end
12
+
13
+ class StreamTest < StreamBaseTest
14
+ def test_get_line
15
+ machine.write(@wfd, "foo\nbar\r\nbaz")
16
+ machine.close(@wfd)
17
+
18
+ assert_equal 'foo', @stream.get_line
19
+ assert_equal 'bar', @stream.get_line
20
+ assert_nil @stream.get_line
21
+ end
22
+
23
+ def test_get_string
24
+ machine.write(@wfd, "foobarbazblahzzz")
25
+ machine.close(@wfd)
26
+
27
+ assert_equal 'foobar', @stream.get_string(6)
28
+ assert_equal 'baz', @stream.get_string(3)
29
+ assert_equal 'blah', @stream.get_string(4)
30
+ assert_nil @stream.get_string(4)
31
+ end
32
+ end
33
+
34
+ class StreamRespTest < StreamBaseTest
35
+ def test_trdp_get_line
36
+ machine.write(@wfd, "foo\r\nbarbar\r\nbaz\n")
37
+ machine.close(@wfd)
38
+
39
+ assert_equal 'foo', @stream.resp_get_line
40
+ assert_equal 'barbar', @stream.resp_get_line
41
+ assert_nil @stream.resp_get_line
42
+ end
43
+
44
+ def test_resp_get_string
45
+ machine.write(@wfd, "foo\r\nbarbar\r\nbaz\n")
46
+ machine.close(@wfd)
47
+
48
+ assert_equal 'foo', @stream.resp_get_string(3)
49
+ assert_equal 'barbar', @stream.resp_get_string(6)
50
+ assert_nil @stream.resp_get_string(3)
51
+ end
52
+
53
+ def test_resp_decode
54
+ machine.write(@wfd, "+foo bar\r\n")
55
+ assert_equal "foo bar", @stream.resp_decode
56
+
57
+ machine.write(@wfd, "+baz\r\n")
58
+ assert_equal "baz", @stream.resp_decode
59
+
60
+ machine.write(@wfd, "-foobar\r\n")
61
+ o = @stream.resp_decode
62
+ assert_kind_of RuntimeError, o
63
+ assert_equal "foobar", o.message
64
+
65
+ machine.write(@wfd, "!3\r\nbaz\r\n")
66
+ o = @stream.resp_decode
67
+ assert_kind_of RuntimeError, o
68
+ assert_equal "baz", o.message
69
+
70
+ machine.write(@wfd, ":123\r\n")
71
+ assert_equal 123, @stream.resp_decode
72
+
73
+ machine.write(@wfd, ":-123\r\n")
74
+ assert_equal(-123, @stream.resp_decode)
75
+
76
+ machine.write(@wfd, ",123.321\r\n")
77
+ assert_equal 123.321, @stream.resp_decode
78
+
79
+ machine.write(@wfd, "_\r\n")
80
+ assert_nil @stream.resp_decode
81
+
82
+ machine.write(@wfd, "#t\r\n")
83
+ assert_equal true, @stream.resp_decode
84
+
85
+ machine.write(@wfd, "#f\r\n")
86
+ assert_equal false, @stream.resp_decode
87
+
88
+ machine.write(@wfd, "$6\r\nfoobar\r\n")
89
+ assert_equal "foobar", @stream.resp_decode
90
+
91
+ machine.write(@wfd, "$3\r\nbaz\r\n")
92
+ assert_equal "baz", @stream.resp_decode
93
+
94
+ machine.write(@wfd, "=10\r\ntxt:foobar\r\n")
95
+ assert_equal "foobar", @stream.resp_decode
96
+
97
+ machine.write(@wfd, "*3\r\n+foo\r\n:42\r\n$3\r\nbar\r\n")
98
+ assert_equal ['foo', 42, 'bar'], @stream.resp_decode
99
+
100
+ machine.write(@wfd, "~3\r\n+foo\r\n:42\r\n$3\r\nbar\r\n")
101
+ assert_equal ['foo', 42, 'bar'], @stream.resp_decode
102
+
103
+ machine.write(@wfd, ">3\r\n+foo\r\n:42\r\n$3\r\nbar\r\n")
104
+ assert_equal ['foo', 42, 'bar'], @stream.resp_decode
105
+
106
+ machine.write(@wfd, "%2\r\n+a\r\n:42\r\n+b\r\n:43\r\n")
107
+ assert_equal({ 'a' => 42, 'b' => 43 }, @stream.resp_decode)
108
+
109
+ machine.write(@wfd, "|2\r\n+a\r\n:42\r\n+b\r\n:43\r\n")
110
+ assert_equal({ 'a' => 42, 'b' => 43 }, @stream.resp_decode)
111
+
112
+ machine.write(@wfd, "%2\r\n+a\r\n:42\r\n+b\r\n*3\r\n+foo\r\n+bar\r\n+baz\r\n")
113
+ assert_equal({ 'a' => 42, 'b' => ['foo', 'bar', 'baz'] }, @stream.resp_decode)
114
+
115
+ end
116
+
117
+ def test_resp_encode
118
+ s = UM::Stream
119
+ assert_equal "_\r\n", s.resp_encode(+'', nil)
120
+ assert_equal "#t\r\n", s.resp_encode(+'', true)
121
+ assert_equal "#f\r\n", s.resp_encode(+'', false)
122
+ assert_equal ":42\r\n", s.resp_encode(+'', 42)
123
+ assert_equal ",42.1\r\n", s.resp_encode(+'', 42.1)
124
+ assert_equal "$6\r\nfoobar\r\n", s.resp_encode(+'', 'foobar')
125
+ assert_equal "$10\r\nפובאר\r\n", s.resp_encode(+'', 'פובאר')
126
+
127
+ assert_equal "*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n",
128
+ s.resp_encode(+'', ['foo', 'bar'])
129
+
130
+ assert_equal "%2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$3\r\nbaz\r\n:42\r\n",
131
+ s.resp_encode(+'', { 'foo' => 'bar', 'baz' => 42 })
132
+ end
133
+ end
data/test/test_um.rb CHANGED
@@ -29,7 +29,7 @@ end
29
29
 
30
30
  class SnoozeTest < UMBaseTest
31
31
  def test_snooze_while_sleeping_fiber
32
- f = machine.spin do
32
+ machine.spin do
33
33
  machine.sleep(0.1)
34
34
  end
35
35
 
@@ -655,7 +655,6 @@ class AcceptEachTest < UMBaseTest
655
655
  end
656
656
 
657
657
  def test_accept_each_interrupted
658
- conns = []
659
658
  count = 0
660
659
  terminated = nil
661
660
  f = @machine.spin do
@@ -678,6 +677,8 @@ class AcceptEachTest < UMBaseTest
678
677
 
679
678
  assert f.done?
680
679
  assert terminated
680
+ ensure
681
+ s.close
681
682
  end
682
683
  end
683
684
 
@@ -1223,6 +1224,34 @@ class WaitTest < UMBaseTest
1223
1224
  ret = machine.read(rfd, buf, 8192)
1224
1225
  assert_equal msg.bytesize, ret
1225
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
1226
1255
  end
1227
1256
 
1228
1257
  def test_waitpid_bad_pid
@@ -1231,3 +1260,81 @@ class WaitTest < UMBaseTest
1231
1260
  assert_raises(Errno::ECHILD) { machine.waitpid(1, UM::WEXITED) }
1232
1261
  end
1233
1262
  end
1263
+
1264
+ class StatxTest < UMBaseTest
1265
+ def test_statx
1266
+ io = File.open(__FILE__, 'r')
1267
+ ustat = machine.statx(io.fileno, nil, UM::AT_EMPTY_PATH, UM::STATX_ALL)
1268
+ rstat = File.stat(__FILE__)
1269
+
1270
+ assert_equal rstat.dev, ustat[:dev]
1271
+ assert_equal rstat.ino, ustat[:ino]
1272
+ assert_equal rstat.mode, ustat[:mode]
1273
+ assert_equal rstat.nlink, ustat[:nlink]
1274
+ assert_equal rstat.uid, ustat[:uid]
1275
+ assert_equal rstat.gid, ustat[:gid]
1276
+ assert_equal rstat.rdev, ustat[:rdev]
1277
+ assert_equal rstat.size, ustat[:size]
1278
+ assert_equal rstat.blksize, ustat[:blksize]
1279
+ assert_equal rstat.blocks, ustat[:blocks]
1280
+ assert_equal rstat.atime.to_i, ustat[:atime].to_i
1281
+ assert_equal rstat.ctime.to_i, ustat[:ctime].to_i
1282
+ assert_equal rstat.mtime.to_i, ustat[:mtime].to_i
1283
+
1284
+ ustat2 = machine.statx(UM::AT_FDCWD, __FILE__, 0, UM::STATX_ALL)
1285
+ assert_equal rstat.dev, ustat2[:dev]
1286
+ assert_equal rstat.ino, ustat2[:ino]
1287
+ assert_equal rstat.mode, ustat2[:mode]
1288
+ assert_equal rstat.nlink, ustat2[:nlink]
1289
+ assert_equal rstat.uid, ustat2[:uid]
1290
+ assert_equal rstat.gid, ustat2[:gid]
1291
+ assert_equal rstat.rdev, ustat2[:rdev]
1292
+ assert_equal rstat.size, ustat2[:size]
1293
+ assert_equal rstat.blksize, ustat2[:blksize]
1294
+ assert_equal rstat.blocks, ustat2[:blocks]
1295
+ assert_equal rstat.atime.to_i, ustat2[:atime].to_i
1296
+ assert_equal rstat.ctime.to_i, ustat2[:ctime].to_i
1297
+ assert_equal rstat.mtime.to_i, ustat2[:mtime].to_i
1298
+ ensure
1299
+ io.close
1300
+ end
1301
+
1302
+ def test_statx_bad_path
1303
+ assert_raises(Errno::ENOENT) { machine.statx(UM::AT_FDCWD, 'foobar', 0, UM::STATX_ALL) }
1304
+ end
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
@@ -22,7 +22,5 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_development_dependency 'rake-compiler', '1.2.9'
24
24
  s.add_development_dependency 'minitest', '5.25.4'
25
- s.add_development_dependency 'http_parser.rb', '0.8.0'
26
25
  s.add_development_dependency 'benchmark-ips', '2.14.0'
27
- s.add_development_dependency 'localhost', '1.3.1'
28
26
  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
  }