···11+(* cat(1) built with liburing.
22+ OCaml version of https://unixism.net/loti/tutorial/cat_liburing.html *)
33+44+let block_size = 1024
55+66+let get_file_size fd =
77+ Unix.handle_unix_error Unix.fstat fd |>
88+ fun {Unix.st_size; _} -> st_size
99+(* TODO make this work with ST_ISBLK *)
1010+1111+let get_completion_and_print uring =
1212+ let bufs, len = Uring.wait_cqe uring in
1313+ let remaining = ref len in
1414+ Printf.eprintf "%d bytes read\n%!" len;
1515+ Array.iter (fun buf ->
1616+ let buflen = Bigstringaf.length buf in
1717+ if !remaining > 0 then begin
1818+ if buflen <= !remaining then begin
1919+ print_string (Bigstringaf.to_string buf);
2020+ remaining := !remaining - buflen;
2121+ end else begin
2222+ print_string (Bigstringaf.substring ~off:0 ~len:!remaining buf);
2323+ remaining := 0;
2424+ end
2525+ end
2626+ ) bufs
2727+2828+let submit_read_request fname uring =
2929+ let fd = Unix.(handle_unix_error (openfile fname [O_RDONLY]) 0) in
3030+ let file_sz = get_file_size fd in
3131+ let blocks = if file_sz mod block_size <> 0 then (file_sz / block_size)+1 else file_sz/block_size in
3232+ let bufs = Array.init blocks (fun _ -> Uring.iobuf_alloc block_size) in
3333+ Uring.submit_readv uring fd bufs;
3434+ let numreq = Uring.submit uring in
3535+ assert(numreq=1);
3636+ ()
3737+3838+let () =
3939+ let fname = Sys.argv.(1) in
4040+ let uring = Uring.create ~queue_depth:1 () in
4141+ submit_read_request fname uring;
4242+ get_completion_and_print uring
4343+
+56-3
uring.ml
···11-type t
11+type uring
22+33+type iobuf = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
44+55+let iobuf_alloc len = Bigarray.(Array1.create char c_layout len)
66+77+(** [ring_setup i] allocates a new io_uring with queue depth [i].
88+ @raise [Failure] *)
99+external uring_create : int -> uring = "ocaml_uring_setup"
1010+external uring_exit : uring -> unit = "ocaml_uring_exit"
1111+(* external uring_register_bigarray : uring -> iobuf -> unit = "ocaml_uring_register_ba" *)
1212+external uring_submit : uring -> int = "ocaml_uring_submit"
1313+1414+type iovecs
1515+external uring_alloc_iovecs : iobuf array -> iovecs = "ocaml_uring_alloc_iovecs"
1616+external uring_free_iovecs : iovecs -> unit = "ocaml_uring_free_iovecs"
1717+1818+external uring_submit_readv : uring -> Unix.file_descr -> iovecs -> int -> unit = "ocaml_uring_submit_readv"
1919+external uring_wait_cqe : uring -> iovecs * int = "ocaml_uring_wait_cqe"
2020+2121+type t = {
2222+ uring: uring;
2323+ iobuf: iobuf;
2424+ pending: (iovecs, iobuf array) Hashtbl.t;
2525+}
2626+2727+let default_iobuf_len = 1024 * 1024 (* 1MB *)
2828+2929+let create ~queue_depth () =
3030+ let uring = uring_create queue_depth in
3131+ (* TODO posix memalign this to page *)
3232+ let iobuf = Bigarray.(Array1.create char c_layout default_iobuf_len) in
3333+ (* uring_register_bigarray uring iobuf; *)
3434+ Gc.finalise uring_exit uring;
3535+ let pending = Hashtbl.create 1 in
3636+ { uring; iobuf; pending }
3737+3838+let submit_readv {uring;pending;_} fd bufs =
3939+ let len = Array.length bufs in
4040+ let iovs = uring_alloc_iovecs bufs in
4141+ uring_submit_readv uring fd iovs len;
4242+ Hashtbl.add pending iovs bufs;
4343+ ()
4444+4545+let submit {uring;_} =
4646+ uring_submit uring
24733-external ring_setup : int -> t = "ring_setup"
4848+let wait_cqe {uring;pending;_} =
4949+ let iovecs, len = uring_wait_cqe uring in
5050+ let bas = Hashtbl.find pending iovecs in
5151+ uring_free_iovecs iovecs;
5252+ bas, len
5353+5454+5555+(*
456external ring_queue_write_full : t -> Unix.file_descr -> (Bigstringaf.t -> int -> unit) -> Bigstringaf.t -> int -> unit = "ring_queue_write_full"
557external ring_queue_read : t -> Unix.file_descr -> (Bigstringaf.t -> int -> unit) -> Bigstringaf.t -> int -> unit = "ring_queue_read"
658external ring_queue_accept : t -> Unix.file_descr -> (Unix.file_descr -> unit) -> unit = "ring_queue_accept"
759external ring_queue_close : t -> Unix.file_descr -> unit = "ring_queue_close"
860external ring_submit : t -> int = "ring_submit"
961external ring_exit : t -> unit = "ring_exit"
1010-external ring_wait : t -> unit = "ring_wait"6262+external ring_wait : t -> unit = "ring_wait"
6363+*)
+7-8
uring.mli
···11+12type t
33+type iobuf = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
2433-val ring_setup : int -> t
44-val ring_queue_write_full : t -> Unix.file_descr -> (Bigstringaf.t -> int -> unit) -> Bigstringaf.t -> int -> unit
55-val ring_queue_read : t -> Unix.file_descr -> (Bigstringaf.t -> int -> unit) -> Bigstringaf.t -> int -> unit
66-val ring_queue_accept : t -> Unix.file_descr -> (Unix.file_descr -> unit) -> unit
77-val ring_queue_close : t -> Unix.file_descr -> unit
88-val ring_submit : t -> int
99-val ring_exit : t -> unit
1010-val ring_wait : t -> unit55+val iobuf_alloc : int -> iobuf
66+val create : queue_depth:int -> unit -> t
77+val submit_readv : t -> Unix.file_descr -> iobuf array -> unit
88+val submit : t -> int
99+val wait_cqe : t -> iobuf array * int
···11-let ring = Uring.ring_setup 1024
11+let () =
22+ let t = Uring.create ~queue_depth:1 () in
33+ let fd = Unix.(handle_unix_error (openfile "test.txt" [O_RDONLY]) 0) in
44+ let b1 = Uring.iobuf_alloc 3 in
55+ let b2 = Uring.iobuf_alloc 5 in
66+ Uring.submit_readv t fd [|b1;b2|];
77+ let res = Uring.submit t in
88+ Printf.eprintf "submitted %d\n%!" res;
99+ let _,res = Uring.wait_cqe t in
1010+ Printf.eprintf "res %d\n%!" res;
1111+ Printf.eprintf "%s -- %s\n%!" (Bigstringaf.to_string b1) (Bigstringaf.to_string b2);
1212+ ()
2131414+(*
315let server_fd = Unix.socket PF_INET SOCK_STREAM 0
416517let client_fd = ref None
···1022 | Some(client) ->
1123 let exit_loop = ref false in
1224 let read_buf = Bigstringaf.create 4096 in
1313- Uring.ring_queue_read ring client (fun buf len ->
1414- if len == 0 then
2525+ Uring.ring_queue_read ring client (fun buf len ->
2626+ if len = 0 then
1527 begin
1628 Printf.printf "Client disconnected!";
1729 exit_loop := true
···3648 let (new_client_fd, _) = Unix.accept server_fd in
3749 Printf.printf "Go connection!\n%!";
3850 client_fd := Some(new_client_fd);
3939- server_loop ()5151+ server_loop ()
5252+ *)