uringmachine 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +2 -1
  3. data/CHANGELOG.md +14 -0
  4. data/README.md +44 -1
  5. data/TODO.md +12 -3
  6. data/examples/bm_snooze.rb +89 -0
  7. data/examples/bm_write.rb +56 -0
  8. data/examples/dns_client.rb +12 -0
  9. data/examples/http_server.rb +42 -43
  10. data/examples/server_client.rb +64 -0
  11. data/examples/snooze.rb +44 -0
  12. data/examples/write_dev_null.rb +16 -0
  13. data/ext/um/extconf.rb +24 -14
  14. data/ext/um/um.c +468 -414
  15. data/ext/um/um.h +129 -39
  16. data/ext/um/um_buffer.c +49 -0
  17. data/ext/um/um_class.c +148 -24
  18. data/ext/um/um_const.c +30 -1
  19. data/ext/um/um_ext.c +4 -0
  20. data/ext/um/um_mutex_class.c +47 -0
  21. data/ext/um/um_op.c +86 -111
  22. data/ext/um/um_queue_class.c +58 -0
  23. data/ext/um/um_sync.c +273 -0
  24. data/ext/um/um_utils.c +1 -1
  25. data/lib/uringmachine/dns_resolver.rb +84 -0
  26. data/lib/uringmachine/version.rb +1 -1
  27. data/lib/uringmachine.rb +19 -3
  28. data/supressions/ruby.supp +71 -0
  29. data/test/test_um.rb +466 -47
  30. data/vendor/liburing/.gitignore +5 -0
  31. data/vendor/liburing/CHANGELOG +1 -0
  32. data/vendor/liburing/configure +32 -0
  33. data/vendor/liburing/examples/Makefile +1 -0
  34. data/vendor/liburing/examples/reg-wait.c +159 -0
  35. data/vendor/liburing/liburing.spec +1 -1
  36. data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
  37. data/vendor/liburing/src/include/liburing.h +28 -2
  38. data/vendor/liburing/src/int_flags.h +10 -3
  39. data/vendor/liburing/src/liburing-ffi.map +13 -2
  40. data/vendor/liburing/src/liburing.map +9 -0
  41. data/vendor/liburing/src/queue.c +25 -16
  42. data/vendor/liburing/src/register.c +73 -4
  43. data/vendor/liburing/src/setup.c +46 -18
  44. data/vendor/liburing/src/setup.h +6 -0
  45. data/vendor/liburing/test/Makefile +7 -0
  46. data/vendor/liburing/test/cmd-discard.c +427 -0
  47. data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
  48. data/vendor/liburing/test/file-exit-unreg.c +48 -0
  49. data/vendor/liburing/test/io_uring_passthrough.c +2 -0
  50. data/vendor/liburing/test/io_uring_register.c +13 -2
  51. data/vendor/liburing/test/napi-test.c +1 -1
  52. data/vendor/liburing/test/no-mmap-inval.c +1 -1
  53. data/vendor/liburing/test/read-mshot-empty.c +2 -0
  54. data/vendor/liburing/test/read-mshot-stdin.c +121 -0
  55. data/vendor/liburing/test/read-mshot.c +6 -0
  56. data/vendor/liburing/test/recvsend_bundle.c +2 -2
  57. data/vendor/liburing/test/reg-fd-only.c +1 -1
  58. data/vendor/liburing/test/reg-wait.c +251 -0
  59. data/vendor/liburing/test/regbuf-clone.c +458 -0
  60. data/vendor/liburing/test/resize-rings.c +643 -0
  61. data/vendor/liburing/test/rsrc_tags.c +1 -1
  62. data/vendor/liburing/test/sqpoll-sleep.c +39 -8
  63. data/vendor/liburing/test/sqwait.c +136 -0
  64. data/vendor/liburing/test/sync-cancel.c +8 -1
  65. data/vendor/liburing/test/timeout.c +13 -8
  66. metadata +22 -4
  67. data/examples/http_server_multishot.rb +0 -57
  68. data/examples/http_server_simpler.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a9efd4af7de9fdb8db6888b9f6347e9dbc63aae9e26fa0f81d43984d265bd90
