Skip to content

Commit d33e5c4

Browse files
0.18.2 --- the stop word wakes a context waiting upon it (#41)
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent a5d9f09 commit d33e5c4

4 files changed

Lines changed: 47 additions & 5 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.1"
11+
openkal-linux = "0.18.2"
1212
```
1313

1414
## Why it does not use a C library

‎mcpp.toml‎

Lines changed: 1 addition & 1 deletion
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.1"
4+
version = "0.18.2"
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

‎src/process.cpp‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,8 +929,12 @@ void stop_handler(int signo) {
929929
__atomic_compare_exchange_n(&g_stop_signal, &none, signo, false,
930930
__ATOMIC_RELAXED, __ATOMIC_RELAXED);
931931
__atomic_store_n(&g_stop_word, 1u, __ATOMIC_RELEASE);
932+
// PRIVATE, AS `kal_task_wait' WAITS (0.18.2). The kernel keys a private
933+
// futex apart from a shared one at the same address, so a shared wake
934+
// reached no context waiting through `kal_task_wait' with no bound, and a
935+
// program that waits for its end to be requested never ended.
932936
okl::sys(okl::nr_futex, reinterpret_cast<okl_long>(&g_stop_word),
933-
1 /* FUTEX_WAKE */, 0x7fffffff, 0, 0, 0);
937+
okl::futex_wake | okl::futex_private, 0x7fffffff, 0, 0, 0);
934938
}
935939

936940
// THE RESULT IS EXAMINED, AND IT WAS NOT WHEN THIS SHIPPED IN 0.11. An

‎tests/stop_word_take_over.cpp‎

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
// The stop word, taken over and given back (openkal 0.17, process.h; K1, K2).
22
//
3-
// Three facts, each of which this implementation got wrong before 0.18:
3+
// Four facts, each of which this implementation got wrong once:
44
// 1. a request delivered after the word is armed returns from the handler ---
55
// under GCC -O0 the return trampoline was in `.bss' and the program died
66
// with SIGSEGV on its way back (K1);
77
// 2. a request the starter arranged not to deliver stays undelivered: SIGINT
88
// ignored before arming is still ignored after it (K2);
99
// 3. ending as requested ends the program as the request would have, which a
10-
// started copy reports to its starter as a signal and not as a status (G4).
10+
// started copy reports to its starter as a signal and not as a status (G4);
11+
// 4. (0.18.2) a context waiting upon the word with `kal_task_wait' and no
12+
// bound is woken by the request. The handler woke the word as a shared
13+
// futex and `kal_task_wait' waits on it as a private one, which the kernel
14+
// keys apart: the waiter slept on, and a program that ends at a request by
15+
// waiting for it never ended.
1116
#include <csignal>
1217
#include <cstdio>
1318
#include <cstring>
@@ -24,7 +29,30 @@ void check(bool held, const char* what) {
2429
}
2530
}
2631

32+
struct waiter {
33+
const kal_u32* word;
34+
volatile int woken;
35+
};
36+
void wait_for_request(void* p) {
37+
auto* w = static_cast<waiter*>(p);
38+
while (*w->word == 0) kal_task_wait(w->word, 0, 0); // no bound
39+
w->woken = 1;
40+
}
41+
2742
int main(int argc, char** argv) {
43+
if (argc > 1 && std::strcmp(argv[1], "--waiter") == 0) {
44+
const kal_u32* word = kal_process_stop_requested();
45+
if (word == nullptr) return 90;
46+
waiter w{ word, 0 };
47+
kal_task t{};
48+
if (kal_task_start(wait_for_request, &w, &t) != kal_ok) return 94;
49+
::usleep(100000); // the context is waiting by now
50+
::kill(::getpid(), SIGTERM);
51+
for (int i = 0; i < 2000 && !w.woken; ++i) ::usleep(1000);
52+
if (!w.woken) return 95;
53+
kal_task_join(t);
54+
return 0;
55+
}
2856
if (argc > 1 && std::strcmp(argv[1], "--hang-up") == 0) {
2957
// 0.18.1: the closing of the terminal is a request to end, taken over
3058
// with the others, and the program ends as it would have.
@@ -79,6 +107,16 @@ int main(int argc, char** argv) {
79107
check(WIFSIGNALED(st) && WTERMSIG(st) == SIGHUP,
80108
"a hang-up is taken over as a request, and the program ends as it would have");
81109

110+
const pid_t waiting = ::fork();
111+
if (waiting == 0) {
112+
::execl("/proc/self/exe", argv[0], "--waiter", nullptr);
113+
::_exit(93);
114+
}
115+
st = 0;
116+
::waitpid(waiting, &st, 0);
117+
check(WIFEXITED(st) && WEXITSTATUS(st) == 0,
118+
"a context waiting upon the word with no bound is woken by the request");
119+
82120
if (failures == 0) std::printf("openkal-linux: the stop word is taken over and given back\n");
83121
return failures == 0 ? 0 : 1;
84122
}

0 commit comments

Comments
 (0)