57 Commits

Author SHA1 Message Date
Thomas Leonard
ecd195da5d Move low-level Eio_linux functions to sub-module
The high-level API that was in `Eio_linux.Objects` is now the top-level
API.
2022-02-03 12:05:42 +00:00
Thomas Leonard
3bd2620fc7 Simplify Flow interface
Remove `read` and `write` classes and just use `source` and `sink` for
everything.

Rename `Flow.read_into src buf` to just `Flow.read src buf`, which makes
more sense.
2022-02-03 11:26:55 +00:00
Thomas Leonard
dddc0735eb Add Eio_unix.FD
This allows creating FDs with Eio and then using them in legacy code.
2022-02-02 14:18:07 +00:00
Thomas Leonard
af27a3008a Add secure_random device to stdenv
Co-authored-by: Patrick Ferris <pf341@patricoferris.com>
2022-02-02 13:48:20 +00:00
Thomas Leonard
6d80705250 Don't depend on Unix for IP address type 2022-01-25 13:27:36 +00:00
Thomas Leonard
369fdac081 [eio_linux] Allow running uring in polling mode
This can be much faster, as Linux can start handling requests without
waiting for us to submit them.
2022-01-24 16:39:44 +00:00
Thomas Leonard
77ff8e18f3 [eio_linux] Avoid copy in read_into
Now that `readv` is implemented, we can read directly into the user's
buffer. Testing this by reading from /dev/null into a 64K buffer was
about 5 times faster than the old way (which has a copy and is limited
by the chunk size).
2022-01-17 15:54:42 +00:00
Thomas Leonard
aea5d71a34 Allow reading absolute paths with Stdenv.fs
`open_in` was missing the fix that was already applied to `open_out` and
`open_dir`.
2022-01-17 15:48:04 +00:00
Thomas Leonard
b9ce69dd35 Fix minor documentation errors 2022-01-17 15:09:45 +00:00
Patrick Ferris
9188db3cfe EffectHandlers -> Effect
This also adds an Eio.Private.Effect compatibility module, which
allows Eio to continue running on 4.12+domains until 5.00 is released.
2022-01-17 10:46:27 +00:00
Thomas Leonard
2f7780935f Remove unused bigstringaf dependency 2022-01-14 11:24:35 +00:00
Thomas Leonard
08a5eab376 Add eio.unix module for Unix integration
For now, this provides `await_readable` and `await_writable`.
2022-01-07 16:39:12 +00:00
Thomas Leonard
e6138a1e94 Rename eunix to eio.utils
Nothing in here actually depends on Unix. This is just a collection of
utility modules that may be useful for building Eio backends. There is
no need for a separate opam package.
2022-01-07 14:34:02 +00:00
Thomas Leonard
2a8755be75 Add ~close_unix flag to FD.of_unix
For integrating with other APIs, it may be necessary to let the user
handle closing the FD.
2022-01-06 10:49:16 +00:00
Thomas Leonard
61b54b4c73 Simplify and improve error reporting
Cancellation contexts are now only about making things stop promptly,
not about reporting errors. That's now handled entirely by the switches.

This fixes a problem where an error raised while cancelling an operation
would be lost.

`Switch.turn_off` is now called `Switch.fail`.
2022-01-06 10:39:44 +00:00
Thomas Leonard
f2b5289bbe Add Fibre.fork_on_accept and Net.accept
`fork_on_accept` runs an accept function in a new switch. If it
succeeds, it passes the result to a handler function in a new fibre,
which adopts the switch.

This allows moving the complicated accept logic out of the individual
backends. It also allows adding the simpler `Net.accept` function for
the case where only a single connection needs to be accepted.

The behaviour of `Fork.sub ~sw ~on_error` has changed slightly:
`on_error` now runs in the context of the parent `sw`,
and is now skipped if and only if `sw` is cancelled.
Also, the `on_release` argument has been removed, since its only use can
now be done using `fork_on_accept`.
2022-01-04 14:23:43 +00:00
Bikal Lem
0008ace7a9 socket: set SO_REUSEPORT option
This commit adds the option of setting SO_REUSEPORT socket option in
linux_uring backend.

For libuv/luv backend, it seems it is not easy to set it as yet. This
is related to another outstanding issue related to SO_REUSEADDR
option in libuv backend. Perhaps once luv releases luv-unix, we can
revisit this issue again. For now in-order to ensure the repo builds
I have followed a similar approach as SO_REUSEADDR, i.e. dummy
function `luv_reuse_port` analogous to `luv_resuse_addr`.

