Skip to content

Commit 6778624

Browse files
committed
Adds support for interacting with devices on macOS
Block devices currently did not work on macOS, due to a bug that prevents poll(2) from working with block devices. This fixes that by creating a new thread that monitors block devices using select(2). The thread is created the first time a user computation attempts to read or write to a block devices. The implementation of the new select manager is in select.ml Additionally, the select manager also needed an eventfd system. The eventfd system from sched.ml was refactoring into a re-usable model that encapsulates some of the internal state in posix_eventfd.ml.
1 parent c44ee5c commit 6778624

File tree

7 files changed

+419
-81
lines changed

7 files changed

+419
-81
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(timeout 3 sh:*)",
5+
"Bash(timeout 5 sh:*)",
6+
"Bash(dune build:*)"
7+
]
8+
}
9+
}

lib_eio_posix/posix_eventfd.ml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
(*
2+
* Copyright (C) 2025 Aaron Eline
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+
module Rcfd = Eio_unix.Private.Rcfd
17+
18+
module Writer = struct
19+
type t = Rcfd.t
20+
let wake_buffer = Bytes.of_string "!"
21+
let wakeup t =
22+
Rcfd.use t
23+
~if_closed:ignore
24+
(fun fd ->
25+
try
26+
ignore (Unix.single_write fd wake_buffer 0 1)
27+
with
28+
(* If the pipe is full then a wake up is pending anyway. *)
29+
| Unix.Unix_error ((Unix.EACCES | EWOULDBLOCK), _, _) -> ()
30+
(* We're shutting down; the event has already been processed. *)
31+
| Unix.Unix_error (Unix.EPIPE, _, _) -> ()
32+
)
33+
end
34+
35+
module Owner = struct
36+
type t = {
37+
read : Unix.file_descr;
38+
write : Rcfd.t;
39+
}
40+
41+
let is_reader fd t = fd = t.read
42+
43+
let reader_fd t = t.read
44+
45+
let create_writer t = t.write
46+
47+
let clear t =
48+
let buf = Bytes.create 8 in
49+
let got = Unix.read t.read buf 0 (Bytes.length buf) in
50+
assert (got > 0)
51+
52+
let create () =
53+
let read, write = Unix.pipe ~cloexec:true () in
54+
Unix.set_nonblock read;
55+
Unix.set_nonblock write;
56+
let write = Rcfd.make write in
57+
{
58+
read; write
59+
}
60+
61+
let cleanup t =
62+
Unix.close t.read;
63+
let was_open = Rcfd.close t.write in
64+
assert was_open
65+
66+
end

lib_eio_posix/posix_eventfd.mli

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
(*
2+
* Copyright (C) 2025 Aaron Eline
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+
(**
18+
This module implements a thread safe re-usable abstraction for POSIX compliant eventfds.
19+
Eventfds are backed by a pipe.
20+
*)
21+
22+
(**
23+
The [Writer] module is the writing end of the eventfd.
24+
Having a [Writer.t] allows you to signal to the holder of the owner to wake up
25+
It is safe to share between threads
26+
*)
27+
module Writer :
28+
sig type t
29+
30+
(** Signal to the owning thread to wake up *)
31+
val wakeup : t -> unit
32+
end
33+
34+
(**
35+
The [Owner] module is the reading end of the event fd.
36+
It is not safe to share between threads.
37+
Anyone who holds a [Writer.t] can send wake up signals to an [Owner.t]
38+
*)
39+
module Owner :
40+
sig
41+
type t
42+
43+
(** Check if a given fd is the read end of the event fd *)
44+
val is_reader : Unix.file_descr -> t -> bool
45+
46+
(** @return the reading fd of the eventfd. This is not safe to share between threads. *)
47+
val reader_fd : t -> Unix.file_descr
48+
49+
(** Get a view into the write end of the event fd.
50+
@return the writing end. Safe to share between threads. *)
51+
val create_writer : t -> Writer.t
52+
53+
(** Clear pending events from the event fd *)
54+
val clear : t -> unit
55+
56+
(** @return a new eventfd owner *)
57+
val create : unit -> t
58+
59+
(** Close the file descriptors associated with the eventfd *)
60+
val cleanup : t -> unit
61+
end

0 commit comments

Comments
 (0)