Skip to content

Commit 6beace5

Browse files
talex5haesbaert
andcommitted
Initial Eio_posix backend
Co-authored-by: Christiano Haesbaert <haesbaert@haesbaert.org>
1 parent e728f53 commit 6beace5

28 files changed

+1498
-5
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ bench:
1717
test_luv:
1818
EIO_BACKEND=luv dune runtest
1919

20+
test_posix:
21+
EIO_BACKEND=posix dune runtest
22+
2023
dscheck:
2124
dune exec -- ./lib_eio/tests/dscheck/test_rcfd.exe
2225
dune exec -- ./lib_eio/tests/dscheck/test_sync.exe

dune-project

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
(package
3333
(name eio_linux)
3434
(synopsis "Eio implementation for Linux using io-uring")
35-
(description "An eio implementation for Linux using io-uring.")
35+
(description "An Eio implementation for Linux using io-uring.")
3636
(depends
3737
(alcotest (and (>= 1.4.0) :with-test))
3838
(eio (= :version))
@@ -41,10 +41,19 @@
4141
(fmt (>= 0.8.9))
4242
(cmdliner (and (>= 1.1.0) :with-test))
4343
(uring (>= 0.5))))
44+
(package
45+
(name eio_posix)
46+
(synopsis "Eio implementation for POSIX systems")
47+
(description "An Eio implementation for most Unix-like platforms")
48+
(depends
49+
(eio (= :version))
50+
(iomux (>= 0.2))
51+
(mdx (and (>= 1.10.0) :with-test))
52+
(fmt (>= 0.8.9))))
4453
(package
4554
(name eio_luv)
4655
(synopsis "Eio implementation using luv (libuv)")
47-
(description "An eio implementation for most platforms, using luv.")
56+
(description "An Eio implementation for most platforms, using luv.")
4857
(depends
4958
(eio (= :version))
5059
(luv (>= 0.5.11))
@@ -58,5 +67,6 @@
5867
(depends
5968
(eio_linux (and (= :version) (= :os "linux")))
6069
(mdx (and (>= 1.10.0) :with-test))
70+
(eio_posix (= :version))
6171
(eio_luv (= :version))))
6272
(using mdx 0.2)

eio_linux.opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This file is generated by dune, edit dune-project instead
22
opam-version: "2.0"
33
synopsis: "Eio implementation for Linux using io-uring"
4-
description: "An eio implementation for Linux using io-uring."
4+
description: "An Eio implementation for Linux using io-uring."
55
maintainer: ["anil@recoil.org"]
66
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
77
license: "ISC"

eio_luv.opam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This file is generated by dune, edit dune-project instead
22
opam-version: "2.0"
33
synopsis: "Eio implementation using luv (libuv)"
4-
description: "An eio implementation for most platforms, using luv."
4+
description: "An Eio implementation for most platforms, using luv."
55
maintainer: ["anil@recoil.org"]
66
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
77
license: "ISC"

eio_main.opam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ depends: [
1212
"dune" {>= "3.0"}
1313
"eio_linux" {= version & os = "linux"}
1414
"mdx" {>= "1.10.0" & with-test}
15+
"eio_posix" {= version}
1516
"eio_luv" {= version}
1617
"odoc" {with-doc}
1718
]

eio_posix.opam

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# This file is generated by dune, edit dune-project instead
2+
opam-version: "2.0"
3+
synopsis: "Eio implementation for POSIX systems"
4+
description: "An Eio implementation for most Unix-like platforms"
5+
maintainer: ["anil@recoil.org"]
6+
authors: ["Anil Madhavapeddy" "Thomas Leonard"]
7+
license: "ISC"
8+
homepage: "https://github.com/ocaml-multicore/eio"
9+
doc: "https://ocaml-multicore.github.io/eio/"
10+
bug-reports: "https://github.com/ocaml-multicore/eio/issues"
11+
depends: [
12+
"dune" {>= "3.0"}
13+
"eio" {= version}
14+
"iomux" {>= "0.2"}
15+
"mdx" {>= "1.10.0" & with-test}
16+
"fmt" {>= "0.8.9"}
17+
"odoc" {with-doc}
18+
]
19+
build: [
20+
["dune" "subst"] {dev}
21+
[
22+
"dune"
23+
"build"
24+
"-p"
25+
name
26+
"-j"
27+
jobs
28+
"@install"
29+
"@runtest" {with-test}
30+
"@doc" {with-doc}
31+
]
32+
]
33+
dev-repo: "git+https://github.com/ocaml-multicore/eio.git"

lib_eio_posix/domain_mgr.ml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
(*
2+
* Copyright (C) 2023 Thomas Leonard
3+
*
4+
* Permission to use, copy, modify, and distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*)
16+
17+
open Eio.Std
18+
19+
[@@@alert "-unstable"]
20+
21+
(* Run an event loop in the current domain, using [fn x] as the root fiber. *)
22+
let run_event_loop fn x =
23+
Sched.with_sched @@ fun sched ->
24+
let open Effect.Deep in
25+
let extra_effects : _ effect_handler = {
26+
effc = fun (type a) (e : a Effect.t) : ((a, Sched.exit) continuation -> Sched.exit) option ->
27+
match e with
28+
| Eio_unix.Private.Get_monotonic_clock -> Some (fun k -> continue k (Time.mono_clock : Eio.Time.Mono.t))
29+
| Eio_unix.Private.Socket_of_fd (sw, close_unix, fd) -> Some (fun k ->
30+
Unix.set_nonblock fd;
31+
let fd = Fd.of_unix ~sw ~blocking:false ~close_unix fd in
32+
continue k (Flow.of_fd fd :> Eio_unix.socket)
33+
)
34+
| Eio_unix.Private.Socketpair (sw, domain, ty, protocol) -> Some (fun k ->
35+
let a, b = Unix.socketpair ~cloexec:true domain ty protocol in
36+
Unix.set_nonblock a;
37+
Unix.set_nonblock b;
38+
let a = Fd.of_unix ~sw ~blocking:false ~close_unix:true a |> Flow.of_fd in
39+
let b = Fd.of_unix ~sw ~blocking:false ~close_unix:true b |> Flow.of_fd in
40+
continue k ((a :> Eio_unix.socket), (b :> Eio_unix.socket))
41+
)
42+
| Eio_unix.Private.Pipe sw -> Some (fun k ->
43+
let r, w = Unix.pipe ~cloexec:true () in
44+
(* See issue #319, PR #327 *)
45+
Unix.set_nonblock r;
46+
Unix.set_nonblock w;
47+
let make x = Flow.of_fd (Fd.of_unix ~sw ~blocking:false ~close_unix:true x) in
48+
let r = (make r :> <Eio.Flow.source; Eio.Flow.close; Eio_unix.unix_fd>) in
49+
let w = (make w :> <Eio.Flow.sink; Eio.Flow.close; Eio_unix.unix_fd>) in
50+
continue k (r, w)
51+
)
52+
| _ -> None
53+
}
54+
in
55+
Sched.run ~extra_effects sched fn x
56+
57+
let v = object
58+
inherit Eio.Domain_manager.t
59+
60+
method run_raw fn =
61+
let domain = ref None in
62+
Eio.Private.Suspend.enter (fun _ctx enqueue ->
63+
domain := Some (Domain.spawn (fun () -> Fun.protect fn ~finally:(fun () -> enqueue (Ok ()))))
64+
);
65+
Domain.join (Option.get !domain)
66+
67+
method run fn =
68+
let domain = ref None in
69+
Eio.Private.Suspend.enter (fun ctx enqueue ->
70+
let cancelled, set_cancelled = Promise.create () in
71+
Eio.Private.Fiber_context.set_cancel_fn ctx (Promise.resolve set_cancelled);
72+
domain := Some (Domain.spawn (fun () ->
73+
Fun.protect (run_event_loop (fun () -> fn ~cancelled))
74+
~finally:(fun () -> enqueue (Ok ()))))
75+
);
76+
Domain.join (Option.get !domain)
77+
end

lib_eio_posix/dune

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
(library
2+
(name eio_posix)
3+
(public_name eio_posix)
4+
(enabled_if (= %{os_type} "Unix"))
5+
(foreign_stubs
6+
(language c)
7+
(flags :standard -D_LARGEFILE64_SOURCE)
8+
(names eio_posix_stubs))
9+
(libraries eio eio.utils eio.unix fmt iomux))

lib_eio_posix/eio_posix.ml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
(*
2+
* Copyright (C) 2023 Thomas Leonard
3+
*
4+
* Permission to use, copy, modify, and distribute this software for any
5+
* purpose with or without fee is hereby granted, provided that the above
6+
* copyright notice and this permission notice appear in all copies.
7+
*
8+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15+
*)
16+
17+
module Low_level = Low_level
18+
19+
type stdenv = <
20+
stdin : <Eio.Flow.source; Eio_unix.unix_fd>;
21+
stdout : <Eio.Flow.sink; Eio_unix.unix_fd>;
22+
stderr : <Eio.Flow.sink; Eio_unix.unix_fd>;
23+
net : Eio.Net.t;
24+
domain_mgr : Eio.Domain_manager.t;
25+
clock : Eio.Time.clock;
26+
mono_clock : Eio.Time.Mono.t;
27+
fs : Eio.Fs.dir Eio.Path.t;
28+
cwd : Eio.Fs.dir Eio.Path.t;
29+
secure_random : Eio.Flow.source;
30+
debug : Eio.Debug.t;
31+
>
32+
33+
let run main =
34+
(* SIGPIPE makes no sense in a modern application. *)
35+
Sys.(set_signal sigpipe Signal_ignore);
36+
Domain_mgr.run_event_loop main @@ object (_ : stdenv)
37+
method stdin = (Flow.of_fd Low_level.Fd.stdin :> <Eio.Flow.source; Eio_unix.unix_fd>)
38+
method stdout = (Flow.of_fd Low_level.Fd.stdout :> <Eio.Flow.sink; Eio_unix.unix_fd>)
39+
method stderr = (Flow.of_fd Low_level.Fd.stderr :> <Eio.Flow.sink; Eio_unix.unix_fd>)
40+
method debug = Eio.Private.Debug.v
41+
method clock = Time.clock
42+
method mono_clock = Time.mono_clock
43+
method net = Net.v
44+
method domain_mgr = Domain_mgr.v
45+
method cwd = ((Fs.cwd, "") :> Eio.Fs.dir Eio.Path.t)
46+
method fs = ((Fs.fs, "") :> Eio.Fs.dir Eio.Path.t)
47+
method secure_random = Flow.secure_random
48+
end

lib_eio_posix/eio_posix.mli

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(** Fallback Eio backend for POSIX systems. *)
2+
3+
type stdenv = <
4+
stdin : <Eio.Flow.source; Eio_unix.unix_fd>;
5+
stdout : <Eio.Flow.sink; Eio_unix.unix_fd>;
6+
stderr : <Eio.Flow.sink; Eio_unix.unix_fd>;
7+
net : Eio.Net.t;
8+
domain_mgr : Eio.Domain_manager.t;
9+
clock : Eio.Time.clock;
10+
mono_clock : Eio.Time.Mono.t;
11+
fs : Eio.Fs.dir Eio.Path.t;
12+
cwd : Eio.Fs.dir Eio.Path.t;
13+
secure_random : Eio.Flow.source;
14+
debug : Eio.Debug.t;
15+
>
16+
(** An extended version of {!Eio.Stdenv.t} with some extra features available on POSIX systems. *)
17+
18+
val run : (stdenv -> 'a) -> 'a
19+
(** [run main] runs an event loop and calls [main stdenv] inside it.
20+
21+
For portable code, you should use {!Eio_main.run} instead, which will call this for you if appropriate. *)
22+
23+
module Low_level = Low_level
24+
(** Low-level API for making POSIX calls directly. *)

0 commit comments

Comments
 (0)