SO_REUSEPORT can be used to build scalable, high performance network
servers in linux version 3.9 and over. This is so because reuseport
is used to enable socket sharding on multiple threads or child
processes. Listening sockets with SO_REUSEPORT enabled are further
load balanced by the kernel; so we get a performant load balancer
for free.

References:
https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/
https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ

Signed-off-by: Bikal Lem <gbikal+git@gmail.com>
2021-12-15 16:51:52 +00:00
Thomas Leonard
3614367515 Make Fibre.fork put both fibres at the head of the run-queue
Some arguments in favour of this:

- This is the most flexible arrangement (you can add yields gets the
  other combinations).
- The order seems a bit more natural (the README examples look better).
- Might be better for the cache in some cases (domainslib works this way).
- Means that `Fibre.both f g` starts `f` and `g` in similar contexts.
  Previously, `f` started before any queued items, while `g` started
  after, which was a bit inconsistent.

This also adds some documentation about scheduling order to the ocamldoc
(note that the previous documentation for `fork` was wrong) and adds a
`rationale.md` file explaining the choice.
2021-12-15 13:58:33 +00:00
Thomas Leonard
983ae79df9 Rename Fork_ignore to Fork
The hardly-used `Fibre.fork` is now `Fibre.fork_promise`.
2021-12-15 13:46:07 +00:00
Thomas Leonard
bc3b0276a2 Remove Fork effect
`Fork_ignore` can be used to implement it just as easily.
2021-12-15 08:31:26 +00:00
Thomas Leonard
9b7d7fcb26 Create fibre context before forking
This moves some more logic out of the individual backends and reduces
the number of contexts we need to create.
2021-12-13 15:23:02 +00:00
Thomas Leonard
43bae57330 Explain about Promises and Streams in the README 2021-12-13 12:01:35 +00:00
Thomas Leonard
f39837f611 Use lock-free run queue in eio_linux too 2021-12-09 14:38:43 +00:00
Thomas Leonard
254088d470 Make cancellation thread-safe
Previously, each cancellation context kept a list of functions to call
when cancelled. When a cancellable operation starts, a function is
registered which can be used to cancel it. When the operation finishes
(or is cancelled) the function is removed again.

With multiple domains, an operation may succeed in one domain just as it
is being cancelled in another. Since removing a node from a
doubly-linked list cannot be done atomically, this would require a
mutex.

Instead, a cancellation context now keeps a list of fibres. When a fibre
is forked, it gets added to the list, and when it finishes it is
removed. A fibre can also move to a new context (e.g. on `Cancel.sub`).
This list is only accessed from the fibre's own domain.

Each fibre holds a single (atomic, optional) cancellation function.
This is set when a cancellable operation starts. When the operation is
cancelled or finishes, this is cleared (using `Atomic.exchange`) and
the continuation is enqueued to be run.

This also fixes a cancellation bug in `Eio_luv.File`, where we cleared
the cancellation callback after starting an operation, not after it
ended!
2021-12-09 11:31:21 +00:00
Thomas Leonard
2fafad2d6e Move noop benchmark to lib_eio_linux
The other benchmarks can run on all platforms.
2021-12-08 10:17:41 +00:00
Thomas Leonard
c9d3f734e9 Avoid Fun.protect in Eio_linux.run
If the scheduler crashes, it tries to shut down the uring, which is
likely to fail. In that case, `Fun.protect` throws away the original
exception, which isn't helpful.
2021-12-07 12:48:17 +00:00
Thomas Leonard
bb105baa32 Add Domain_manager.run to start a domain with an event loop 2021-12-02 14:08:06 +00:00
Thomas Leonard
99435ef4a9 Thread-safe promises, streams and semaphores
There is a new `make bench` target to test them:

    Reading a resolved promise: 4.681 ns
    use_domains,   n_iters, ns/iter, promoted/iter
	  false,  1000000,   948.44,       26.0096
	   true,   100000, 13084.44,       16.7043
    dune exec -- ./bench/bench_stream.exe
    use_domains,  n_iters, capacity, ns/iter, promoted/iter
	  false, 10000000,        1,  150.53,        0.0090
	  false, 10000000,       10,   76.48,        0.0041
	  false, 10000000,      100,   52.41,        0.0112
	  false, 10000000,     1000,   51.88,        0.0696
	   true,  1000000,        1, 4087.97,        1.0091
	   true,  1000000,       10, 1084.47,        0.2518
	   true,  1000000,      100,  271.43,        0.0081
	   true,  1000000,     1000,  287.15,        0.0037
    dune exec -- ./bench/bench_semaphore.exe
    use_domains,   n_iters,  batch, ns/iter, promoted/iter
	  false,  1000000,   1,   354.46,        0.0246
	  false,  1000000,  10,    86.71,        0.0030
	  false,  1000000, 100,    57.40,        0.0010
	   true,   100000,   1, 12117.10,        3.0368
	   true,   100000,  10,  1555.81,        0.3111
	   true,   100000, 100,   339.90,        0.0364