4
- data.tar.gz: 5289699ce1e3e173d3766e0211fc77b57f3c123e2a6e041e9e751a3bf5ce07b2
3
+ metadata.gz: 2067cd0f88d6dbc341410ca6911916f510132ee23ce3f6d5fb5978259eeaef11
4
+ data.tar.gz: f816a9478f714a3a9770740bc14fc03ae2687f2fe7d0e29cbc0b8632994bad1f
5
5
  SHA512:
6
- metadata.gz: 3cf02bbaae5a9e19b9ea994d1c2bf4b327a96121b083ca6756eca70629738f6c24aca10096bb49a0400678542232062969889ed3f0773591f5dc71f718707fef
7
- data.tar.gz: 67b368097ddecd6c9ca9ce360cc918d8e7de91ec83a00d617765c2026fbe08f16f5009b78323e9f314cd1df63a1baaa39e8887b4a90fff0cb8010d810276df7d
6
+ metadata.gz: 6e0a9ed6e6f131bf6d67a56622786893532a525f4427e134670499997c0461a4df6de3ca1cb9e70851769c1135575986468a83edfd9b5d75c7d592e41bb0ca8c
7
+ data.tar.gz: 2c73ed9a3268ea96b3a167064251d16279c531ee50e5f9c6de9aa2c56f6a70973ef04ce5d6c44f46e39309f7bf8cb3f3ff5e61bf1512ca07cc5f35b91f7303dc
@@ -32,4 +32,5 @@ jobs:
32
32
  - name: Compile C-extension
33
33
  run: bundle exec rake compile
34
34
  - name: Run tests
35
- run: bundle exec rake test
35
+ # run: bundle exec ruby test/test_um.rb --name test_read_each_raising_2
36
+ run: bundle exec rake test
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # 2024-11-14 Version 0.5
2
+
3
+ - Add `#waitpid`
4
+ - Add `UM.pipe`, `UM.kernel_version`
5
+ - Add `#open`
6
+ - Fix `#spin`
7
+ - Fix handling of signal interruption.
8
+ - Reimplement and simplify um_op
9
+ - Add `UM::Queue`, `#push`, `#pop`, `#shift`, `#unshift`
10
+ - Add `UM::Mutex`, `#synchronize`
11
+ - Add `#recv_each`
12
+ - Add `#getsockopt`, `#setsockopt`
13
+ - Simplify and improve op management
14
+
1
15
  # 2024-10-06 Version 0.4
2
16
 
3
17
  - Add socket constants
