Skip to content

Commit b5bac27

Browse files
committed
Merge pull request 'Improvement' (#9) from with-trim-malloc into main
Reviewed-on: https://git.robur.coop/robur/mkernel/pulls/9
2 parents f03f032 + 01033d9 commit b5bac27

File tree

5 files changed

+51
-22
lines changed

5 files changed

+51
-22
lines changed

dune-workspace

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
(host default)
66
(toolchain solo5)
77
(disable_dynamically_linked_foreign_archives true)))
8-
(context (default
9-
(name unikraft)
10-
(host default)
11-
(toolchain unikraft)
12-
(disable_dynamically_linked_foreign_archives true)))
8+
; (context (default
9+
; (name unikraft)
10+
; (host default)
11+
; (toolchain unikraft)
12+
; (disable_dynamically_linked_foreign_archives true)))

lib/mkernel.mli

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@
9292
to understand how reading and writing behave when developing an application
9393
as a unikernel using Solo5/Unikraft.
9494
95-
Writing a packet to the net interface is direct and failsafe. In other
95+
Writing a packet to the net interface is {b direct} and failsafe. In other
9696
words, we don't need to wait for anything to happen before writing to the
9797
net device (if an error occurs on your host system, the tender will fail —
9898
and by extension, so will your unikernel). So, from the scheduler's point of
@@ -187,14 +187,32 @@ module Net : sig
187187
@raise Invalid_argument
188188
if [off] and [len] do not designate a valid range of [bstr]. *)
189189

190+
(** {4 Writing to a net device according to the backend.}
191+
192+
Depending on the backend used (Solo5/hvt or Unikraft & Solo5/virtio),
193+
writing to a TAP interface may involve an intermediate "queue" between the
194+
unikernel (which fills this queue) and the tender (which consumes this
195+
queue). This feature allows for a process on the tender side that attempts
196+
to write without interruption (and thus improves performance).
197+
198+
In this case, unlike Solo5/hvt, writing is not necessarily effective
199+
between the unikernel and the TAP interface. However, this effectiveness
200+
also involves the tender's point of view, which is not taken into account
201+
(deliberately) in this documentation.
202+
203+
Furthermore, from the point of view of the unikernel, OCaml and Miou (and
204+
only on that side), the write is effective. *)
205+
190206
val write_bigstring : t -> ?off:int -> ?len:int -> bigstring -> unit
191207
(** [write_bigstring t ?off ?len bstr] writes [len] (defaults to
192208
[Bigarray.Array1.dim bstr - off]) bytes to the net device [t], taking them
193209
from byte sequence [bstr], starting at position [off] (defaults to [0]) in
194210
[bstr].
195211
196-
[write_bigstring] is currently writing directly to the net device [t].
197-
Writing cannot fail.
212+
[write_bigstring] is currently writing directly to the net device [t]. In
213+
other words, the write is effective and does not give the scheduler the
214+
opportunity to execute another task during the write. It is therefore an
215+
atomic operation. Writing cannot fail.
198216
199217
@raise Invalid_argument
200218
if [off] and [len] do not designate a valid range of [bstr]. *)
@@ -207,7 +225,11 @@ module Net : sig
207225
to write a new Ethernet frame. In the case of Unikraft, for example, we
208226
need to allocate a buffer that will be added to Unikraft's internal queue
209227
so that it can be written to the TAP interface. The same applies to Solo5
210-
and its virtio support.
228+
and its {i virtio} support.
229+
230+
[write_into] has the same characteristic as {!val:write_bigstring}, i.e.
231+
it is an atomic operation that does not give the scheduler the opportunity
232+
to execute another task.
211233
212234
In this specific case, [write_into] is more useful than
213235
{!val:write_bigstring} because it prepares the allocation and lets the

lib/mkernel.solo5.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ external miou_solo5_block_write :
8989
-> (int[@untagged]) = "unimplemented" "miou_solo5_block_write"
9090
[@@noalloc]
9191

92+
external miou_solo5_malloc_trim :
93+
unit
94+
-> bool = "unimplemented" "miou_solo5_malloc_trim"
95+
[@@noalloc]
96+
9297
(* End of the unsafe part. Come back to the OCaml world! *)
9398

9499
external unsafe_get_int64_ne : bytes -> int -> int64 = "%caml_bytes_get64u"
@@ -576,8 +581,16 @@ and go : type k res. ((unit -> res) -> res) -> (k, res) devices -> k -> res =
576581
let r = f v in
577582
go run devices r
578583

584+
let trim () =
585+
Gc.compact ();
586+
let trimmed = miou_solo5_malloc_trim () in
587+
Log.debug (fun m -> m "dlmalloc trimmed: %b" trimmed)
588+
579589
let run ?now:clock ?g devices fn =
580590
Option.iter (fun fn -> now := fn) clock;
591+
let alarm = Gc.create_alarm trim in
592+
let finally () = Gc.delete_alarm alarm in
593+
Fun.protect ~finally @@ fun () ->
581594
Miou.run ~events ~domains:0 ?g @@ fun () ->
582595
let run fn = fn () in
583596
go run devices fn

lib/stubs.solo5.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ intnat miou_solo5_clock_monotonic(__unit()) {
135135

136136
intnat miou_solo5_clock_wall(__unit()) { return (solo5_clock_wall()); }
137137

138+
extern int malloc_trim(size_t);
139+
140+
CAMLprim value
141+
miou_solo5_malloc_trim(__unit()) {
142+
return (Val_bool(malloc_trim(0)));
143+
}
144+
138145
extern void _nolibc_init(uintptr_t, size_t);
139146

140147
static char *strdup(const char *s) {

mkernel.opam

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,7 @@ depends: [
2222
"ohex"
2323
"jsonm"
2424
"ocaml-solo5"
25-
"ocaml-unikraft"
2625
"hxd" {with-test}
2726
"fmt" {with-test}
2827
"cachet" {with-test}
2928
]
30-
31-
pin-depends: [
32-
[ "ocaml-unikraft.1.0.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
33-
[ "ocaml-unikraft-x86_64.1.0.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
34-
[ "ocaml-unikraft-toolchain-x86_64.0.18.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
35-
[ "ocaml-unikraft-default-x86_64.1.0.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
36-
[ "ocaml-unikraft-arm64.1.0.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
37-
[ "ocaml-unikraft-default-arm64.1.0.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
38-
[ "ocaml-unikraft-toolchain-arm64.0.18.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
39-
[ "ocaml-unikraft-backend-qemu.0.18.0" "git+https://github.com/mirage/ocaml-unikraft.git#9becd4cae4612f5250753eae896b3e173108ab0f" ]
40-
[ "ocaml-solo5.1.1.0" "git+https://github.com/mirage/ocaml-solo5.git#c8a95779da6c0e444d4606d6d001098fc00d4b2d" ]
41-
]

0 commit comments

Comments
 (0)