uringmachine 0.23.1 → 0.25.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.gitignore +1 -0
- data/.gitmodules +0 -3
- data/CHANGELOG.md +17 -0
- data/Gemfile +12 -1
- data/README.md +266 -112
- data/Rakefile +8 -0
- data/TODO.md +40 -17
- data/benchmark/bm_io_pipe.rb +43 -1
- data/benchmark/bm_io_socketpair.rb +32 -2
- data/benchmark/bm_mutex_io.rb +47 -5
- data/benchmark/chart_bm_io_pipe_x.png +0 -0
- data/benchmark/common.rb +163 -17
- data/benchmark/http_parse.rb +9 -9
- data/benchmark/http_server_accept_queue.rb +104 -0
- data/benchmark/http_server_multi_accept.rb +93 -0
- data/benchmark/http_server_multi_ractor.rb +99 -0
- data/benchmark/http_server_single_thread.rb +80 -0
- data/benchmark/ips_io_pipe.rb +146 -0
- data/benchmark/openssl.rb +77 -0
- data/benchmark/openssl_socketpair.rb +112 -0
- data/benchmark/sqlite.rb +1 -1
- data/docs/design/buffer_pool.md +183 -0
- data/docs/um_api.md +91 -0
- data/examples/fiber_scheduler_file_io.rb +34 -0
- data/examples/fiber_scheduler_file_io_async.rb +33 -0
- data/ext/um/extconf.rb +15 -0
- data/ext/um/um.c +83 -50
- data/ext/um/um.h +18 -3
- data/ext/um/um_async_op_class.c +31 -0
- data/ext/um/um_class.c +759 -30
- data/ext/um/um_const.c +31 -0
- data/ext/um/um_mutex_class.c +12 -0
- data/ext/um/um_queue_class.c +16 -0
- data/ext/um/um_sidecar.c +106 -0
- data/ext/um/um_ssl.c +109 -0
- data/ext/um/um_stream.c +40 -8
- data/ext/um/um_stream_class.c +14 -0
- data/ext/um/um_utils.c +3 -4
- data/grant-2025/interim-report.md +130 -0
- data/grant-2025/journal.md +166 -2
- data/grant-2025/tasks.md +32 -20
- data/lib/uringmachine/dns_resolver.rb +38 -0
- data/lib/uringmachine/fiber_scheduler.rb +42 -32
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +105 -7
- data/test/helper.rb +23 -3
- data/test/test_fiber.rb +16 -0
- data/test/test_fiber_scheduler.rb +221 -72
- data/test/test_ssl.rb +85 -0
- data/test/test_stream.rb +27 -0
- data/test/test_um.rb +250 -26
- data/uringmachine.gemspec +1 -7
- data/vendor/liburing/examples/send-zerocopy.c +43 -31
- data/vendor/liburing/examples/zcrx.c +260 -69
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +12 -0
- data/vendor/liburing/src/include/liburing.h +3 -2
- data/vendor/liburing/src/liburing-ffi.map +4 -0
- data/vendor/liburing/src/liburing.map +4 -0
- data/vendor/liburing/src/queue.c +12 -0
- data/vendor/liburing/src/register.c +1 -0
- data/vendor/liburing/src/setup.c +15 -7
- data/vendor/liburing/test/Makefile +8 -4
- data/vendor/liburing/test/conn-unreach.c +1 -1
- data/vendor/liburing/test/epwait.c +32 -6
- data/vendor/liburing/test/io-wq-exit.c +131 -0
- data/vendor/liburing/test/iowait.c +1 -1
- data/vendor/liburing/test/min-timeout.c +3 -1
- data/vendor/liburing/test/open-close.c +39 -0
- data/vendor/liburing/test/poll-update-trigger.c +85 -0
- data/vendor/liburing/test/recvsend_bundle.c +14 -11
- data/vendor/liburing/test/sendzc-bug.c +146 -0
- data/vendor/liburing/test/sqe-mixed-nop.c +151 -7
- data/vendor/liburing/test/test.h +2 -0
- data/vendor/liburing/test/timestamp-bug.c +135 -0
- data/vendor/liburing/test/timestamp.c +5 -0
- data/vendor/liburing/test/vec-regbuf.c +136 -1
- metadata +50 -284
- data/vendor/libressl/.github/scripts/changelog.sh +0 -74
- data/vendor/libressl/.github/workflows/android.yml +0 -35
- data/vendor/libressl/.github/workflows/cifuzz.yml +0 -33
- data/vendor/libressl/.github/workflows/cmake-config.yml +0 -98
- data/vendor/libressl/.github/workflows/coverity.yml +0 -69
- data/vendor/libressl/.github/workflows/emscripten.yml +0 -71
- data/vendor/libressl/.github/workflows/fedora-rawhide.yml +0 -39
- data/vendor/libressl/.github/workflows/freebsd.yml +0 -71
- data/vendor/libressl/.github/workflows/linux.yml +0 -71
- data/vendor/libressl/.github/workflows/macos.yml +0 -37
- data/vendor/libressl/.github/workflows/release.yml +0 -81
- data/vendor/libressl/.github/workflows/rust-openssl.yml +0 -47
- data/vendor/libressl/.github/workflows/solaris.yml +0 -37
- data/vendor/libressl/.github/workflows/windows.yml +0 -70
- data/vendor/libressl/.gitignore +0 -333
- data/vendor/libressl/CMakeLists.txt +0 -581
- data/vendor/libressl/COPYING +0 -133
- data/vendor/libressl/ChangeLog +0 -3280
- data/vendor/libressl/FindLibreSSL.cmake +0 -232
- data/vendor/libressl/LibreSSLConfig.cmake.in +0 -36
- data/vendor/libressl/Makefile.am +0 -60
- data/vendor/libressl/Makefile.am.common +0 -20
- data/vendor/libressl/OPENBSD_BRANCH +0 -1
- data/vendor/libressl/README.md +0 -238
- data/vendor/libressl/README.mingw.md +0 -43
- data/vendor/libressl/apps/CMakeLists.txt +0 -18
- data/vendor/libressl/apps/Makefile.am +0 -5
- data/vendor/libressl/apps/nc/CMakeLists.txt +0 -67
- data/vendor/libressl/apps/nc/Makefile.am +0 -64
- data/vendor/libressl/apps/nc/compat/accept4.c +0 -17
- data/vendor/libressl/apps/nc/compat/readpassphrase.c +0 -205
- data/vendor/libressl/apps/nc/compat/socket.c +0 -29
- data/vendor/libressl/apps/nc/compat/sys/socket.h +0 -30
- data/vendor/libressl/apps/ocspcheck/CMakeLists.txt +0 -44
- data/vendor/libressl/apps/ocspcheck/Makefile.am +0 -45
- data/vendor/libressl/apps/ocspcheck/compat/.gitignore +0 -0
- data/vendor/libressl/apps/openssl/CMakeLists.txt +0 -97
- data/vendor/libressl/apps/openssl/Makefile.am +0 -108
- data/vendor/libressl/apps/openssl/apps_win.c +0 -138
- data/vendor/libressl/apps/openssl/certhash_win.c +0 -13
- data/vendor/libressl/apps/openssl/compat/clock_gettime_osx.c +0 -26
- data/vendor/libressl/apps/openssl/compat/poll_win.c +0 -329
- data/vendor/libressl/appveyor.yml +0 -53
- data/vendor/libressl/autogen.sh +0 -15
- data/vendor/libressl/check-release.sh +0 -86
- data/vendor/libressl/cmake_export_symbol.cmake +0 -71
- data/vendor/libressl/cmake_uninstall.cmake.in +0 -36
- data/vendor/libressl/config +0 -17
- data/vendor/libressl/configure.ac +0 -165
- data/vendor/libressl/crypto/CMakeLists.txt +0 -863
- data/vendor/libressl/crypto/Makefile.am +0 -962
- data/vendor/libressl/crypto/Makefile.am.arc4random +0 -46
- data/vendor/libressl/crypto/Makefile.am.elf-mips +0 -14
- data/vendor/libressl/crypto/Makefile.am.elf-mips64 +0 -14
- data/vendor/libressl/crypto/Makefile.am.elf-x86_64 +0 -35
- data/vendor/libressl/crypto/Makefile.am.macosx-x86_64 +0 -35
- data/vendor/libressl/crypto/Makefile.am.masm-x86_64 +0 -22
- data/vendor/libressl/crypto/Makefile.am.mingw64-x86_64 +0 -23
- data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_darwin.c +0 -60
- data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_linux.c +0 -62
- data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_none.c +0 -26
- data/vendor/libressl/crypto/arch/aarch64/crypto_cpu_caps_windows.c +0 -36
- data/vendor/libressl/crypto/arch/loongarch64/crypto_arch.h +0 -21
- data/vendor/libressl/crypto/arch/mips/crypto_arch.h +0 -21
- data/vendor/libressl/crypto/bn/arch/loongarch64/bn_arch.h +0 -23
- data/vendor/libressl/crypto/bn/arch/mips/bn_arch.h +0 -24
- data/vendor/libressl/crypto/compat/.gitignore +0 -31
- data/vendor/libressl/crypto/compat/arc4random.h +0 -41
- data/vendor/libressl/crypto/compat/b_win.c +0 -55
- data/vendor/libressl/crypto/compat/bsd-asprintf.c +0 -96
- data/vendor/libressl/crypto/compat/crypto_lock_win.c +0 -56
- data/vendor/libressl/crypto/compat/explicit_bzero_win.c +0 -13
- data/vendor/libressl/crypto/compat/freezero.c +0 -32
- data/vendor/libressl/crypto/compat/getdelim.c +0 -78
- data/vendor/libressl/crypto/compat/getline.c +0 -40
- data/vendor/libressl/crypto/compat/getopt_long.c +0 -528
- data/vendor/libressl/crypto/compat/getpagesize.c +0 -18
- data/vendor/libressl/crypto/compat/getprogname_linux.c +0 -23
- data/vendor/libressl/crypto/compat/getprogname_unimpl.c +0 -7
- data/vendor/libressl/crypto/compat/getprogname_windows.c +0 -13
- data/vendor/libressl/crypto/compat/posix_win.c +0 -296
- data/vendor/libressl/crypto/compat/syslog_r.c +0 -19
- data/vendor/libressl/crypto/compat/ui_openssl_win.c +0 -334
- data/vendor/libressl/dist.sh +0 -22
- data/vendor/libressl/gen-coverage-report.sh +0 -58
- data/vendor/libressl/gen-openbsd-tags.sh +0 -20
- data/vendor/libressl/include/CMakeLists.txt +0 -61
- data/vendor/libressl/include/Makefile.am +0 -79
- data/vendor/libressl/include/arch/loongarch64/opensslconf.h +0 -150
- data/vendor/libressl/include/arch/mips/opensslconf.h +0 -150
- data/vendor/libressl/include/compat/arpa/inet.h +0 -15
- data/vendor/libressl/include/compat/arpa/nameser.h +0 -25
- data/vendor/libressl/include/compat/cet.h +0 -19
- data/vendor/libressl/include/compat/dirent.h +0 -17
- data/vendor/libressl/include/compat/dirent_msvc.h +0 -611
- data/vendor/libressl/include/compat/endian.h +0 -161
- data/vendor/libressl/include/compat/err.h +0 -95
- data/vendor/libressl/include/compat/fcntl.h +0 -32
- data/vendor/libressl/include/compat/getopt.h +0 -50
- data/vendor/libressl/include/compat/limits.h +0 -25
- data/vendor/libressl/include/compat/netdb.h +0 -10
- data/vendor/libressl/include/compat/netinet/in.h +0 -19
- data/vendor/libressl/include/compat/netinet/ip.h +0 -49
- data/vendor/libressl/include/compat/netinet/tcp.h +0 -10
- data/vendor/libressl/include/compat/poll.h +0 -63
- data/vendor/libressl/include/compat/pthread.h +0 -122
- data/vendor/libressl/include/compat/readpassphrase.h +0 -44
- data/vendor/libressl/include/compat/resolv.h +0 -24
- data/vendor/libressl/include/compat/stdint.h +0 -31
- data/vendor/libressl/include/compat/stdio.h +0 -65
- data/vendor/libressl/include/compat/stdlib.h +0 -57
- data/vendor/libressl/include/compat/string.h +0 -98
- data/vendor/libressl/include/compat/sys/_null.h +0 -18
- data/vendor/libressl/include/compat/sys/ioctl.h +0 -11
- data/vendor/libressl/include/compat/sys/mman.h +0 -19
- data/vendor/libressl/include/compat/sys/param.h +0 -15
- data/vendor/libressl/include/compat/sys/queue.h +0 -536
- data/vendor/libressl/include/compat/sys/select.h +0 -10
- data/vendor/libressl/include/compat/sys/socket.h +0 -18
- data/vendor/libressl/include/compat/sys/stat.h +0 -129
- data/vendor/libressl/include/compat/sys/time.h +0 -37
- data/vendor/libressl/include/compat/sys/tree.h +0 -1006
- data/vendor/libressl/include/compat/sys/types.h +0 -69
- data/vendor/libressl/include/compat/sys/uio.h +0 -17
- data/vendor/libressl/include/compat/syslog.h +0 -38
- data/vendor/libressl/include/compat/time.h +0 -59
- data/vendor/libressl/include/compat/unistd.h +0 -83
- data/vendor/libressl/include/compat/win32netcompat.h +0 -57
- data/vendor/libressl/include/openssl/Makefile.am.tpl +0 -45
- data/vendor/libressl/libcrypto.pc.in +0 -28
- data/vendor/libressl/libressl.pub +0 -2
- data/vendor/libressl/libssl.pc.in +0 -28
- data/vendor/libressl/libtls.pc.in +0 -28
- data/vendor/libressl/m4/ax_add_fortify_source.m4 +0 -80
- data/vendor/libressl/m4/ax_check_compile_flag.m4 +0 -53
- data/vendor/libressl/m4/check-hardening-options.m4 +0 -110
- data/vendor/libressl/m4/check-libc.m4 +0 -189
- data/vendor/libressl/m4/check-os-options.m4 +0 -181
- data/vendor/libressl/m4/disable-compiler-warnings.m4 +0 -44
- data/vendor/libressl/man/CMakeLists.txt +0 -26
- data/vendor/libressl/man/links +0 -2780
- data/vendor/libressl/man/update_links.sh +0 -25
- data/vendor/libressl/openssl.pc.in +0 -11
- data/vendor/libressl/patches/bn_shift.patch +0 -34
- data/vendor/libressl/patches/crypto_arch.h.patch +0 -34
- data/vendor/libressl/patches/crypto_namespace.h.patch +0 -22
- data/vendor/libressl/patches/netcat.c.patch +0 -178
- data/vendor/libressl/patches/openssl.c.patch +0 -12
- data/vendor/libressl/patches/opensslfeatures.h.patch +0 -49
- data/vendor/libressl/patches/patch-amd64-crypto-cpu-caps.c.patch +0 -20
- data/vendor/libressl/patches/patch-i386-crypto-cpu-caps.c.patch +0 -20
- data/vendor/libressl/patches/speed.c.patch +0 -114
- data/vendor/libressl/patches/ssl_namespace.h.patch +0 -21
- data/vendor/libressl/patches/tls.h.patch +0 -16
- data/vendor/libressl/patches/tls_config.c.patch +0 -15
- data/vendor/libressl/patches/win32_amd64_bn_arch.h.patch +0 -28
- data/vendor/libressl/patches/windows_headers.patch +0 -80
- data/vendor/libressl/scripts/config.guess +0 -1774
- data/vendor/libressl/scripts/config.sub +0 -1907
- data/vendor/libressl/scripts/i686-w64-mingw32.cmake +0 -9
- data/vendor/libressl/scripts/test +0 -210
- data/vendor/libressl/scripts/wrap-compiler-for-flag-check +0 -31
- data/vendor/libressl/scripts/x86_64-w64-mingw32.cmake +0 -9
- data/vendor/libressl/ssl/CMakeLists.txt +0 -183
- data/vendor/libressl/ssl/Makefile.am +0 -187
- data/vendor/libressl/tests/CMakeLists.txt +0 -970
- data/vendor/libressl/tests/Makefile.am +0 -944
- data/vendor/libressl/tests/aeadtest.sh +0 -30
- data/vendor/libressl/tests/arc4randomforktest.sh +0 -21
- data/vendor/libressl/tests/asn1time_small.test +0 -10
- data/vendor/libressl/tests/cmake/CMakeLists.txt +0 -52
- data/vendor/libressl/tests/cmake/crypto.c +0 -7
- data/vendor/libressl/tests/cmake/ssl.c +0 -6
- data/vendor/libressl/tests/cmake/tls.c +0 -6
- data/vendor/libressl/tests/compat/pipe2.c +0 -186
- data/vendor/libressl/tests/dtlstest.sh +0 -28
- data/vendor/libressl/tests/evptest.sh +0 -22
- data/vendor/libressl/tests/keypairtest.sh +0 -27
- data/vendor/libressl/tests/mlkem_tests.sh +0 -39
- data/vendor/libressl/tests/ocsptest.bat +0 -25
- data/vendor/libressl/tests/ocsptest.sh +0 -23
- data/vendor/libressl/tests/openssl.cnf +0 -29
- data/vendor/libressl/tests/optionstest.c +0 -381
- data/vendor/libressl/tests/pidwraptest.c +0 -85
- data/vendor/libressl/tests/pidwraptest.sh +0 -26
- data/vendor/libressl/tests/quictest.bat +0 -27
- data/vendor/libressl/tests/quictest.sh +0 -30
- data/vendor/libressl/tests/renegotiation_test.bat +0 -27
- data/vendor/libressl/tests/renegotiation_test.sh +0 -30
- data/vendor/libressl/tests/rfc5280time_small.test +0 -10
- data/vendor/libressl/tests/servertest.bat +0 -27
- data/vendor/libressl/tests/servertest.sh +0 -30
- data/vendor/libressl/tests/shutdowntest.bat +0 -27
- data/vendor/libressl/tests/shutdowntest.sh +0 -30
- data/vendor/libressl/tests/ssltest.bat +0 -32
- data/vendor/libressl/tests/ssltest.sh +0 -48
- data/vendor/libressl/tests/testdsa.bat +0 -47
- data/vendor/libressl/tests/testdsa.sh +0 -57
- data/vendor/libressl/tests/testenc.bat +0 -85
- data/vendor/libressl/tests/testenc.sh +0 -93
- data/vendor/libressl/tests/testrsa.bat +0 -47
- data/vendor/libressl/tests/testrsa.sh +0 -57
- data/vendor/libressl/tests/testssl.bat +0 -171
- data/vendor/libressl/tests/tlstest.bat +0 -27
- data/vendor/libressl/tests/tlstest.sh +0 -28
- data/vendor/libressl/tls/CMakeLists.txt +0 -125
- data/vendor/libressl/tls/Makefile.am +0 -76
- data/vendor/libressl/tls/compat/ftruncate.c +0 -17
- data/vendor/libressl/tls/compat/pread.c +0 -29
- data/vendor/libressl/tls/compat/pwrite.c +0 -29
- data/vendor/libressl/update.sh +0 -460
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
|
|
5
|
+
require 'uringmachine'
|
|
6
|
+
require 'uringmachine/fiber_scheduler'
|
|
7
|
+
require 'securerandom'
|
|
8
|
+
|
|
9
|
+
$machine = UringMachine.new
|
|
10
|
+
scheduler = UM::FiberScheduler.new($machine)
|
|
11
|
+
Fiber.set_scheduler scheduler
|
|
12
|
+
|
|
13
|
+
fn = "/tmp/file_io_#{SecureRandom.hex}"
|
|
14
|
+
|
|
15
|
+
r, w = IO.pipe
|
|
16
|
+
|
|
17
|
+
f1 = Fiber.schedule do
|
|
18
|
+
File.open(fn, 'w') {
|
|
19
|
+
it.sync = true
|
|
20
|
+
UM.debug "writing..."
|
|
21
|
+
it << 'foobar'
|
|
22
|
+
# w.close
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
File.open(fn, 'r') {
|
|
26
|
+
UM.debug "reading..."
|
|
27
|
+
buf = it.read
|
|
28
|
+
UM.debug "read: #{buf}"
|
|
29
|
+
}
|
|
30
|
+
rescue => e
|
|
31
|
+
p e
|
|
32
|
+
p e.backtrace
|
|
33
|
+
end
|
|
34
|
+
scheduler.join
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/inline'
|
|
4
|
+
|
|
5
|
+
gemfile do
|
|
6
|
+
source 'https://rubygems.org'
|
|
7
|
+
gem 'io-event'
|
|
8
|
+
gem 'async'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
require 'async'
|
|
13
|
+
require 'securerandom'
|
|
14
|
+
|
|
15
|
+
selector ||= IO::Event::Selector::URing.new(Fiber.current)
|
|
16
|
+
scheduler = Async::Scheduler.new(selector:)
|
|
17
|
+
Fiber.set_scheduler scheduler
|
|
18
|
+
|
|
19
|
+
fn = "/tmp/file_io_#{SecureRandom.hex}"
|
|
20
|
+
|
|
21
|
+
scheduler.run do
|
|
22
|
+
Fiber.schedule do
|
|
23
|
+
File.open(fn, 'w') {
|
|
24
|
+
it << 'foo'
|
|
25
|
+
p pre_flush: IO.read(fn)
|
|
26
|
+
it.flush
|
|
27
|
+
it << 'bar'
|
|
28
|
+
p post_flush: IO.read(fn)
|
|
29
|
+
|
|
30
|
+
}
|
|
31
|
+
p post_close: IO.read(fn)
|
|
32
|
+
end
|
|
33
|
+
end
|
data/ext/um/extconf.rb
CHANGED
|
@@ -54,6 +54,21 @@ if !find_library('uring', nil, File.join(liburing_path, 'src'))
|
|
|
54
54
|
raise "Couldn't find liburing.a"
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
if !have_header("openssl/ssl.h")
|
|
58
|
+
raise "Couldn't find OpenSSL headers"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if !have_library("ssl", "SSL_new")
|
|
62
|
+
raise "Couldn't find OpenSSL library"
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
version_ok = checking_for("OpenSSL version >= 1.1.1") {
|
|
66
|
+
try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10101000L", "openssl/opensslv.h")
|
|
67
|
+
}
|
|
68
|
+
unless version_ok
|
|
69
|
+
raise "OpenSSL >= 1.1.1 or LibreSSL >= 3.9.0 is required"
|
|
70
|
+
end
|
|
71
|
+
|
|
57
72
|
have_func("&rb_process_status_new")
|
|
58
73
|
|
|
59
74
|
$defs << "-DUM_KERNEL_VERSION=#{config[:kernel_version]}"
|
data/ext/um/um.c
CHANGED
|
@@ -18,7 +18,7 @@ inline void prepare_io_uring_params(struct io_uring_params *params, uint sqpoll_
|
|
|
18
18
|
params->flags |= IORING_SETUP_COOP_TASKRUN;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
void um_setup(VALUE self, struct um *machine, uint size, uint sqpoll_timeout_msec) {
|
|
21
|
+
void um_setup(VALUE self, struct um *machine, uint size, uint sqpoll_timeout_msec, int sidecar_mode) {
|
|
22
22
|
memset(machine, 0, sizeof(struct um));
|
|
23
23
|
|
|
24
24
|
RB_OBJ_WRITE(self, &machine->self, self);
|
|
@@ -27,16 +27,26 @@ void um_setup(VALUE self, struct um *machine, uint size, uint sqpoll_timeout_mse
|
|
|
27
27
|
machine->size = (size > 0) ? size : DEFAULT_SIZE;
|
|
28
28
|
machine->sqpoll_mode = !!sqpoll_timeout_msec;
|
|
29
29
|
|
|
30
|
+
// sidecar handling
|
|
31
|
+
machine->sidecar_mode = sidecar_mode;
|
|
32
|
+
machine->sidecar_signal = aligned_alloc(4, sizeof(uint32_t));
|
|
33
|
+
memset(machine->sidecar_signal, 0, sizeof(uint32_t));
|
|
34
|
+
|
|
30
35
|
struct io_uring_params params;
|
|
31
36
|
prepare_io_uring_params(¶ms, sqpoll_timeout_msec);
|
|
32
37
|
int ret = io_uring_queue_init_params(machine->size, &machine->ring, ¶ms);
|
|
33
38
|
if (ret) rb_syserr_fail(-ret, strerror(-ret));
|
|
34
39
|
machine->ring_initialized = 1;
|
|
40
|
+
|
|
41
|
+
if (machine->sidecar_mode) um_sidecar_setup(machine);
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
inline void um_teardown(struct um *machine) {
|
|
38
45
|
if (!machine->ring_initialized) return;
|
|
39
46
|
|
|
47
|
+
if (machine->sidecar_mode) um_sidecar_teardown(machine);
|
|
48
|
+
if (machine->sidecar_signal) free(machine->sidecar_signal);
|
|
49
|
+
|
|
40
50
|
for (unsigned i = 0; i < machine->buffer_ring_count; i++) {
|
|
41
51
|
struct buf_ring_descriptor *desc = machine->buffer_rings + i;
|
|
42
52
|
io_uring_free_buf_ring(&machine->ring, desc->br, desc->buf_count, i);
|
|
@@ -59,8 +69,7 @@ inline struct io_uring_sqe *um_get_sqe(struct um *machine, struct um_op *op) {
|
|
|
59
69
|
sqe = io_uring_get_sqe(&machine->ring);
|
|
60
70
|
if (likely(sqe)) goto done;
|
|
61
71
|
|
|
62
|
-
|
|
63
|
-
um_raise_internal_error("Failed to get SQE");
|
|
72
|
+
um_raise_internal_error("Submission queue full. Consider raising the machine size.");
|
|
64
73
|
|
|
65
74
|
// TODO: retry getting SQE?
|
|
66
75
|
|
|
@@ -271,37 +280,60 @@ inline void um_profile_wait_cqe_post(struct um *machine, double time_monotonic0,
|
|
|
271
280
|
// machine->metrics.time_last_cpu = time_cpu;
|
|
272
281
|
}
|
|
273
282
|
|
|
283
|
+
inline void *um_wait_for_sidecar_signal(void *ptr) {
|
|
284
|
+
struct um *machine = ptr;
|
|
285
|
+
um_sidecar_signal_wait(machine);
|
|
286
|
+
return NULL;
|
|
287
|
+
}
|
|
288
|
+
|
|
274
289
|
// Waits for the given minimum number of completion entries. The wait_nr is
|
|
275
290
|
// either 1 - where we wait for at least one CQE to be ready, or 0, where we
|
|
276
291
|
// don't wait, and just process any CQEs that already ready.
|
|
277
292
|
static inline void um_wait_for_and_process_ready_cqes(struct um *machine, int wait_nr) {
|
|
278
293
|
struct wait_for_cqe_ctx ctx = { .machine = machine, .cqe = NULL, .wait_nr = wait_nr };
|
|
279
294
|
machine->metrics.total_waits++;
|
|
280
|
-
double time_monotonic0 = 0.0;
|
|
281
|
-
VALUE fiber;
|
|
282
|
-
if (machine->profile_mode) um_profile_wait_cqe_pre(machine, &time_monotonic0, &fiber);
|
|
283
|
-
rb_thread_call_without_gvl(um_wait_for_cqe_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
|
|
284
|
-
if (machine->profile_mode) um_profile_wait_cqe_post(machine, time_monotonic0, fiber);
|
|
285
|
-
|
|
286
|
-
if (unlikely(ctx.result < 0)) {
|
|
287
|
-
// the internal calls to (maybe submit) and wait for cqes may fail with:
|
|
288
|
-
// -EINTR (interrupted by signal)
|
|
289
|
-
// -EAGAIN (apparently can be returned when wait_nr = 0)
|
|
290
|
-
// both should not raise an exception.
|
|
291
|
-
switch (ctx.result) {
|
|
292
|
-
case -EINTR:
|
|
293
|
-
case -EAGAIN:
|
|
294
|
-
// do nothing
|
|
295
|
-
break;
|
|
296
|
-
default:
|
|
297
|
-
rb_syserr_fail(-ctx.result, strerror(-ctx.result));
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
295
|
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
|
|
296
|
+
if (machine->sidecar_mode) {
|
|
297
|
+
// fprintf(stderr, ">> sidecar wait cqes (unsubmitted: %d)\n", machine->metrics.ops_unsubmitted);
|
|
298
|
+
if (machine->metrics.ops_unsubmitted) {
|
|
299
|
+
io_uring_submit(&machine->ring);
|
|
300
|
+
machine->metrics.ops_unsubmitted = 0;
|
|
301
|
+
}
|
|
302
|
+
if (wait_nr) {
|
|
303
|
+
// fprintf(stderr, ">> um_wait_for_sidecar_signal\n");
|
|
304
|
+
// rb_thread_call_without_gvl(um_wait_for_sidecar_signal, (void *)machine, RUBY_UBF_PROCESS, 0);
|
|
305
|
+
// fprintf(stderr, "<< um_wait_for_sidecar_signal\n");
|
|
306
|
+
um_sidecar_signal_wait(machine);
|
|
307
|
+
}
|
|
304
308
|
um_process_ready_cqes(machine);
|
|
309
|
+
// fprintf(stderr, "<< sidecar wait cqes\n");
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
double time_monotonic0 = 0.0;
|
|
313
|
+
VALUE fiber;
|
|
314
|
+
if (machine->profile_mode) um_profile_wait_cqe_pre(machine, &time_monotonic0, &fiber);
|
|
315
|
+
rb_thread_call_without_gvl(um_wait_for_cqe_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
|
|
316
|
+
if (machine->profile_mode) um_profile_wait_cqe_post(machine, time_monotonic0, fiber);
|
|
317
|
+
|
|
318
|
+
if (unlikely(ctx.result < 0)) {
|
|
319
|
+
// the internal calls to (maybe submit) and wait for cqes may fail with:
|
|
320
|
+
// -EINTR (interrupted by signal)
|
|
321
|
+
// -EAGAIN (apparently can be returned when wait_nr = 0)
|
|
322
|
+
// both should not raise an exception.
|
|
323
|
+
switch (ctx.result) {
|
|
324
|
+
case -EINTR:
|
|
325
|
+
case -EAGAIN:
|
|
326
|
+
// do nothing
|
|
327
|
+
break;
|
|
328
|
+
default:
|
|
329
|
+
rb_syserr_fail(-ctx.result, strerror(-ctx.result));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (ctx.cqe) {
|
|
333
|
+
um_process_cqe(machine, ctx.cqe);
|
|
334
|
+
io_uring_cq_advance(&machine->ring, 1);
|
|
335
|
+
um_process_ready_cqes(machine);
|
|
336
|
+
}
|
|
305
337
|
}
|
|
306
338
|
}
|
|
307
339
|
|
|
@@ -336,30 +368,15 @@ inline VALUE um_switch(struct um *machine) {
|
|
|
336
368
|
&machine->ring, machine->metrics.ops_unsubmitted, machine->metrics.ops_pending,
|
|
337
369
|
machine->metrics.total_ops
|
|
338
370
|
);
|
|
371
|
+
|
|
339
372
|
while (true) {
|
|
340
373
|
struct um_op *op = um_runqueue_shift(machine);
|
|
341
374
|
if (op) {
|
|
342
375
|
if (unlikely(op->flags & OP_F_RUNQUEUE_SKIP)) continue;
|
|
343
376
|
|
|
344
|
-
// in
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
// snooze repeatedly, which can prevent completions from being processed.
|
|
348
|
-
|
|
349
|
-
// is the op a snooze op and is this the same fiber as the current one?
|
|
350
|
-
if (unlikely(op->kind == OP_SCHEDULE && op->fiber == rb_fiber_current())) {
|
|
351
|
-
// are there any pending ops (i.e. waiting for completion)?
|
|
352
|
-
if (machine->metrics.ops_pending > 0) {
|
|
353
|
-
// if yes, process completions, get runqueue head, put original op
|
|
354
|
-
// back on runqueue.
|
|
355
|
-
// um_process_ready_cqes(machine);
|
|
356
|
-
um_wait_for_and_process_ready_cqes(machine, 0);
|
|
357
|
-
struct um_op *op2 = um_runqueue_shift(machine);
|
|
358
|
-
if (likely(op2 && op2 != op)) {
|
|
359
|
-
um_runqueue_push(machine, op);
|
|
360
|
-
op = op2;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
377
|
+
// in test mode we want to process I/O on each snooze
|
|
378
|
+
if (unlikely(machine->test_mode && (op->kind == OP_SCHEDULE))) {
|
|
379
|
+
um_wait_for_and_process_ready_cqes(machine, 0);
|
|
363
380
|
}
|
|
364
381
|
return process_runqueue_op(machine, op);
|
|
365
382
|
}
|
|
@@ -513,7 +530,7 @@ VALUE um_read(struct um *machine, int fd, VALUE buffer, size_t maxlen, ssize_t b
|
|
|
513
530
|
VALUE ret = um_yield(machine);
|
|
514
531
|
|
|
515
532
|
if (um_check_completion(machine, &op)) {
|
|
516
|
-
um_update_read_buffer(
|
|
533
|
+
um_update_read_buffer(buffer, buffer_offset, op.result.res);
|
|
517
534
|
ret = INT2NUM(op.result.res);
|
|
518
535
|
|
|
519
536
|
}
|
|
@@ -563,6 +580,22 @@ VALUE um_write(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_
|
|
|
563
580
|
return ret;
|
|
564
581
|
}
|
|
565
582
|
|
|
583
|
+
size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t maxlen) {
|
|
584
|
+
struct um_op op;
|
|
585
|
+
um_prep_op(machine, &op, OP_WRITE, 0);
|
|
586
|
+
struct io_uring_sqe *sqe = um_get_sqe(machine, &op);
|
|
587
|
+
io_uring_prep_write(sqe, fd, buffer, maxlen, 0);
|
|
588
|
+
|
|
589
|
+
VALUE ret = um_yield(machine);
|
|
590
|
+
|
|
591
|
+
if (um_check_completion(machine, &op))
|
|
592
|
+
return op.result.res;
|
|
593
|
+
|
|
594
|
+
RAISE_IF_EXCEPTION(ret);
|
|
595
|
+
RB_GC_GUARD(ret);
|
|
596
|
+
return 0;
|
|
597
|
+
}
|
|
598
|
+
|
|
566
599
|
VALUE um_writev(struct um *machine, int fd, int argc, VALUE *argv) {
|
|
567
600
|
__u64 file_offset = -1;
|
|
568
601
|
if (TYPE(argv[argc - 1]) == T_FIXNUM) {
|
|
@@ -592,10 +625,10 @@ VALUE um_writev(struct um *machine, int fd, int argc, VALUE *argv) {
|
|
|
592
625
|
|
|
593
626
|
int completed = um_op_completed_p(&op);
|
|
594
627
|
if (unlikely(!completed)) goto cancelled;
|
|
595
|
-
|
|
628
|
+
|
|
596
629
|
writev_res = op.result.res;
|
|
597
630
|
if (unlikely(writev_res < 0)) goto done;
|
|
598
|
-
|
|
631
|
+
|
|
599
632
|
len -= writev_res;
|
|
600
633
|
if (len) {
|
|
601
634
|
um_advance_iovecs_for_writing(&iovecs_ptr, &iovecs_len, (size_t)writev_res);
|
|
@@ -788,7 +821,7 @@ VALUE um_recv(struct um *machine, int fd, VALUE buffer, size_t maxlen, int flags
|
|
|
788
821
|
VALUE ret = um_yield(machine);
|
|
789
822
|
|
|
790
823
|
if (um_check_completion(machine, &op)) {
|
|
791
|
-
um_update_read_buffer(
|
|
824
|
+
um_update_read_buffer(buffer, 0, op.result.res);
|
|
792
825
|
ret = INT2NUM(op.result.res);
|
|
793
826
|
}
|
|
794
827
|
|
|
@@ -1016,7 +1049,7 @@ VALUE um_select(struct um *machine, VALUE rfds, VALUE wfds, VALUE efds) {
|
|
|
1016
1049
|
}
|
|
1017
1050
|
|
|
1018
1051
|
while (pending) {
|
|
1019
|
-
um_wait_for_and_process_ready_cqes(machine,
|
|
1052
|
+
um_wait_for_and_process_ready_cqes(machine, 1);
|
|
1020
1053
|
|
|
1021
1054
|
for (uint i = 0; i < total_len; i++) {
|
|
1022
1055
|
struct um_op *op = ops + i;
|
data/ext/um/um.h
CHANGED
|
@@ -156,7 +156,11 @@ struct um {
|
|
|
156
156
|
uint mark; // used to mark instances for debugging
|
|
157
157
|
|
|
158
158
|
struct um_metrics metrics;
|
|
159
|
+
int test_mode;
|
|
159
160
|
int profile_mode;
|
|
161
|
+
int sidecar_mode;
|
|
162
|
+
pthread_t sidecar_thread;
|
|
163
|
+
uint32_t *sidecar_signal;
|
|
160
164
|
|
|
161
165
|
uint buffer_ring_count; // number of registered buffer rings
|
|
162
166
|
|
|
@@ -166,7 +170,7 @@ struct um {
|
|
|
166
170
|
struct buf_ring_descriptor buffer_rings[BUFFER_RING_MAX_COUNT];
|
|
167
171
|
|
|
168
172
|
struct um_op *transient_head; // list of pending transient ops
|
|
169
|
-
VALUE pending_fibers; //
|
|
173
|
+
VALUE pending_fibers; // set containing pending fibers
|
|
170
174
|
|
|
171
175
|
struct um_op *runqueue_head;
|
|
172
176
|
struct um_op *runqueue_tail;
|
|
@@ -227,7 +231,7 @@ extern VALUE cAsyncOp;
|
|
|
227
231
|
extern VALUE eStreamRESPError;
|
|
228
232
|
|
|
229
233
|
struct um *um_get_machine(VALUE self);
|
|
230
|
-
void um_setup(VALUE self, struct um *machine, uint size, uint sqpoll_timeout_msec);
|
|
234
|
+
void um_setup(VALUE self, struct um *machine, uint size, uint sqpoll_timeout_msec, int sidecar_mode);
|
|
231
235
|
void um_teardown(struct um *machine);
|
|
232
236
|
|
|
233
237
|
VALUE um_metrics(struct um *machine, struct um_metrics *metrics);
|
|
@@ -264,7 +268,7 @@ void um_prep_op(struct um *machine, struct um_op *op, enum um_op_kind kind, unsi
|
|
|
264
268
|
void um_raise_on_error_result(int result);
|
|
265
269
|
void um_get_buffer_bytes_for_writing(VALUE buffer, const void **base, size_t *size);
|
|
266
270
|
void * um_prepare_read_buffer(VALUE buffer, ssize_t len, ssize_t ofs);
|
|
267
|
-
void um_update_read_buffer(
|
|
271
|
+
void um_update_read_buffer(VALUE buffer, ssize_t buffer_offset, __s32 result);
|
|
268
272
|
int um_setup_buffer_ring(struct um *machine, unsigned size, unsigned count);
|
|
269
273
|
VALUE um_get_string_from_buffer_ring(struct um *machine, int bgid, __s32 result, __u32 flags);
|
|
270
274
|
void um_add_strings_to_buffer_ring(struct um *machine, int bgid, VALUE strings);
|
|
@@ -293,6 +297,7 @@ VALUE um_read(struct um *machine, int fd, VALUE buffer, size_t maxlen, ssize_t b
|
|
|
293
297
|
size_t um_read_raw(struct um *machine, int fd, char *buffer, size_t maxlen);
|
|
294
298
|
VALUE um_read_each(struct um *machine, int fd, int bgid);
|
|
295
299
|
VALUE um_write(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_offset);
|
|
300
|
+
size_t um_write_raw(struct um *machine, int fd, const char *buffer, size_t maxlen);
|
|
296
301
|
VALUE um_writev(struct um *machine, int fd, int argc, VALUE *argv);
|
|
297
302
|
VALUE um_write_async(struct um *machine, int fd, VALUE buffer, size_t len, __u64 file_offset);
|
|
298
303
|
VALUE um_close(struct um *machine, int fd);
|
|
@@ -350,6 +355,7 @@ VALUE stream_get_line(struct um_stream *stream, VALUE buf, ssize_t maxlen);
|
|
|
350
355
|
VALUE stream_get_string(struct um_stream *stream, VALUE buf, ssize_t len);
|
|
351
356
|
VALUE resp_decode(struct um_stream *stream, VALUE out_buffer);
|
|
352
357
|
void resp_encode(struct um_write_buffer *buf, VALUE obj);
|
|
358
|
+
void resp_encode_cmd(struct um_write_buffer *buf, int argc, VALUE *argv);
|
|
353
359
|
|
|
354
360
|
__attribute__((noreturn)) void um_raise_internal_error(const char *msg);
|
|
355
361
|
|
|
@@ -358,4 +364,13 @@ void write_buffer_update_len(struct um_write_buffer *buf);
|
|
|
358
364
|
|
|
359
365
|
void um_define_net_constants(VALUE mod);
|
|
360
366
|
|
|
367
|
+
void um_sidecar_setup(struct um *machine);
|
|
368
|
+
void um_sidecar_teardown(struct um *machine);
|
|
369
|
+
void um_sidecar_signal_wait(struct um *machine);
|
|
370
|
+
void um_sidecar_signal_wake(struct um *machine);
|
|
371
|
+
|
|
372
|
+
void um_ssl_set_bio(struct um *machine, VALUE ssl_obj);
|
|
373
|
+
int um_ssl_read(struct um *machine, VALUE ssl, VALUE buf, int maxlen);
|
|
374
|
+
int um_ssl_write(struct um *machine, VALUE ssl, VALUE buf, int len);
|
|
375
|
+
|
|
361
376
|
#endif // UM_H
|
data/ext/um/um_async_op_class.c
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
#include "um.h"
|
|
2
2
|
#include <stdlib.h>
|
|
3
3
|
|
|
4
|
+
/*
|
|
5
|
+
* Document-class: UringMachine::AsyncOp
|
|
6
|
+
*
|
|
7
|
+
* Encapsulates an asynchronous operation. Currently the only asynchronous
|
|
8
|
+
* operation supported is a timeout operation.
|
|
9
|
+
*/
|
|
10
|
+
|
|
4
11
|
VALUE cAsyncOp;
|
|
5
12
|
|
|
6
13
|
VALUE SYM_timeout;
|
|
@@ -59,6 +66,10 @@ inline int async_op_is_done(struct um_async_op *async_op) {
|
|
|
59
66
|
return (async_op->op->flags & OP_F_COMPLETED);
|
|
60
67
|
}
|
|
61
68
|
|
|
69
|
+
/* Returns the kind of asynchronous operation.
|
|
70
|
+
*
|
|
71
|
+
* @return [Symbol] operation kind
|
|
72
|
+
*/
|
|
62
73
|
VALUE AsyncOp_kind(VALUE self) {
|
|
63
74
|
struct um_async_op *async_op = AsyncOp_data(self);
|
|
64
75
|
raise_on_missing_op(async_op);
|
|
@@ -71,6 +82,10 @@ VALUE AsyncOp_kind(VALUE self) {
|
|
|
71
82
|
}
|
|
72
83
|
}
|
|
73
84
|
|
|
85
|
+
/* Returns true if the operation has completed.
|
|
86
|
+
*
|
|
87
|
+
* @return [bool] is the operation done
|
|
88
|
+
*/
|
|
74
89
|
VALUE AsyncOp_done_p(VALUE self) {
|
|
75
90
|
struct um_async_op *async_op = AsyncOp_data(self);
|
|
76
91
|
raise_on_missing_op(async_op);
|
|
@@ -78,6 +93,10 @@ VALUE AsyncOp_done_p(VALUE self) {
|
|
|
78
93
|
return async_op_is_done(async_op) ? Qtrue : Qfalse;
|
|
79
94
|
}
|
|
80
95
|
|
|
96
|
+
/* Returns the operation result. If the operation is not completed, returns nil.
|
|
97
|
+
*
|
|
98
|
+
* @return [Integer, nil] operation result
|
|
99
|
+
*/
|
|
81
100
|
VALUE AsyncOp_result(VALUE self) {
|
|
82
101
|
struct um_async_op *async_op = AsyncOp_data(self);
|
|
83
102
|
raise_on_missing_op(async_op);
|
|
@@ -85,6 +104,10 @@ VALUE AsyncOp_result(VALUE self) {
|
|
|
85
104
|
return async_op_is_done(async_op) ? INT2NUM(async_op->op->result.res) : Qnil;
|
|
86
105
|
}
|
|
87
106
|
|
|
107
|
+
/* Returns true if the operation has been cancelled.
|
|
108
|
+
*
|
|
109
|
+
* @return [bool] is the operation cancelled
|
|
110
|
+
*/
|
|
88
111
|
VALUE AsyncOp_cancelled_p(VALUE self) {
|
|
89
112
|
struct um_async_op *async_op = AsyncOp_data(self);
|
|
90
113
|
raise_on_missing_op(async_op);
|
|
@@ -94,6 +117,10 @@ VALUE AsyncOp_cancelled_p(VALUE self) {
|
|
|
94
117
|
return (async_op->op->result.res == -ECANCELED) ? Qtrue : Qfalse;
|
|
95
118
|
}
|
|
96
119
|
|
|
120
|
+
/* Waits for the operation to complete.
|
|
121
|
+
*
|
|
122
|
+
* @return [Integer] operation result
|
|
123
|
+
*/
|
|
97
124
|
VALUE AsyncOp_await(VALUE self) {
|
|
98
125
|
struct um_async_op *async_op = AsyncOp_data(self);
|
|
99
126
|
raise_on_missing_op(async_op);
|
|
@@ -104,6 +131,10 @@ VALUE AsyncOp_await(VALUE self) {
|
|
|
104
131
|
return um_async_op_await(async_op);
|
|
105
132
|
}
|
|
106
133
|
|
|
134
|
+
/* Cancels the operation.
|
|
135
|
+
*
|
|
136
|
+
* @return [UringMachine::AsyncOp] self
|
|
137
|
+
*/
|
|
107
138
|
VALUE AsyncOp_cancel(VALUE self) {
|
|
108
139
|
struct um_async_op *async_op = AsyncOp_data(self);
|
|
109
140
|
raise_on_missing_op(async_op);
|