Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ for Linux, written on the kernel's own system-call interface.
openkal = "0.17.0"

[target.'cfg(os = "linux")'.dependencies]
openkal-linux = "0.18.1"
openkal-linux = "0.18.2"
```

## Why it does not use a C library
Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
namespace = "mcpplibs"
name = "openkal-linux"
version = "0.18.1"
version = "0.18.2"
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."
license = "Apache-2.0"

Expand Down
6 changes: 5 additions & 1 deletion src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -929,8 +929,12 @@ void stop_handler(int signo) {
__atomic_compare_exchange_n(&g_stop_signal, &none, signo, false,
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
__atomic_store_n(&g_stop_word, 1u, __ATOMIC_RELEASE);
// PRIVATE, AS `kal_task_wait' WAITS (0.18.2). The kernel keys a private
// futex apart from a shared one at the same address, so a shared wake
// reached no context waiting through `kal_task_wait' with no bound, and a
// program that waits for its end to be requested never ended.
okl::sys(okl::nr_futex, reinterpret_cast<okl_long>(&g_stop_word),
1 /* FUTEX_WAKE */, 0x7fffffff, 0, 0, 0);
okl::futex_wake | okl::futex_private, 0x7fffffff, 0, 0, 0);
}

// THE RESULT IS EXAMINED, AND IT WAS NOT WHEN THIS SHIPPED IN 0.11. An
Expand Down
42 changes: 40 additions & 2 deletions tests/stop_word_take_over.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
// The stop word, taken over and given back (openkal 0.17, process.h; K1, K2).
//
// Three facts, each of which this implementation got wrong before 0.18:
// Four facts, each of which this implementation got wrong once:
// 1. a request delivered after the word is armed returns from the handler ---
// under GCC -O0 the return trampoline was in `.bss' and the program died
// with SIGSEGV on its way back (K1);
// 2. a request the starter arranged not to deliver stays undelivered: SIGINT
// ignored before arming is still ignored after it (K2);
// 3. ending as requested ends the program as the request would have, which a
// started copy reports to its starter as a signal and not as a status (G4).
// started copy reports to its starter as a signal and not as a status (G4);
// 4. (0.18.2) a context waiting upon the word with `kal_task_wait' and no
// bound is woken by the request. The handler woke the word as a shared
// futex and `kal_task_wait' waits on it as a private one, which the kernel
// keys apart: the waiter slept on, and a program that ends at a request by
// waiting for it never ended.
#include <csignal>
#include <cstdio>
#include <cstring>
Expand All @@ -24,7 +29,30 @@ void check(bool held, const char* what) {
}
}

struct waiter {
const kal_u32* word;
volatile int woken;
};
void wait_for_request(void* p) {
auto* w = static_cast<waiter*>(p);
while (*w->word == 0) kal_task_wait(w->word, 0, 0); // no bound
w->woken = 1;
}

int main(int argc, char** argv) {
if (argc > 1 && std::strcmp(argv[1], "--waiter") == 0) {
const kal_u32* word = kal_process_stop_requested();
if (word == nullptr) return 90;
waiter w{ word, 0 };
kal_task t{};
if (kal_task_start(wait_for_request, &w, &t) != kal_ok) return 94;
::usleep(100000); // the context is waiting by now
::kill(::getpid(), SIGTERM);
for (int i = 0; i < 2000 && !w.woken; ++i) ::usleep(1000);
if (!w.woken) return 95;
kal_task_join(t);
return 0;
}
if (argc > 1 && std::strcmp(argv[1], "--hang-up") == 0) {
// 0.18.1: the closing of the terminal is a request to end, taken over
// with the others, and the program ends as it would have.
Expand Down Expand Up @@ -79,6 +107,16 @@ int main(int argc, char** argv) {
check(WIFSIGNALED(st) && WTERMSIG(st) == SIGHUP,
"a hang-up is taken over as a request, and the program ends as it would have");

const pid_t waiting = ::fork();
if (waiting == 0) {
::execl("/proc/self/exe", argv[0], "--waiter", nullptr);
::_exit(93);
}
st = 0;
::waitpid(waiting, &st, 0);
check(WIFEXITED(st) && WEXITSTATUS(st) == 0,
"a context waiting upon the word with no bound is woken by the request");

if (failures == 0) std::printf("openkal-linux: the stop word is taken over and given back\n");
return failures == 0 ? 0 : 1;
}
Loading