Feat: POSIX signal

This commit is contained in:
2025-05-04 20:38:25 +08:00
parent 8d1045f20d
commit d31f5e02fe
9 changed files with 171 additions and 33 deletions

View File

@@ -161,6 +161,9 @@ uint64_t _r_sp()
// #define DEBUG_THREAD(val) DEBUG(val) // #define DEBUG_THREAD(val) DEBUG(val)
#define DEBUG_THREAD(val) CLEAN #define DEBUG_THREAD(val) CLEAN
#define DEBUG_SIGNAL(val) DEBUG(val)
// #define DEBUG_SIGNAL(val) CLEAN
extern char logger_buf[LOGGER_BUFLEN]; extern char logger_buf[LOGGER_BUFLEN];
extern char *logger_cur; extern char *logger_cur;
extern char sp_buf[LOGGER_BUFLEN]; extern char sp_buf[LOGGER_BUFLEN];

View File

@@ -1,6 +1,8 @@
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
#include <vector.h>
#include <signal.h>
typedef struct { typedef struct {
uint64_t x0, x1; uint64_t x0, x1;
@@ -38,6 +40,13 @@ typedef struct process {
void *mem; void *mem;
size_t mem_size; size_t mem_size;
void *sigstack;
size_t sigstack_size;
bool sigstate[SIGNAL_NUM];
int32_t current_signal;
signal_handler_t sighandlers[SIGNAL_NUM];
trapframe_t *regs; trapframe_t *regs;
} process_t; } process_t;
@@ -51,3 +60,4 @@ int32_t run_process(uint64_t process);
process_t *fork_process(const process_t *from); process_t *fork_process(const process_t *from);
extern int32_t global_pid_counter; extern int32_t global_pid_counter;
extern vector_t *global_processes;

11
kernel/include/signal.h Normal file
View File

@@ -0,0 +1,11 @@
#pragma once
#include <stddef.h>
#define SIGNAL_NUM 32
#define SIGKILL 9
typedef void (*signal_handler_t)();
void run_signal(int32_t SIGNAL);

View File

@@ -2,6 +2,7 @@
#include <stddef.h> #include <stddef.h>
#include <process.h> #include <process.h>
#include <signal.h>
void syscall_handler(trapframe_t *regs); void syscall_handler(trapframe_t *regs);
@@ -12,4 +13,7 @@ int32_t sys_exec(const char *name, char *const argv[]);
int32_t sys_fork(void); int32_t sys_fork(void);
void sys_exit(int32_t status); void sys_exit(int32_t status);
int32_t sys_mbox_call(uint8_t ch, uint32_t *mbox); int32_t sys_mbox_call(uint8_t ch, uint32_t *mbox);
void sys_kill(int32_t pid); void sys_kill_by_id(int32_t pid);
void sys_signal(int32_t SIGNAL, signal_handler_t handler);
void sys_kill(int32_t pid, int32_t SIGNAL);
void sys_sigreturn(void);

View File

@@ -57,7 +57,7 @@
int mbox_call(unsigned char ch, unsigned int *input) int mbox_call(unsigned char ch, unsigned int *input)
{ {
unsigned int *_mbox = kmalloc((size_t)input[0] + 0xf), *mbox = ALIGN16(_mbox); unsigned int *_mbox = kmalloc((size_t)input[0] + 0xf), *mbox = ALIGN16(_mbox);
LOG(_mbox); LOG(mbox); DEBUG((size_t)input[0]); LOG(_mbox); LOG(mbox); DEBUG_THREAD((size_t)input[0]);
memcpy(mbox, input, (size_t)input[0]); memcpy(mbox, input, (size_t)input[0]);
unsigned int r = (unsigned long)mbox | (unsigned int)(ch&0xf); unsigned int r = (unsigned long)mbox | (unsigned int)(ch&0xf);
/* wait until we can write to the mailbox */ /* wait until we can write to the mailbox */

View File

@@ -11,15 +11,16 @@
#include <interrupt.h> #include <interrupt.h>
int32_t global_pid_counter = 0; int32_t global_pid_counter = 0;
vector_t *global_processes = 0x0;
static inline static inline
process_t *_make_process(const char *filename) process_t *_make_process()
{ {
process_t *ret = kmalloc(sizeof(process_t)); process_t *ret = kmalloc(sizeof(process_t));
file_node_t *file = initrd_get(initrd_root, filename); if (!global_processes)
if (file == 0x0) global_processes = make_vector(0);
panic(ERR_NOT_EXIST); VEC_PUSH(global_processes, ret);
*ret = (process_t){ *ret = (process_t){
.pid = global_pid_counter++, .pid = global_pid_counter++,
@@ -33,26 +34,46 @@ process_t *_make_process(const char *filename)
.mem = allocate_page(256), .mem = allocate_page(256),
.mem_size = 256 << 12, .mem_size = 256 << 12,
.sigstack = allocate_page(256),
.sigstack_size = 256 << 12,
.current_signal = 0,
.regs = kmalloc(sizeof(trapframe_t)), .regs = kmalloc(sizeof(trapframe_t)),
}; };
memcpy(ret->mem, file->filecontent, file->filesize);
memset(ret->sigstate, 0x0, SIGNAL_NUM * sizeof(bool));
memset(ret->sighandlers, 0x0, SIGNAL_NUM * sizeof(signal_handler_t));
memset(ret->regs, 0x0, sizeof(trapframe_t)); memset(ret->regs, 0x0, sizeof(trapframe_t));
*ret->regs = (trapframe_t){
.spsr_el1 = 0x0, // enable all interrupt
.elr_el1 = (uint64_t)ret->mem,
.sp_el0 = ((uint64_t)ret->stack + ret->stack_size - 64),
};
return ret; return ret;
} }
static inline
void _init_process(process_t *process, const char *filename)
{
file_node_t *file = initrd_get(initrd_root, filename);
if (file == 0x0)
panic(ERR_NOT_EXIST);
memcpy(process->mem, file->filecontent, file->filesize);
*process->regs = (trapframe_t){
.spsr_el1 = 0x0, // enable all interrupt
.elr_el1 = (uint64_t)process->mem,
.sp_el0 = ((uint64_t)process->stack + process->stack_size - 64),
};
}
// void run_process_by_name(const char *filename) // void run_process_by_name(const char *filename)
int32_t run_process_by_name(uint64_t param) int32_t run_process_by_name(uint64_t param)
{ {
const char *filename = (void *)param; const char *filename = (void *)param;
thread_t *th = get_current(); thread_t *th = get_current();
th->process = _make_process(filename); if (!th->process)
th->process = _make_process();
_init_process(th->process, filename);
th->process->th = th; th->process->th = th;
LOG("Run process by name"); DEBUG_THREAD(filename); LOG("Run process by name"); DEBUG_THREAD(filename);
LOG(th->process->stack); DEBUG_THREAD(th->process->regs->sp_el0); LOG(th->process->stack); DEBUG_THREAD(th->process->regs->sp_el0);
@@ -84,21 +105,7 @@ int32_t run_process(uint64_t param)
process_t *fork_process(const process_t *from) process_t *fork_process(const process_t *from)
{ {
process_t *ret = kmalloc(sizeof(process_t)); process_t *ret = _make_process();
*ret = (process_t){
.pid = global_pid_counter++,
.th = 0x0,
.exitcode = from->exitcode,
.stack = allocate_page(256),
.stack_size = 256 << 12,
.mem = allocate_page(256),
.mem_size = 256 << 12,
.regs = kmalloc(sizeof(trapframe_t)),
};
memcpy(ret->stack, from->stack, from->stack_size); memcpy(ret->stack, from->stack, from->stack_size);
memcpy(ret->mem, from->mem, from->mem_size); memcpy(ret->mem, from->mem, from->mem_size);
*ret->regs = (trapframe_t){ *ret->regs = (trapframe_t){

59
kernel/lib/signal.c Normal file
View File

@@ -0,0 +1,59 @@
#include <signal.h>
#include <logger.h>
#include <string.h>
#include <process.h>
#include <thread.h>
#include <kmalloc.h>
#include <interrupt.h>
#include <exec.h>
static inline
void _sighandler_wrapper(signal_handler_t handler)
{
handler();
asm volatile(
"mov x8, #10" ENDL
"svc 0"
::: "x8"
);
}
static inline
void _sigkill_default_handler()
{
thread_t *th = get_current();
th->status = THREAD_STATUS_ZOMBIE;
}
void run_signal(int32_t SIGNAL)
{
LOG("run_signal"); DEBUG_SIGNAL(SIGNAL);
process_t *process = get_current()->process;
process->current_signal = SIGNAL;
trapframe_t *regs = kmalloc(sizeof(trapframe_t));
memcpy(regs, process->regs, sizeof(trapframe_t));
if (!process->sighandlers[SIGNAL]) {
switch (SIGNAL) {
case SIGKILL:
_sigkill_default_handler();
break;
default:
LOG("No default handler for this signal"); DEBUG_SIGNAL(SIGNAL);
return;
}
}
*regs = (trapframe_t){
.x0 = (uint64_t)process->sighandlers[SIGNAL],
.elr_el1 = (uint64_t)_sighandler_wrapper,
.sp_el0 = ((uint64_t)process->sigstack + process->sigstack_size - 64),
};
disable_interrupt();
process->current_signal = 0x0;
process->sigstate[SIGNAL] = false;
user_exec(regs);
__builtin_unreachable();
}

View File

@@ -4,6 +4,7 @@
#include <thread.h> #include <thread.h>
#include <process.h> #include <process.h>
#include <mbox.h> #include <mbox.h>
#include <exec.h>
void syscall_handler(trapframe_t *regs) void syscall_handler(trapframe_t *regs)
{ {
@@ -27,13 +28,22 @@ void syscall_handler(trapframe_t *regs)
regs->x0 = sys_fork(); regs->x0 = sys_fork();
break; break;
case 5: // void exit(int32_t status) case 5: // void exit(int32_t status)
sys_exit((int)regs->x0); sys_exit((int32_t)regs->x0);
break; break;
case 6: // int32_t mbox_call(uint8_t ch, uint32_t *mbox) case 6: // int32_t mbox_call(uint8_t ch, uint32_t *mbox)
regs->x0 = sys_mbox_call((uint8_t)regs->x0, (uint32_t *)regs->x1); regs->x0 = sys_mbox_call((uint8_t)regs->x0, (uint32_t *)regs->x1);
break; break;
case 7: // void kill(int32_t pid) case 7: // void kill_by_id(int32_t pid)
sys_kill((int)regs->x0); sys_kill_by_id((int32_t)regs->x0);
break;
case 8: // void signal(int32_t SIGNAL, signal_handler_t handler)
sys_signal((int32_t)regs->x0, (signal_handler_t)regs->x1);
break;
case 9: // void kill(int32_t pid, int32_t SIGNAL)
sys_kill((int32_t)regs->x0, (int32_t)regs->x1);
break;
case 10: // void sigreturn(void)
sys_sigreturn();
break; break;
default: default:
LOG("unsupported syscall"); ERROR(regs->x8); LOG("unsupported syscall"); ERROR(regs->x8);
@@ -74,6 +84,34 @@ void sys_exit(int32_t status)
int32_t sys_mbox_call(uint8_t ch, uint32_t *mbox) int32_t sys_mbox_call(uint8_t ch, uint32_t *mbox)
{ return mbox_call(ch, mbox); } { return mbox_call(ch, mbox); }
void sys_kill(int32_t pid) void sys_kill_by_id(int32_t pid)
{ {
if (!global_processes || global_processes->size <= (size_t)pid) {
LOG("Process not exist"); INFOR(pid);
return;
}
process_t *process = VEC_AT(process_t, global_processes, pid);
process->th->status = THREAD_STATUS_ZOMBIE;
LOG("Process killed"); INFOR(pid);
}
void sys_signal(int32_t SIGNAL, signal_handler_t handler)
{
thread_t *th = get_current();
th->process->sighandlers[SIGNAL] = handler;
LOG(handler); LOG(SIGNAL); DEBUG_SIGNAL("registered");
}
void sys_kill(int32_t pid, int32_t SIGNAL)
{
process_t *process = VEC_AT(process_t, global_processes, pid);
process->sigstate[SIGNAL] = true;
}
void sys_sigreturn(void)
{
DEBUG_SIGNAL("sigreturn");
thread_t *th = get_current();
user_exec(th->process->regs);
} }

View File

@@ -41,5 +41,11 @@ void timer_irq_handler(void)
uint64_t cntfrq_el0; uint64_t cntfrq_el0;
R_SYSREG(cntfrq_el0, cntfrq_el0); R_SYSREG(cntfrq_el0, cntfrq_el0);
W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 5); W_SYSREG(cntp_tval_el0, cntfrq_el0 >> 5);
thread_t *th = get_current();
for (int32_t i = 0; i < SIGNAL_NUM; ++i) {
if (th->process->sigstate[i])
run_signal(i);
}
schedule(); schedule();
} }