Note: this is just a starting point and not well optimised.

Other changes:

- Hook is now defunctionalised (simpler and slightly faster).
- `Promise.state` no longer exposes the internals.
- `Switch.await` has moved to `Waiters`.
2021-11-26 10:16:24 +00:00
Thomas Leonard
3aec167795 Make enqueue thread-safe
Note that the deadlock detection code had to be deleted. Now that we can
be woken up from another domain, we can never be sure we're stuck.
2021-11-24 14:43:02 +00:00
Thomas Leonard
f379454555 Propagate backtraces in more places 2021-11-24 14:40:10 +00:00
Thomas Leonard
0116670732 Set cancelletion context correctly in Fibre.fork
In should inherit from the switch, not from the current context.
2021-11-18 10:57:31 +00:00
Thomas Leonard
9c41d9fdf2 Keep an explicit tree of cancellation contexts
This is slightly more efficient, and might also be useful to allow
dumping out the tree for debugging.
2021-11-18 10:32:35 +00:00
Thomas Leonard
3713d9470b Split cancellation out from Switch
Cancellation and grouping are easier to handle separately.

`Fibre.both` no longer takes a switch, but instead just creates a new
cancellation context.
2021-11-11 19:13:49 +00:00
Thomas Leonard
ed2382bed5 Implicit cancellation
Instead of requiring every cancellable operation to pass a `~sw`
argument, give each fibre a default switch and use that. It's too easy
to forget to make something cancellable and clutters up the code.
2021-11-08 13:27:51 +00:00
Sidharth Kshatriya
f3d1774e3a Effect handlers have their own module now
See https://github.com/ocaml-multicore/ocaml-multicore/pull/687
2021-10-12 20:46:34 +05:30
Thomas Leonard
055fe3036e linux_eio: Free the ring after use 2021-10-11 14:04:11 +01:00
Bikal Lem
84ff89390f make eio build with 4.12.0+domains OCaml 2021-10-07 18:09:58 +01:00
Thomas Leonard
beced77261 Don't crash when receiving a signal 2021-08-20 15:18:03 +01:00
Thomas Leonard
280ded7b61 Work-around for io_uring bug reading from terminals
Reading from a terminal blocks the whole process (see
https://github.com/axboe/liburing/issues/354).

Should be fixed in Linux 5.14.
2021-08-20 14:24:08 +01:00
Thomas Leonard
9a3b123953 Add Eio.Net.Connection_reset exception 2021-07-30 11:01:06 +01:00
Thomas Leonard
16ae4626c0 Update to cstruct 6.0.1 for shiftv 2021-07-29 15:47:37 +01:00
Thomas Leonard
b77176e212 Add eio_luv backend 2021-07-29 14:39:01 +01:00
Thomas Leonard
76c32e0e46 Add more generic exceptions
This is to avoid depending on backend-specific exceptions in the tests.
2021-07-26 18:34:02 +01:00
Thomas Leonard
75ec13ac00 Allow cancelling writes during copies too 2021-07-19 16:50:07 +01:00
Thomas Leonard
88f0b3107e Add Flow.read_methods for optimised reading
Allows sources to offer faster alternatives. This is useful for e.g.
faraday and tls, which allocate their own buffers. The Linux FD sink
now uses `writev` to send the data directly where possible.
2021-07-19 13:52:45 +01:00
Thomas Leonard
8f5043c458 Improve traceln formatting
- Set up a box so that wrapping works correctly.
- Print a `+` at the start of each trace line to show it is trace output.
- Format location tag with the rest of the output (fixes wrapping).
- Add tests for traceln.
2021-07-15 11:42:19 +01:00
Thomas Leonard
8a1b2c6d82 Make traceln an effect
This allows different backends to provide different implementations,
and allows suppressing or changing trace output where needed.
2021-07-15 10:47:18 +01:00
Thomas Leonard
9aacbc3444 Use new Enter effect for most other operations 2021-06-24 11:55:17 +01:00
Thomas Leonard
da84272736 Add generic Enter effect to simplify scheduler 2021-06-24 11:37:00 +01:00
Thomas Leonard
d9f8f70223 Simplify handling of completions
We can handle the different log messages after the effect has finished.
2021-06-24 11:21:46 +01:00