This also handles mmap errors better by using the `uerror` helper
to raise a proper exception using `errno`.
Changed type of `len` from `int` to `size_t`: at construction time we
ensure the length is >= 0, so we can reflect this by using an unsigned
type. The type is unsigned at the C API level, and a negative integer
would just get translated to a very large unsigned number otherwise.
mmap also takes off_t and size_t, so using int64 would be more generic
here, however we only ever use this interface to map rings, so keeping
the `int` sizes is fine.
OCaml itself only uses `ints` for mapping bigarrays, and int64 for just
the offset.
Signed-off-by: Edwin Török <edvin.torok@citrix.com>
---
tools/ocaml/libs/mmap/mmap_stubs.h | 4 +++-
tools/ocaml/libs/mmap/xenmmap_stubs.c | 31 +++++++++++++++++----------
2 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/tools/ocaml/libs/mmap/mmap_stubs.h b/tools/ocaml/libs/mmap/mmap_stubs.h
index 816ba6a724..3352594e38 100644
--- a/tools/ocaml/libs/mmap/mmap_stubs.h
+++ b/tools/ocaml/libs/mmap/mmap_stubs.h
@@ -27,7 +27,7 @@
struct mmap_interface
{
void *addr;
- int len;
+ size_t len;
};
#ifndef Data_abstract_val
@@ -37,4 +37,6 @@ struct mmap_interface
#define Intf_val(a) ((struct mmap_interface *) Data_abstract_val(a))
#define Intf_data_val(a) (Intf_val(a)->addr)
+value stub_mmap_alloc(void *addr, size_t len);
+
#endif
diff --git a/tools/ocaml/libs/mmap/xenmmap_stubs.c b/tools/ocaml/libs/mmap/xenmmap_stubs.c
index 4d09c5a6e6..d7a97c76f5 100644
--- a/tools/ocaml/libs/mmap/xenmmap_stubs.c
+++ b/tools/ocaml/libs/mmap/xenmmap_stubs.c
@@ -27,16 +27,18 @@
#include <caml/custom.h>
#include <caml/fail.h>
#include <caml/callback.h>
+#include <caml/unixsupport.h>
#define Wsize_bsize_round(n) (Wsize_bsize( (n) + sizeof(value) - 1 ))
-static int mmap_interface_init(struct mmap_interface *intf,
- int fd, int pflag, int mflag,
- int len, int offset)
+value stub_mmap_alloc(void *addr, size_t len)
{
- intf->len = len;
- intf->addr = mmap(NULL, len, pflag, mflag, fd, offset);
- return (intf->addr == MAP_FAILED) ? errno : 0;
+ CAMLparam0();
+ CAMLlocal1(result);
+ result = caml_alloc(Wsize_bsize_round(sizeof(struct mmap_interface)), Abstract_tag);
+ Intf_val(result)->addr = addr;
+ Intf_val(result)->len = len;
+ CAMLreturn(result);
}
CAMLprim value stub_mmap_init(value fd, value pflag, value mflag,
@@ -45,6 +47,8 @@ CAMLprim value stub_mmap_init(value fd, value pflag, value mflag,
CAMLparam5(fd, pflag, mflag, len, offset);
CAMLlocal1(result);
int c_pflag, c_mflag;
+ void* addr;
+ size_t length;
switch (Int_val(pflag)) {
case 0: c_pflag = PROT_READ; break;
@@ -59,12 +63,17 @@ CAMLprim value stub_mmap_init(value fd, value pflag, value mflag,
default: caml_invalid_argument("maptype");
}
- result = caml_alloc(Wsize_bsize_round(sizeof(struct mmap_interface)), Abstract_tag);
+ if (Int_val(len) < 0)
+ caml_invalid_argument("negative size");
+ if (Int_val(offset) < 0)
+ caml_invalid_argument("negative offset");
+ length = Int_val(len);
- if (mmap_interface_init(Intf_val(result), Int_val(fd),
- c_pflag, c_mflag,
- Int_val(len), Int_val(offset)))
- caml_failwith("mmap");
+ addr = mmap(NULL, length, c_pflag, c_mflag, Int_val(fd), Int_val(offset));
+ if (MAP_FAILED == addr)
+ uerror("mmap", Nothing);
+
+ result = stub_mmap_alloc(addr, length);
CAMLreturn(result);
}
--
2.25.1