data/README.md CHANGED
@@ -32,6 +32,8 @@ UringMachine is based on my experience marrying Ruby and io_uring:
32
32
  - [IOU](https://github.com/digital-fabric/iou) - a low-level asynchronous API
33
33
  for using io_uring from Ruby.
34
34
 
35
+ ### Learnings
36
+
35
37
  Some important learnings from those two projects, in no particular order:
36
38
 
37
39
  - Monkey-patching is not a good solution, long term. You need to deal with
@@ -73,7 +75,25 @@ based on the following principles:
73
75
  - Do not insist on structured concurrency, just provide the APIs necessary to
74
76
  create actors and to supervise the execution of fibers.
75
77
 
76
- ## Example
78
+ ### Cancellation
79
+
80
+ When working with io_uring, managing the life cycle of asynchronous operations
81
+ is quite tricky, especially with regards to cancellation. This is due to the
82
+ fact each operation lives on both sides of the userspace-kernel divide. This
83
+ means that when cancelling an operation, we cannot free, or dispose of any
84
+ resources associated with the operation, until we know for sure that the kernel
85
+ side is also done with the operation.
86
+
87
+ As stated above, working with fibers allows us to keep operation metadata and
88
+ associated data (such as buffers etc) on the stack, which can greatly simplify
89
+ the managing of the operation's lifetime, as well as significantly reduce heap
90
+ allocations.
91
+
92
+ When a cancellation does occur, UringMachine issues a cancellation (using
93
+ `io_uring_prep_cancel64`), and then waits for the corresponding CQE (with a
94
+ `-ECANCELED` result).
95
+
96
+ ## Short Example
77
97
 
78
98
  ```ruby
79
99
  require 'uringmachine'
@@ -94,3 +114,26 @@ loop do
94
114
  end
95
115
  end
96
116
  ```
117
+
118
+ ## Concurrent Execution
119
+
120
+ Concurrent execution is done by calling `#spin`, which creates a fiber:
121
+
122
+ ```ruby
123
+ machine = UringMachine.new
124
+
125
+ rfd, wfd = machine.pipe
126
+
127
+ f1 = machine.spin do
128
+ machine.write(wfd, 'hello')
129
+ machine.write(wfd, 'world')
130
+ machine.close(wfd)
131
+ end
132
+
133
+ bgid = machine.setup_buffer_ring(4096, 1024)
134
+ f2 = machine.spin do
135
+ machine.read_each(rfd, bgid) do |str|
136
+ puts str
137
+ end
138
+ end
139
+ ```
data/TODO.md CHANGED
@@ -1,5 +1,14 @@
1
- - splice
1
+ - splice / - tee
2
2
  - sendto
3
3
  - recvfrom
4
-
5
- - queues
4
+ - poll_add / poll_remove / poll_multishot / poll_update
5
+ - fsync
6
+ - mkdir / mkdirat
7
+ - statx
8
+ - link / linkat / unlink / unlinkat / symlink
9
+ - rename / renameat
10
+ - fadvise
11
+ - madvise
12
+ - getxattr / setxattr
13
+ - shutdown
14
+ - send_bundle / recv_bundle (kernel >= 6.10)
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'uringmachine', path: '..'
8
+ gem 'benchmark-ips'
9
+ end
10
+
11
+ require 'benchmark/ips'
12
+ require 'uringmachine'
13
+
14
+ ITERATIONS = 1000
15
+
16
+ $machine = UringMachine.new
17
+
18
+ def run_snooze
19
+ count = 0
20
+ main = Fiber.current
21
+
22
+ f1 = Fiber.new do
23
+ loop do
24
+ count += 1
25
+ if count == ITERATIONS
26
+ $machine.schedule(main, nil)
27
+ break
28
+ else
29
+ $machine.snooze
30
+ end
31
+ end
32
+ end
33
+
34
+ f2 = Fiber.new do
35
+ loop do
36
+ count += 1
37
+ if count == ITERATIONS
38
+ $machine.schedule(main, nil)
39
+ break
40
+ else
41
+ $machine.snooze
42
+ end
43
+ end
44
+ end
45
+
46
+ $machine.schedule(f1, nil)
47
+ $machine.schedule(f2, nil)
48
+ $machine.yield
49
+ end
50
+
51
+ def run_raw_transfer
52
+ count = 0
53
+ main = Fiber.current
54
+ f2 = nil
55
+ f1 = Fiber.new do
56
+ loop do
57
+ count += 1
58
+ if count == ITERATIONS
59
+ main.transfer(nil)
60
+ break
61
+ else
62
+ f2.transfer(nil)
63
+ end
64
+ end
65
+ end
66
+
67
+ f2 = Fiber.new do
68
+ loop do
69
+ count += 1
70
+ if count == ITERATIONS
71
+ main.transfer(nil)
72
+ break
73
+ else
74
+ f1.transfer(nil)
75
+ end
76
+ end
77
+ end
78
+
79
+ f1.transfer(nil)
80
+ end
81
+
82
+ bm = Benchmark.ips do |x|
83
+ x.config(:time => 5, :warmup => 2)
84
+
85
+ x.report("snooze") { run_snooze }
86
+ x.report("raw transfer") { run_raw_transfer }
87
+
88
+ x.compare!
89
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'uringmachine', path: '..'
8
+ gem 'benchmark'
9
+ end
10
+
11
+ require 'benchmark'
12
+ require 'uringmachine'
13
+
14
+ ITERATIONS = 100000
15
+ BUF = ('*' * 8192).freeze
16
+ FN = '/tmp/bm_write'
17
+
18
+ def run_io_write(num_threads)
19
+ FileUtils.rm(FN) rescue nil
20
+ fio = File.open(FN, 'w')
21
+
22
+ threads = num_threads.times.map do |i|
23
+ Thread.new do
24
+ ITERATIONS.times { fio.write(BUF) }
25
+ end
26
+ end
27
+ threads.each(&:join)
28
+ ensure
29
+ fio.close
30
+ end
31
+
32
+ def run_um_write(num_fibers)
33
+ FileUtils.rm(FN) rescue nil
34
+ fio = File.open(FN, 'w')
35
+ fd = fio.fileno
36
+
37
+ machine = UringMachine.new
38
+ done = UringMachine::Queue.new
39
+ num_fibers.times do
40
+ machine.spin do
41
+ ITERATIONS.times { machine.write(fd, BUF) }
42
+ machine.push(done, true)
43
+ end
44
+ end
45
+ num_fibers.times { machine.pop(done) }
46
+ ensure
47
+ fio.close
48
+ end
49
+
50
+ Benchmark.bm do |x|
51
+ [1, 2, 4, 8].each do |c|
52
+ x.report("IO (#{c} threads)") { run_io_write(c) }
53
+ x.report("UM (#{c} fibers) ") { run_um_write(c) }
54
+ puts
55
+ end
56
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+ require 'resolv'
5
+
6
+ machine = UM.new
7
+
8
+ addrs = machine.resolve('status.realiteq.net')
9
+
10
+ puts '*' * 40
11
+ puts addrs.join("\n")
12
+ puts
@@ -1,56 +1,55 @@
1
- require_relative '../lib/iou'
2
- require 'socket'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
3
4
  require 'http/parser'
4
5
 
5
- def log(msg)
6
- # return
7
- STDERR.puts msg
8
- end
6
+ @machine = UM.new
7
+ @bgid = @machine.setup_buffer_ring(4096, 1024)
9
8
 
10
- socket = TCPServer.open('127.0.0.1', 1234)
11
- log 'Listening on port 1234...'
9
+ def http_handle_connection(fd)
10
+ # puts "Accepting connection on fd #{fd}"
11
+ parser = Http::Parser.new
12
+ done = nil
13
+ parser.on_message_complete = -> do
14
+ http_send_response(fd, "Hello, world!\n")
15
+ done = true
16
+ end
12
17
 
13
- @ring = IOU::Ring.new
14
- @bg_id = @ring.setup_buffer_ring(count: 1024, size: 4096)
18
+ @machine.read_each(fd, @bgid) do
19
+ parser << _1
20
+ break if done
21
+ end
15
22
 
16
- @ring.prep_accept(fd: socket.fileno, multishot: true) do |c|
17
- setup_connection(c[:result]) if c[:result] > 0
23
+ # puts "Connection closed on fd #{fd}"
24
+ rescue => e
25
+ # puts "Error while handling connection on fd #{fd}: #{e.inspect}"
26
+ ensure
27
+ @machine.close(fd) rescue nil
18
28
  end
19
29
 
20
- def setup_connection(fd)
21
- log "Connection accepted fd #{fd}"
22
-
23
- parser = Http::Parser.new
24
- parser.on_message_complete = -> {
25
- http_send_response(fd, "Hello, world!\n") do
26
- @ring.prep_close(fd: fd)
27
- end
28
- }
29
-
30
- http_prep_read(fd, parser)
30
+ def http_send_response(fd, body)
31
+ # msg = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}"
32
+ msg = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}"
33
+ @machine.write(fd, msg)
31
34
  end
