···2233let () =
44 C.main ~name:"discover" (fun c ->
55- C.C_define.import c ~c_flags:["-D_GNU_SOURCE"] ~includes:["fcntl.h"; "poll.h"; "sys/uio.h"] C.C_define.Type.[
55+ C.C_define.import c ~c_flags:["-D_GNU_SOURCE"]
66+ ~includes:["fcntl.h"; "poll.h"; "sys/uio.h"; "linux/time_types.h"]
77+ C.C_define.Type.[
68 "POLLIN", Int;
79 "POLLOUT", Int;
810 "POLLERR", Int;
···3133 "AT_FDCWD", Int;
32343335 "sizeof(struct iovec)", Int;
3636+ "sizeof(struct __kernel_timespec)", Int;
3437 ]
3538 |> List.map (function
3639 | name, C.C_define.Value.Int v ->
3737- let name = if name = "sizeof(struct iovec)" then "sizeof_iovec" else name in
4040+ let name =
4141+ match name with
4242+ | "sizeof(struct iovec)" -> "sizeof_iovec"
4343+ | "sizeof(struct __kernel_timespec)" -> "sizeof_kernel_timespec"
4444+ | nm -> nm
4545+ in
3846 Printf.sprintf "let %s = 0x%x" (String.lowercase_ascii name) v
3947 | _ -> assert false
4048 )
+10
lib/uring/uring.ml
···197197198198type 'a job = 'a Heap.entry
199199200200+type clock = Boottime | Realtime
201201+200202module Uring = struct
201203 type t
202204···212214213215 type offset = Optint.Int63.t
214216 external submit_nop : t -> id -> bool = "ocaml_uring_submit_nop" [@@noalloc]
217217+ external submit_timeout : t -> id -> Sketch.ptr -> clock -> bool -> bool = "ocaml_uring_submit_timeout" [@@noalloc]
215218 external submit_poll_add : t -> Unix.file_descr -> id -> Poll_mask.t -> bool = "ocaml_uring_submit_poll_add" [@@noalloc]
216219 external submit_read : t -> Unix.file_descr -> id -> Cstruct.t -> offset -> bool = "ocaml_uring_submit_read" [@@noalloc]
217220 external submit_write : t -> Unix.file_descr -> id -> Cstruct.t -> offset -> bool = "ocaml_uring_submit_write" [@@noalloc]
···336339337340let noop t user_data =
338341 with_id t (fun id -> Uring.submit_nop t.uring id) user_data
342342+343343+external set_timespec: Sketch.ptr -> int64 -> unit = "ocaml_uring_set_timespec" [@@noalloc]
344344+345345+let timeout ?(absolute = false) t clock timeout_ns user_data =
346346+ let timespec_ptr = Sketch.alloc t.sketch Config.sizeof_kernel_timespec in
347347+ set_timespec timespec_ptr timeout_ns;
348348+ with_id t (fun id -> Uring.submit_timeout t.uring id timespec_ptr clock absolute) user_data
339349340350let at_fdcwd : Unix.file_descr = Obj.magic Config.at_fdcwd
341351
+13
lib/uring/uring.mli
···6767(** [noop t d] submits a no-op operation to uring [t]. The user data [d] will be
6868 returned by {!wait} or {!peek} upon completion. *)
69697070+(** {2 Timeout} *)
7171+7272+type clock = Boottime | Realtime
7373+(** Represents Linux clocks. [Boottime] and [Realtime] represents OS clocks CLOCK_BOOTTIME
7474+ and CLOCK_REALTIME respectively. *)
7575+7676+val timeout: ?absolute:bool -> 'a t -> clock -> int64 -> 'a -> 'a job option
7777+(** [timeout t clock ns d] submits a timeout request to uring [t].
7878+7979+ [absolute] denotes how [clock] and [ns] relate to one another. Default value is [false]
8080+8181+ [ns] is the timeout time in nanoseconds *)
8282+7083module type FLAGS = sig
7184 type t = private int
7285 (** A set of flags. *)
+35-3
lib/uring/uring_stubs.c
···4949#endif
50505151#define Ring_val(v) *((struct io_uring**)Data_custom_val(v))
5252+#define Sketch_ptr_val(vsp) (Caml_ba_data_val(Field(vsp, 0)) + Long_val(Field(vsp, 1)))
5353+#define Sketch_ptr_len_val(vsp) Long_val(Field(vsp, 2))
52545355// Note that this does not free the ring data. You must not allow this to be
5456// GC'd until the ring has been released by calling ocaml_uring_exit.
···146148 return (Val_int(io_uring_sq_ready(ring)));
147149}
148150151151+void /* noalloc */
152152+ocaml_uring_set_timespec(value v_sketch_ptr, value v_timeout)
153153+{
154154+ struct __kernel_timespec *t = Sketch_ptr_val(v_sketch_ptr);
155155+ t->tv_sec = 0;
156156+ t->tv_nsec = Int64_val(v_timeout);
157157+}
158158+159159+#define Val_boottime Val_int(0)
160160+161161+value /* noalloc */
162162+ocaml_uring_submit_timeout(value v_uring, value v_id, value v_sketch_ptr, value v_clock, value v_absolute)
163163+{
164164+ struct __kernel_timespec *t = Sketch_ptr_val(v_sketch_ptr);
165165+ struct io_uring* ring = Ring_val(v_uring);
166166+ struct io_uring_sqe* sqe;
167167+ int flags;
168168+169169+ if (v_clock == Val_boottime)
170170+ flags = IORING_TIMEOUT_BOOTTIME;
171171+ else
172172+ flags = IORING_TIMEOUT_REALTIME;
173173+174174+ if(Bool_val(v_absolute))
175175+ flags |= IORING_TIMEOUT_ABS;
176176+177177+ sqe = io_uring_get_sqe(ring);
178178+ if (!sqe) return Val_false;
179179+ io_uring_prep_timeout(sqe, t, 0, flags);
180180+ io_uring_sqe_set_data(sqe, (void *)Long_val(v_id));
181181+ return Val_true;
182182+}
183183+149184struct open_how_data {
150185 struct open_how how;
151186 char path[];
···223258 io_uring_sqe_set_data(sqe, (void *)Long_val(v_id));
224259 return (Val_true);
225260}
226226-227227-#define Sketch_ptr_val(vsp) (Caml_ba_data_val(Field(vsp, 0)) + Long_val(Field(vsp, 1)))
228228-#define Sketch_ptr_len_val(vsp) Long_val(Field(vsp, 2))
229261230262void /* noalloc */
231263ocaml_uring_set_iovec(value v_sketch_ptr, value v_csl)
+39
tests/main.md
···776776# Uring.exit t;;
777777- : unit = ()
778778```
779779+780780+## Timeout
781781+782782+Timeout should return (-ETIME). This is defined in https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/errno.h#L45
783783+784784+```ocaml
785785+# let t = Uring.create ~queue_depth:1 ();;
786786+val t : '_weak13 Uring.t = <abstr>
787787+788788+# let ns1 = Int64.(mul 10L 1_000_000L) in
789789+ Uring.(timeout t Boottime ns1 `Timeout);;
790790+- : _[> `Timeout ] Uring.job option = Some <abstr>
791791+792792+# Uring.submit t;;
793793+- : int = 1
794794+795795+# let `Timeout, timeout = consume t;;
796796+val timeout : int = -62
797797+798798+# let ns =
799799+ ((Unix.gettimeofday () +. 0.01) *. 1e9)
800800+ |> Int64.of_float
801801+ in
802802+ Uring.(timeout ~absolute:true t Realtime ns `Timeout);;
803803+- : [ `Timeout ] Uring.job option = Some <abstr>
804804+805805+# let `Timeout, timeout = consume t;;
806806+val timeout : int = -62
807807+808808+# let ns1 = Int64.(mul 10L 1_000_000L) in
809809+ Uring.(timeout ~absolute:true t Boottime ns1 `Timeout);;
810810+- : [ `Timeout ] Uring.job option = Some <abstr>
811811+812812+# let `Timeout, timeout = consume t;;
813813+val timeout : int = -62
814814+815815+# Uring.exit t;;
816816+- : unit = ()
817817+```