Skip to content

Commit ff8ce45

Browse files
0.19.0 --- openkal.map: a part of a file in the address space, by mmap (#43)
The file's length and kind are read with fstat first: the kernel maps beyond a file's end and maps some devices, and the specification refuses both at the call. kal_map_sync is msync(MS_ASYNC), the visibility the specification asks for and not durability. No PROT_EXEC. Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent cde4abb commit ff8ce45

5 files changed

Lines changed: 75 additions & 7 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ for Linux, written on the kernel's own system-call interface.
88
openkal = "0.17.0"
99

1010
[target.'cfg(os = "linux")'.dependencies]
11-
openkal-linux = "0.18.3"
11+
openkal-linux = "0.19.0"
1212
```
1313

1414
## Why it does not use a C library

‎mcpp.toml‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
namespace = "mcpplibs"
33
name = "openkal-linux"
4-
version = "0.18.3"
4+
version = "0.19.0"
55
description = "The reference implementation of openkal for Linux, written on the kernel's own system-call interface so that it can be placed beneath a C library as well as above one."
66
license = "Apache-2.0"
77

@@ -60,10 +60,11 @@ provides-interfaces = [
6060
"openkal.datagram",
6161
"openkal.space",
6262
"openkal.timeout",
63+
"openkal.map",
6364
]
6465

6566
[dependencies]
66-
openkal = "0.17.1"
67+
openkal = "0.18.0"
6768

6869
# The package contributes definitions and no modules. The interface it
6970
# implements is declared by the specification package, which this package

‎src/map.cpp‎

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include "sys.h"
2+
#include "handle.h"
3+
#include <openkal/map.h>
4+
5+
// openkal.map on this kernel (openkal 0.18).
6+
//
7+
// One system call each way: mmap, msync, munmap. The region is the address the
8+
// kernel returned and the length the caller passed, so there is nothing to
9+
// record; a handle would have needed a table from handles to mappings, which
10+
// clause 7.1 excludes.
11+
//
12+
// THE FILE'S LENGTH IS ASKED FIRST. The kernel maps beyond the end of a file
13+
// and lets an access there fault; the specification refuses such a region at
14+
// the call (map.h), so the length is read with fstat and compared. The same
15+
// fstat says whether the file is a regular one: the kernel maps some devices,
16+
// and a device's contents are not a file's.
17+
//
18+
// NO PROT_EXEC. Instructions run only from memory openkal.exec published.
19+
20+
extern "C" {
21+
22+
int kal_map_file(kal_file f, kal_u64 offset, kal_uintptr length, kal_uintptr how, void** out) {
23+
if (out == nullptr) return kal_err_invalid;
24+
*out = nullptr;
25+
const int fd = okl::unpack(f.h);
26+
if (fd < 0 || length == 0 || offset % KAL_MAP_ALIGNMENT != 0
27+
|| (how & ~(KAL_MAP_WRITE | KAL_MAP_SHARED)) != 0)
28+
return kal_err_invalid;
29+
okl::kstat st{};
30+
const okl_long s = okl::sys(okl::nr_fstat, fd, reinterpret_cast<okl_long>(&st));
31+
if (okl::failed(s)) return okl::translate(s);
32+
if ((st.mode & okl::s_ifmt) != okl::s_ifreg) return kal_err_not_supported;
33+
const kal_u64 size = st.size > 0 ? static_cast<kal_u64>(st.size) : 0;
34+
if (offset > size || static_cast<kal_u64>(length) > size - offset) return kal_err_invalid;
35+
const okl_long prot = okl::prot_read | ((how & KAL_MAP_WRITE) ? okl::prot_write : 0);
36+
const okl_long flags = (how & KAL_MAP_SHARED) ? okl::map_shared : okl::map_private;
37+
const okl_long r = okl::sys(okl::nr_mmap, 0, static_cast<okl_long>(length), prot, flags, fd,
38+
static_cast<okl_long>(offset));
39+
if (okl::failed(r)) {
40+
// ENODEV: the file system does not map. The resource, not the
41+
// implementation, refuses (map.h).
42+
if (-r == okl::e_nodev) return kal_err_not_supported;
43+
return okl::translate(r);
44+
}
45+
*out = reinterpret_cast<void*>(r);
46+
return kal_ok;
47+
}
48+
49+
int kal_map_sync(void* region, kal_uintptr length) {
50+
if (region == nullptr || length == 0) return kal_err_invalid;
51+
// MS_ASYNC: a shared mapping is the page cache, which a read of the file
52+
// already reads; what the specification asks of this call is that
53+
// visibility, not durability, and asking for durability here would make
54+
// every caller wait for the medium.
55+
const okl_long r = okl::sys(okl::nr_msync, reinterpret_cast<okl_long>(region),
56+
static_cast<okl_long>(length), okl::ms_async);
57+
return okl::failed(r) ? okl::translate(r) : kal_ok;
58+
}
59+
60+
void kal_map_release(void* region, kal_uintptr length) {
61+
if (region == nullptr || length == 0) return;
62+
(void)okl::sys(okl::nr_munmap, reinterpret_cast<okl_long>(region), static_cast<okl_long>(length));
63+
}
64+
65+
}

‎src/sys.h‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ inline okl_long sys(okl_long n, okl_long a, okl_long b, okl_long c, okl_long d,
9595

9696
enum : okl_long {
9797
nr_read = 0, nr_write = 1, nr_close = 3, nr_fstat = 5, nr_lseek = 8,
98-
nr_mmap = 9, nr_mprotect = 10, nr_munmap = 11, nr_ioctl = 16,
98+
nr_mmap = 9, nr_mprotect = 10, nr_munmap = 11, nr_ioctl = 16, nr_msync = 26,
9999
nr_readv = 19, nr_writev = 20, nr_sched_yield = 24, nr_nanosleep = 35,
100100
nr_getpid = 39, nr_clone = 56, nr_execve = 59, nr_exit = 60, nr_wait4 = 61,
101101
nr_kill = 62, nr_ftruncate = 77, nr_getcwd = 79, nr_fsync = 74,
@@ -197,7 +197,7 @@ enum : okl_long {
197197
nr_exit = 93, nr_exit_group = 94, nr_set_tid_address = 96, nr_futex = 98,
198198
nr_nanosleep = 101, nr_clock_gettime = 113, nr_clock_getres = 114,
199199
nr_sched_yield = 124, nr_kill = 129, nr_tgkill = 131, nr_gettid = 178,
200-
nr_getpid = 172, nr_mmap = 222, nr_munmap = 215, nr_mprotect = 226,
200+
nr_getpid = 172, nr_mmap = 222, nr_munmap = 215, nr_mprotect = 226, nr_msync = 227,
201201
nr_clone = 220, nr_execve = 221, nr_wait4 = 260, nr_renameat = 38,
202202
nr_dup3 = 24, nr_execveat = 281,
203203
nr_close_range = 436, nr_prlimit64 = 261, nr_dup2 = -1, nr_fcntl = 25,
@@ -323,7 +323,8 @@ enum : okl_long {
323323
#endif
324324
at_fdcwd = -100, at_removedir = 0x200, at_symlink_nofollow = 0x100,
325325
prot_read = 1, prot_write = 2, prot_exec = 4, prot_none = 0,
326-
map_private = 2, map_anonymous = 0x20, map_stack = 0x20000,
326+
map_shared = 1, map_private = 2, map_anonymous = 0x20, map_stack = 0x20000,
327+
ms_async = 1,
327328
clock_monotonic = 1, clock_realtime = 0,
328329
futex_wait = 0, futex_wake = 1, futex_private = 128,
329330
};

‎src/version.cpp‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ kal_u64 kal_interfaces(void) {
2323
| KAL_IFACE_ENV | KAL_IFACE_TIME | KAL_IFACE_RANDOM
2424
| KAL_IFACE_FS | KAL_IFACE_PROCESS | KAL_IFACE_TASK
2525
| KAL_IFACE_EXEC | KAL_IFACE_TERMINAL | KAL_IFACE_NET
26-
| KAL_IFACE_DATAGRAM | KAL_IFACE_SPACE | KAL_IFACE_TIMEOUT;
26+
| KAL_IFACE_DATAGRAM | KAL_IFACE_SPACE | KAL_IFACE_TIMEOUT
27+
| KAL_IFACE_MAP;
2728
}
2829

2930
}

0 commit comments

Comments
 (0)