Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,21 @@ jobs:
# fails to compile and the diagnostic names it.
list="$(grep -vE '^[[:space:]]*(#|$)' .spec/SURFACE.txt | sort -u)"
{
for m in types abort stream memory env time fs process task; do
# ⚠️ THE MODULE LIST IS DERIVED, NOT WRITTEN OUT.
#
# It used to be written out, and it fell out of step the first time
# the specification gained an interface: SURFACE.txt listed four
# `kal_exec_*' names, no `import openkal.exec' was emitted, and the
# generated test failed with four undeclared identifiers --- which
# names the symptom (a name is missing) and not the cause (a list
# here was not updated).
#
# SURFACE.txt groups its names under `# openkal.<interface>'
# headings, so the list it already carries is the list this needs.
# `types' is not a group there --- it declares no kal_ name --- and
# is therefore named separately.
echo "import openkal.types;"
for m in $(grep -oE '^# openkal\.[a-z]+' .spec/SURFACE.txt | cut -d. -f2); do
echo "import openkal.$m;"
done
echo 'const void *const surface[] = {'
Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = ["mcpplibs"]
repo = "https://github.com/mcpplibs/openkal-linux"

[dependencies]
openkal = "0.5.2"
openkal = { git = "https://github.com/mcpplibs/openkal", branch = "feat/openkal-closure" }

# The package contributes definitions and no modules. The interface it
# implements is declared by the specification package, which this package
Expand Down
61 changes: 61 additions & 0 deletions src/exec.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include "sys.h"
#include <openkal/exec.h>

// openkal.exec on this kernel.
//
// A mapping obtained writable and made executable afterwards. The kernel places
// no condition upon either step, so this implementation provides the interface
// unconditionally --- unlike one of the other systems, where the same interface
// is available only to a program produced in a particular way, which clause 6.5
// covers and which is not this system's case.
//
// The reservation is not made executable at the outset even though this kernel
// would permit it. Two of the three environments the specification targets
// refuse a mapping that is both, so an implementation that returned one here
// would be offering a program a shape it could not use elsewhere --- and the
// program would discover that only on the other system. The interface states
// the narrower contract and this implementation keeps to it.

namespace {

constexpr okl_uptr kPage = 4096;

okl_uptr round_up(okl_uptr n, okl_uptr to) { return (n + to - 1) & ~(to - 1); }

} // namespace

extern "C" {

void* kal_exec_alloc(kal_uintptr size) {
if (size == 0) return nullptr;
const okl_uptr bytes = round_up(static_cast<okl_uptr>(size), kPage);
const okl_long r = okl::sys(okl::nr_mmap, 0, static_cast<okl_long>(bytes),
okl::prot_read | okl::prot_write,
okl::map_private | okl::map_anonymous, -1, 0);
if (okl::failed(r)) return nullptr;
return reinterpret_cast<void*>(r);
}

int kal_exec_publish(void* p, kal_uintptr size) {
if (p == nullptr || size == 0) return kal_err_invalid;
const okl_uptr bytes = round_up(static_cast<okl_uptr>(size), kPage);
const okl_long r = okl::sys(okl::nr_mprotect, reinterpret_cast<okl_long>(p),
static_cast<okl_long>(bytes),
okl::prot_read | okl::prot_exec);
if (okl::failed(r)) return okl::translate(r);
return kal_ok;
}

void kal_exec_free(void* p, kal_uintptr size) {
if (p == nullptr || size == 0) return;
const okl_uptr bytes = round_up(static_cast<okl_uptr>(size), kPage);
okl::sys(okl::nr_munmap, reinterpret_cast<okl_long>(p),
static_cast<okl_long>(bytes));
}

// A published region may be reserved for writing again: this kernel's
// protection call is not one-way. The position is set accordingly, and a
// caller that must change published bytes need not abandon the region.
const kal_uintptr kal_exec_props = KAL_EXEC_PROP_REPUBLISH;

} // extern "C"
2 changes: 1 addition & 1 deletion src/sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ enum : okl_long {
o_creat = 0100, o_excl = 0200, o_trunc = 01000, o_append = 02000,
o_directory = 0200000, o_cloexec = 02000000, o_nofollow = 0400000,
at_fdcwd = -100, at_removedir = 0x200, at_symlink_nofollow = 0x100,
prot_read = 1, prot_write = 2, prot_none = 0,
prot_read = 1, prot_write = 2, prot_exec = 4, prot_none = 0,
map_private = 2, map_anonymous = 0x20, map_stack = 0x20000,
clock_monotonic = 1, clock_realtime = 0,
futex_wait = 0, futex_wake = 1, futex_private = 128,
Expand Down
Loading