32
35
 
33
- def http_prep_read(fd, parser)
34
- buffer = +''
35
- @ring.prep_read(fd: fd, buffer: buffer, len: 4096) do |c|
36
- if c[:result] > 0
37
- http_prep_read(fd, parser)
38
- parser << buffer
39
- elsif c[:result] == 0
40
- log "Connection closed by client on fd #{fd}"
41
- else
42
- log "Got error #{c[:result]} on fd #{fd}, closing connection..."
43
- @ring.prep_close(fd: fd) do |c|
44
- log "Connection closed on fd #{fd}, result #{c[:result]}"
45
- end
46
- end
36
+ server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
37
+ @machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
38
+ @machine.bind(server_fd, '127.0.0.1', 1234)
39
+ @machine.listen(server_fd, UM::SOMAXCONN)
40
+ puts 'Listening on port 1234'
41
+
42
+ @machine.spin do
43
+ @machine.accept_each(server_fd) do |fd|
44
+ @machine.spin(fd) { http_handle_connection _1 }
47
45
  end
48
46
  end
49
47
 
50
- def http_send_response(fd, body)
51
- msg = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: keep-alive\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}"
52
- @ring.prep_write(fd: fd, buffer: msg)
53
- end
48
+ main = Fiber.current
49
+ trap('SIGINT') { @machine.schedule(main, nil) }
50
+ trap('SIGTERM') { @machine.schedule(main, nil) }
54
51
 
