improvements to arch/signal

use mmap for stacks

split up main into different steps

add SA_RESTART to sigaction flags
This commit is contained in:
Chris Copeland 2024-05-16 01:18:10 -07:00
parent 37534bb9fc
commit 51b29dabde
Signed by: chrisnc
GPG Key ID: 14550DA72485DF30
5 changed files with 76 additions and 46 deletions

View File

@ -59,6 +59,9 @@ def ld_emitter(target, source, env):
env = Environment(
tools=["cc", "c++", "as", "ar", "link"],
CC="clang",
CXX="clang++",
CPPPATH=[Dir("include").srcnode()],
CCFLAGS=llvm_flags,
ASFLAGS=llvm_flags,
@ -93,8 +96,6 @@ else:
if "TERM" in os.environ:
env["ENV"]["TERM"] = os.environ["TERM"]
env["CC"] = "clang"
env["CXX"] = "clang++"
env.Append(CPPPATH=[Dir("arch/signal/include").srcnode()])
if "darwin" in sys.platform:
@ -105,6 +106,7 @@ elif "linux" in sys.platform:
env["RANLIB"] = "llvm-ranlib"
env["AR"] = "llvm-ar"
env.Append(
CPPDEFINES=["_GNU_SOURCE"],
LINKFLAGS=[
"-Wl,--gc-sections",
"-Wl,-z,noexecstack",

View File

@ -0,0 +1,9 @@
#pragma once
#include <sys/time.h>
// Initialize the signal handlers used by rt.
void rt_signal_init(void);
// Start a periodic tick timer.
void rt_signal_init_tick(const struct timeval *period);

View File

@ -1,5 +1,6 @@
#include <rt/arch/irq.h>
#include <rt/arch/syscall.h>
#include <rt/arch/init.h>
#include <rt/assert.h>
#include <rt/context.h>
#include <rt/cycle.h>
@ -14,6 +15,7 @@
#include <pthread.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <unistd.h>
@ -33,6 +35,10 @@
#error "unsupported architecture"
#endif
#ifndef MAP_STACK
#define MAP_STACK 0
#endif
// Signals in ascending priority order. Later signals should mask earlier ones.
#define SIGPENDSYSCALL SIGUSR1
#define SIGTICK SIGALRM
@ -94,16 +100,21 @@ __attribute__((noreturn)) void rt_task_entry(void);
__attribute__((noreturn)) void rt_task_entry_arg(void);
static struct context *context_init(void *stack, size_t stack_size)
static struct context *context_init(void)
{
void *const sp = (char *)stack + stack_size;
void *const sp =
(char *)mmap(NULL, (size_t)PTHREAD_STACK_MIN, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK, -1, 0) +
PTHREAD_STACK_MIN;
struct context *ctx = sp;
return ctx - 1;
}
void *rt_context_init(void (*fn)(void), void *stack, size_t stack_size)
{
struct context *ctx = context_init(stack, stack_size);
(void)stack;
(void)stack_size;
struct context *ctx = context_init();
#ifdef __aarch64__
ctx->x19 = (uint64_t)fn;
ctx->fp = 0;
@ -119,7 +130,9 @@ void *rt_context_init(void (*fn)(void), void *stack, size_t stack_size)
void *rt_context_init_arg(void (*fn)(uintptr_t), uintptr_t arg, void *stack,
size_t stack_size)
{
struct context *ctx = context_init(stack, stack_size);
(void)stack;
(void)stack_size;
struct context *ctx = context_init();
#ifdef __aarch64__
ctx->x19 = (uint64_t)fn;
ctx->x20 = arg;
@ -208,49 +221,48 @@ static void trap_handler(int arg)
exit(0);
}
void rt_signal_init_tick(const struct timeval *period)
{
const struct itimerval timer = {
.it_interval = *period,
.it_value = *period,
};
setitimer(ITIMER_REAL, &timer, NULL);
}
void rt_signal_init(void)
{
struct sigaction action;
action.sa_flags = SA_RESTART;
// Pending syscalls don't mask other signals.
action.sa_handler = rt_pending_syscall_handler;
sigemptyset(&action.sa_mask);
sigaction(SIGPENDSYSCALL, &action, NULL);
// IRQ and trap mask all rt-related signals.
action.sa_handler = irq_handler;
action.sa_mask = sigset_all;
sigaction(SIGIRQ, &action, NULL);
action.sa_handler = trap_handler;
sigaction(SIGTRAP, &action, NULL);
// The tick handler must mask SIGPENDSYSCALL.
action.sa_handler = tick_handler;
action.sa_mask = sigset_pendsyscall;
sigaction(SIGTICK, &action, NULL);
}
__attribute__((weak)) int main(void)
{
// Block pending syscalls until we have started running the first task.
rt_block_pending_syscalls();
struct sigaction pending_syscall_action = {
.sa_handler = rt_pending_syscall_handler,
};
sigemptyset(&pending_syscall_action.sa_mask);
sigaction(SIGPENDSYSCALL, &pending_syscall_action, NULL);
// The tick handler must block SIGPENDSYSCALL.
struct sigaction tick_action = {
.sa_handler = tick_handler,
.sa_mask = sigset_pendsyscall,
};
sigaction(SIGTICK, &tick_action, NULL);
// The IRQ handler must block SIGPENDSYSCALL and SIGTICK.
struct sigaction irq_action = {
.sa_handler = irq_handler,
};
sigemptyset(&irq_action.sa_mask);
sigaddset(&irq_action.sa_mask, SIGPENDSYSCALL);
sigaddset(&irq_action.sa_mask, SIGTICK);
sigaction(SIGIRQ, &irq_action, NULL);
// Trap masks all rt-related signals.
struct sigaction trap_action = {
.sa_handler = trap_handler,
.sa_mask = sigset_all,
};
sigaction(SIGTRAP, &trap_action, NULL);
rt_signal_init();
static const struct timeval milli = {
.tv_sec = 0,
.tv_usec = 1000,
};
struct itimerval timer = {
.it_interval = milli,
.it_value = milli,
};
setitimer(ITIMER_REAL, &timer, NULL);
rt_signal_init_tick(&milli);
rt_start();
}

View File

@ -18,14 +18,14 @@ struct Arch<'a> {
name: &'a str,
sources: &'a [&'a str],
flags: &'a [&'a str],
defs: &'a [(&'a str, &'a str)],
defs: &'a [(&'a str, Option<&'a str>)],
}
static SIGNAL_ARCH: Arch = Arch {
name: "signal",
sources: &["signal.c", "syscall.S", "task_entry.S"],
flags: &["-pthread"],
defs: &[],
defs: &[("_GNU_SOURCE", None)],
};
static ARM_ARCH: Arch = Arch {
@ -127,11 +127,16 @@ fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let arch_def_flags = arch.defs.iter().map(|(m, ov)| match ov {
Some(v) => format!("-D{m}={v}"),
None => format!("-D{m}"),
});
bindgen::builder()
.header(wrapper)
.clang_arg(format!("-I{}", include_dir.display()))
.clang_arg(format!("-I{}", arch_include_dir.display()))
.clang_args(arch.defs.iter().map(|&(m, v)| format!("-D{m}={v}")))
.clang_args(arch_def_flags)
.clang_args(arch.flags)
.disable_nested_struct_naming()
.use_core()

View File

@ -23,7 +23,9 @@ impl UnwindSafe for Condvar {}
impl RefUnwindSafe for Condvar {}
pub(crate) const fn c_cond_init(c: &'static rt_cond) -> rt_cond {
rt_cond { sem: c_sem_init(&c.sem, 0, 1) }
rt_cond {
sem: c_sem_init(&c.sem, 0, 1),
}
}
impl Condvar {