55
- trap('SIGINT') { exit! }
56
- @ring.process_completions_loop
52
+ @machine.yield
53
+ puts "Closing server FD"
54
+ @machine.close(server_fd) rescue nil
55
+ puts "done!"
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+
5
+ PORT = 1234
6
+
7
+ @machine = UM.new
8
+ @bgid = @machine.setup_buffer_ring(4096, 1024)
9
+
10
+ @counter = 0
11
+
12
+ def handle_connection(fd)
13
+ buf = +''
14
+ loop do
15
+ res = @machine.recv(fd, buf, 8192, 0)
16
+ break if res == 0
17
+
18
+ @machine.write(fd, buf)
19
+ @counter += 2
20
+ end
21
+ ensure
22
+ @machine.close(fd) rescue nil
23
+ end
24
+
25
+ def run_client
26
+ fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
27
+ @machine.connect(fd, '127.0.0.1', PORT)
28
+ msg = 'foo' * 30
29
+ buf = +''
30
+ loop do
31
+ @machine.send(fd, msg, msg.bytesize, 0)
32
+ res = @machine.recv(fd, buf, 8192, 0)
33
+ @counter += 2
34
+
35
+ break if res == 0
36
+ raise "Got #{res} bytes instead of #{msg.bytesize}" if res != msg.bytesize
37
+ end
38
+ end
39
+
40
+ trap('SIGINT') { exit }
41
+
42
+ server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
43
+ @machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
44
+ @machine.bind(server_fd, '127.0.0.1', PORT)
45
+ @machine.listen(server_fd, UM::SOMAXCONN)
46
+ puts "Listening on port #{PORT}"
47
+
48
+ at_exit { @machine.close(server_fd) rescue nil }
49
+
50
+ 20.times do
51
+ @machine.spin { run_client }
52
+ end
53
+
54
+ @machine.spin do
55
+ @machine.accept_each(server_fd) do |fd|
56
+ @machine.spin(fd) { handle_connection _1 }
57
+ end
58
+ end
59
+
60
+ t0 = Time.now
61
+ @machine.sleep 3
62
+ t1 = Time.now
63
+ elapsed = t1 - t0
64
+ puts "Did #{@counter} ops in #{elapsed} seconds (#{(@counter / elapsed)} ops/s)"
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+
5
+ @machine = UM.new
6
+
7
+ @counter = 0
8
+ @fiber_count = 0
9
+
10
+ def start_fiber
11
+ @fiber_count += 1
12
+ @machine.spin do
13
+ max_count = @counter + rand(1000)
14
+ puts "Start #{Fiber.current} #{max_count - @counter}"
15
+ loop do
16
+ @machine.sleep 0.001
17
+ @counter += 1
18
+ break if @counter >= max_count
19
+ end
20
+ puts "Stop #{Fiber.current}"
21
+ ensure
22
+ @fiber_count -= 1
23
+ end
24
+ end
25
+
26
+ t0 = Time.now
27
+ MAX_FIBERS = 20
28
+ MAX_TIME = 10
29
+ loop do
30
+ @machine.sleep 0.1
31
+ puts "pending: #{@machine.pending_count}"
32
+ break if (Time.now - t0) > MAX_TIME
33
+ start_fiber while @fiber_count < MAX_FIBERS
34
+ end
35
+ t1 = Time.now
36
+ elapsed = t1 - t0
37
+ rate = @counter / elapsed
38
+ puts "Did #{@counter} ops in #{elapsed} seconds (#{rate} ops/s)"
39
+
40
+ puts "Waiting for fibers... (#{@fiber_count})"
41
+ while @fiber_count > 0
42
+ @machine.sleep 0.1
43
+ end
44
+ puts "Done"
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../lib/uringmachine'
4
+
5
+ ITERATIONS = 1000
6
+ DEV_NULL = File.open('/dev/null', 'w')
7
+ FD = DEV_NULL.fileno
8
+ BUF = ('*' * 8192).freeze
9
+
10
+ $machine = UringMachine.new
11
+
12
+ def run_um_write
13
+ $machine.write(FD, BUF)
14
+ end
15
+
16
+ 1000.times { run_um_write }
data/ext/um/extconf.rb CHANGED
@@ -8,8 +8,9 @@ dir_config 'um_ext'
8
8
 
9
9
  KERNEL_INFO_RE = /Linux (\d)\.(\d+)(?:\.)?((?:\d+\.?)*)(?:\-)?([\w\-]+)?/
10
10
  def get_config
11
- config = { linux: !!(RUBY_PLATFORM =~ /linux/) }
12
- raise "UringMachine only works on Linux!" if !config[:linux]
11
+ if RUBY_PLATFORM !~ /linux/
12
+ raise "UringMachine only works on Linux!"
13
+ end
13
14
 
14
15
  kernel_info = `uname -sr`
15
16
  m = kernel_info.match(KERNEL_INFO_RE)
@@ -20,14 +21,18 @@ def get_config
20
21
  combined_version = version.to_i * 100 + major_revision.to_i
21
22
  raise "UringMachine requires kernel version 6.4 or newer!" if combined_version < 604
22
23
 
23
- config[:kernel_version] = combined_version
24
- config[:submit_all_flag] = combined_version >= 518
25
- config[:coop_taskrun_flag] = combined_version >= 519
26
- config[:single_issuer_flag] = combined_version >= 600
27
- config[:prep_bind] = combined_version >= 611
28
- config[:prep_listen] = combined_version >= 611
29
-
30
- config
24
+ {
25
+ kernel_version: combined_version,
26
+ submit_all_flag: combined_version >= 518,
27
+ coop_taskrun_flag: combined_version >= 519,
28
+ single_issuer_flag: combined_version >= 600,
29
+ prep_bind: combined_version >= 611,
30
+ prep_listen: combined_version >= 611,
31
+ prep_cmd_sock: combined_version >= 607,
32
+ prep_futex: combined_version >= 607,
33
+ prep_waitid: combined_version >= 607,
34
+ prep_read_multishot: combined_version >= 607
35
+ }
31
36
  end
32
37
 
33
38
  config = get_config
@@ -51,10 +56,15 @@ if !find_library('uring', nil, File.join(liburing_path, 'src'))
51
56
  raise "Couldn't find liburing.a"
52
57
  end
53
58
 
54
- $defs << '-DHAVE_IORING_SETUP_SUBMIT_ALL' if config[:submit_all_flag]
55
- $defs << '-DHAVE_IORING_SETUP_COOP_TASKRUN' if config[:coop_taskrun_flag]
56
- $defs << '-DHAVE_IO_URING_PREP_BIND' if config[:prep_bind]
57
- $defs << '-DHAVE_IO_URING_PREP_LISTEN' if config[:prep_listen]
59
+ $defs << "-DUM_KERNEL_VERSION=#{config[:kernel_version]}"
60
+ $defs << '-DHAVE_IORING_SETUP_SUBMIT_ALL' if config[:submit_all_flag]
61
+ $defs << '-DHAVE_IORING_SETUP_COOP_TASKRUN' if config[:coop_taskrun_flag]
62
+ $defs << '-DHAVE_IO_URING_PREP_BIND' if config[:prep_bind]
63
+ $defs << '-DHAVE_IO_URING_PREP_LISTEN' if config[:prep_listen]
64
+ $defs << '-DHAVE_IO_URING_PREP_CMD_SOCK' if config[:prep_cmd_sock]
65
+ $defs << '-DHAVE_IO_URING_PREP_FUTEX' if config[:prep_futex]
66
+ $defs << '-DHAVE_IO_URING_PREP_WAITID' if config[:prep_waitid]
67
+ $defs << '-DHAVE_IO_URING_PREP_READ_MULTISHOT' if config[:prep_read_multishot]
58
68
  $CFLAGS << ' -Wno-pointer-arith'
59
69
 
60
70
  CONFIG['optflags'] << ' -fno-strict-aliasing'