diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-07-01 23:34:57 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2024-07-01 23:34:57 +0300 |
| commit | 7ad9c01dad7b1b46eced8290b8b991383d648188 (patch) | |
| tree | cd528648af552974b90117efef431659ef5f0cc6 | |
| parent | 9ff67d879b4695e0c9910b7276f3959c005c7b19 (diff) | |
| download | kmi-7ad9c01dad7b1b46eced8290b8b991383d648188.tar.gz kmi-7ad9c01dad7b1b46eced8290b8b991383d648188.zip | |
expand notifications into interrupt handlers
+ Terminology is still a bit poor, and will still have to write
documentation + implement ipis properly
| -rwxr-xr-x | arch/riscv64/conf/init | bin | 3512 -> 5312 bytes | |||
| -rw-r--r-- | arch/riscv64/conf/init.c | 85 | ||||
| -rw-r--r-- | arch/riscv64/conf/initrd | bin | 4096 -> 5632 bytes | |||
| -rw-r--r-- | arch/riscv64/kernel/csr.h | 2 | ||||
| -rw-r--r-- | arch/riscv64/kernel/irq.c | 10 | ||||
| -rw-r--r-- | include/kmi/caps.h | 5 | ||||
| -rw-r--r-- | include/kmi/notify.h | 9 | ||||
| -rw-r--r-- | include/kmi/syscalls.h | 12 | ||||
| -rw-r--r-- | include/kmi/tcb.h | 5 | ||||
| -rw-r--r-- | include/kmi/uapi.h | 30 | ||||
| -rw-r--r-- | src/ipi.c | 10 | ||||
| -rw-r--r-- | src/irq.c | 15 | ||||
| -rw-r--r-- | src/proc.c | 2 | ||||
| -rw-r--r-- | src/timer.c | 9 | ||||
| -rw-r--r-- | src/uapi/dispatch.c | 2 | ||||
| -rw-r--r-- | src/uapi/ipc.c | 89 | ||||
| -rw-r--r-- | src/uapi/irq.c | 14 | ||||
| -rw-r--r-- | src/uapi/proc.c | 3 |
18 files changed, 222 insertions, 80 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init Binary files differindex d04c492..ea63935 100755 --- a/arch/riscv64/conf/init +++ b/arch/riscv64/conf/init diff --git a/arch/riscv64/conf/init.c b/arch/riscv64/conf/init.c index 293d5e8..80bb68a 100644 --- a/arch/riscv64/conf/init.c +++ b/arch/riscv64/conf/init.c @@ -24,10 +24,6 @@ #include <stddef.h> #include "../../../include/kmi/syscalls.h" -struct sys_ret { - long a0, a1, a2, a3, a4, a5; -}; - char *strcpy(char * restrict dst, const char * restrict src) { const char *s1 = src; @@ -40,8 +36,8 @@ char *strcpy(char * restrict dst, const char * restrict src) } static inline struct sys_ret ecall(size_t n, - long arg0, long arg1, long arg2, long arg3, - long arg4, long arg5) + sys_arg_t arg0, sys_arg_t arg1, sys_arg_t arg2, sys_arg_t arg3, + sys_arg_t arg4, sys_arg_t arg5) { /* here a static assert of n <= 6 && n >= 1 would be ideal */ @@ -103,11 +99,11 @@ static uint64_t sys_timebase() { struct sys_ret r = ecall1(SYS_TIMEBASE); #if defined(_LP64) - return r.a1; + return r.ar0; #else - uint64_t t = r.a1; + uint64_t t = r.ar0; t <<= 32; - return t + r.a2; + return t + r.ar1; #endif } @@ -115,11 +111,11 @@ static uint64_t sys_ticks() { struct sys_ret r = ecall1(SYS_TICKS); #if defined(_LP64) - return r.a1; + return r.ar0; #else - uint64_t t = r.a1; + uint64_t t = r.ar0; t <<= 32; - return t + r.a2; + return t + r.ar1; #endif } @@ -161,21 +157,21 @@ static uint64_t sys_fork() { struct sys_ret r = ecall1(SYS_FORK); - if (r.a0 != 0) { - print_value("fork() failed with error ", r.a0); - return r.a0; + if (r.s != 0) { + print_value("fork() failed with error ", r.s); + return r.s; } - return r.a1; + return r.ar0; } static uint64_t sys_swap(long tid) { struct sys_ret r = ecall2(SYS_SWAP, tid); - if (r.a0 != 0) { - print_value("swap() failed with error ", r.a0); - return r.a0; + if (r.s != 0) { + print_value("swap() failed with error ", r.s); + return r.s; } return 0; @@ -185,29 +181,23 @@ static void sys_ipc_server(void *f) { struct sys_ret r = ecall2(SYS_IPC_SERVER, (long)f); - if (r.a0 != 0) - print_value("ipc_server() failed with error ", r.a0); + if (r.s != 0) + print_value("ipc_server() failed with error ", r.s); } -/** Helper for ipc arguments/return values. */ -struct ipc_args { - long s; long a0, a1, a2, a3; -}; - -static inline struct ipc_args sys_ipc_req(long tid, long d0, long d1, long d2, - long d3) +static inline struct sys_ret sys_ipc_req(sys_arg_t pid, + sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, + sys_arg_t d3) { - struct sys_ret r = ecall6(SYS_IPC_REQ, tid, d0, d1, d2, d3); + struct sys_ret r = ecall6(SYS_IPC_REQ, pid, d0, d1, d2, d3); - if (r.a0) { - print_value("ipc_req() failed with error ", r.a0); - return (struct ipc_args){r.a0, 0, 0, 0, 0}; - } + if (r.s) + print_value("ipc_req() failed with error ", r.s); - return (struct ipc_args){r.a0, r.a1, r.a2, r.a3, r.a4}; + return r; } -static void sys_ipc_resp(long d0, long d1, long d2, long d3) +static void sys_ipc_resp(sys_arg_t d0, sys_arg_t d1, sys_arg_t d2, sys_arg_t d3) { ecall5(SYS_IPC_RESP, d0, d1, d2, d3); } @@ -221,20 +211,20 @@ static void *sys_req_mem(size_t count) { struct sys_ret r = ecall3(SYS_REQ_MEM, count, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4)); - if (r.a0) { - print_value("sys_req_mem() failed with error ", r.a0); + if (r.s) { + print_value("sys_req_mem() failed with error ", r.s); return NULL; } - return (void *)r.a1; + return (void *)r.ar0; } static void sys_free_mem(void *p) { struct sys_ret r = ecall2(SYS_FREE_MEM, (long)p); - if (r.a0) - print_value("sys_free_mem() failed with error ", r.a0); + if (r.s) + print_value("sys_free_mem() failed with error ", r.s); } static void *sys_req_sharedmem(long tid, unsigned long size, void **cbuf) @@ -242,13 +232,13 @@ static void *sys_req_sharedmem(long tid, unsigned long size, void **cbuf) struct sys_ret r = ecall5(SYS_REQ_SHAREDMEM, tid, size, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4), (1 << 0) | (1 << 1) | (1 << 2) | (1 << 4)); - if (r.a0) { - print_value("sys_req_sharedmem() failed with error ", r.a0); + if (r.s) { + print_value("sys_req_sharedmem() failed with error ", r.s); return NULL; } - *cbuf = (void *)r.a2; - return (void *)r.a1; + *cbuf = (void *)r.ar1; + return (void *)r.ar0; } /* I'm guessing my elf parser doesn't handle data pages correctly yet... */ @@ -345,9 +335,10 @@ void _start() } puts("Checking shared memory\n"); - struct ipc_args r = sys_ipc_req(1, 1, 0, 0, 0); - rw_buf = (char *)r.a1; - rw_buf_size = (size_t)r.a2; + struct sys_ret r = sys_ipc_req(1, 1, 0, 0, 0); + rw_buf = (char *)r.ar1; + rw_buf_size = (size_t)r.ar2; + print_value("Response from", r.ar0); print_value("Shared memory ptr", (uintptr_t)rw_buf); print_value("Shared memory size", rw_buf_size); diff --git a/arch/riscv64/conf/initrd b/arch/riscv64/conf/initrd Binary files differindex c8d7253..72260ef 100644 --- a/arch/riscv64/conf/initrd +++ b/arch/riscv64/conf/initrd diff --git a/arch/riscv64/kernel/csr.h b/arch/riscv64/kernel/csr.h index 9b7b78a..bc48464 100644 --- a/arch/riscv64/kernel/csr.h +++ b/arch/riscv64/kernel/csr.h @@ -40,6 +40,8 @@ /** Address of \c sstatus CSR. */ #define CSR_SSTATUS 0x100 +#define SR_SPIE 0b10 + /** Address of \c sie CSR. */ #define CSR_SIE 0x104 diff --git a/arch/riscv64/kernel/irq.c b/arch/riscv64/kernel/irq.c index 964401f..2ef15cc 100644 --- a/arch/riscv64/kernel/irq.c +++ b/arch/riscv64/kernel/irq.c @@ -41,12 +41,13 @@ stat_t deactivate_irq(irq_t id) /* very simple for now */ void enable_irqs() { - csr_set(CSR_SSTATUS, CSR_SIE); + /* should be supervisor external interrupt */ + csr_set(CSR_SIE, 1 << 9); } void disable_irqs() { - csr_clear(CSR_SSTATUS, CSR_SIE); + csr_clear(CSR_SIE, 1 << 9); } irq_t get_irq() @@ -71,9 +72,10 @@ static void riscv_unknown_interrupt(long id) * * @param id ID of interrupt, with interrupt bit still set. */ -void riscv_handle_interrupt(long id) +void riscv_handle_interrupt(unsigned long id) { - id = -id; + /* clear leading one */ + id = (id << 1) >> 1; switch (id) { /* I think */ diff --git a/include/kmi/caps.h b/include/kmi/caps.h index 2813634..8af9293 100644 --- a/include/kmi/caps.h +++ b/include/kmi/caps.h @@ -26,7 +26,7 @@ enum { /** Thread is allowed to modify process statuses, create/exec/fork/etc. */ CAP_PROC = (1 << 1), - /** Thread is allowed to force interrupt to callback in other thread. */ + /** Thread is allowed to force notification in other thread. */ CAP_CALL = (1 << 2), /** Thread is allowed to shut down system. */ @@ -37,6 +37,9 @@ enum { /** Thread is allowed to request to handle IRQs. */ CAP_IRQ = (1 << 5), + + /** Thread is allowed to request notification handler. */ + CAP_NOTIFICATION = (1 << 6), }; /** diff --git a/include/kmi/notify.h b/include/kmi/notify.h new file mode 100644 index 0000000..0a17654 --- /dev/null +++ b/include/kmi/notify.h @@ -0,0 +1,9 @@ +#ifndef KMI_NOTIFY_H +#define KMI_NOTIFY_H + +#include <kmi/tcb.h> + +/* Implemented in ipc.c */ +void notify(struct tcb *t); + +#endif /* KMI_NOTIFY_H */ diff --git a/include/kmi/syscalls.h b/include/kmi/syscalls.h index e503709..23fc799 100644 --- a/include/kmi/syscalls.h +++ b/include/kmi/syscalls.h @@ -18,7 +18,7 @@ /** enum for now, possibly macros in the future once I get an approximate idea of * which syscalls are necessary etc. */ -enum { +enum sys_code { /** * @name Misc. * Implementation in \ref dispatch.c instead of a separate file, as I @@ -96,6 +96,9 @@ enum { /** IPC response from server. */ SYS_IPC_RESP, + /** IPC return without visible side effects. */ + SYS_IPC_GHOST, + /** IPC notify thread, essentially interrupt or signal. */ SYS_IPC_NOTIFY, /** @} */ @@ -148,11 +151,18 @@ enum { /** Request to handle IRQ. */ SYS_IRQ_REQ, + /** Request a notification handler. */ + SYS_REQ_NOTIFICATION, + /** @} */ SYS_NUM, }; +enum sys_user { + SYS_USER_NOTIFY, +}; + /* function declarations should be somewhere else, this file could be used in * userspace applications as well */ diff --git a/include/kmi/tcb.h b/include/kmi/tcb.h index 6614d62..999b6a8 100644 --- a/include/kmi/tcb.h +++ b/include/kmi/tcb.h @@ -177,6 +177,11 @@ struct tcb { /** Cpu currently executing this thread. */ id_t cpu_id; + /** In which process to run notifications. Note that this is currently + * set in the syscall handlers due to the different rules for inheriting + * this id, might change in the future. */ + id_t notify_id; + /** Capabilities of thread. */ capflags_t caps; diff --git a/include/kmi/uapi.h b/include/kmi/uapi.h index 5e5f446..1631500 100644 --- a/include/kmi/uapi.h +++ b/include/kmi/uapi.h @@ -427,7 +427,8 @@ SYSCALL_DECLARE0(ticks); * * @param t Current tcb. * @param ticks Number of ticks from now. - * @param mult Number of times to trigger. + * @param mult Multiplier for \p ticks if we're on 32bit systems to produce a + * combined 64 bit value. Ignored on 64bit systems. * @param c Unused. * @param d Unused. * @param e Unused. @@ -556,6 +557,16 @@ SYSCALL_DECLARE5(ipc_kick, pid, d0, d1, d2, d3); SYSCALL_DECLARE4(ipc_resp, d0, d1, d2, d3); /** + * Returns to caller but without changing any visible state. Primarily used when + * returning from interrupt handlers, like notifications, timers or external + * devices. + * + * @param r Current tcb. + * + */ +SYSCALL_DECLARE0(ipc_ghost); + +/** * Notify thread syscall. * * @param t Current tcb. @@ -748,6 +759,22 @@ SYSCALL_DECLARE2(get_cap, tid, off); SYSCALL_DECLARE3(clear_cap, tid, off, cap); /** + * Set which process to move notifications to for thread. + * @todo Should converge on either calling everything irq or notification or + * whatever, but mixing both is a bit dumb. + * + * @param t Current tcb. + * @param tid Thread whose notifications should be moved. + * @param pid Process that is willing to handle the notifications. + * @param c Unused. + * @param d Unused. + * @param e Unused. + * + * Returns \ref OK. + */ +SYSCALL_DECLARE2(req_notification, tid, pid); + +/** * Power off syscall. * * Either shut down or reboot system. @@ -792,6 +819,7 @@ SYSCALL_DECLARE0(sleep); * @todo document error codes better. */ SYSCALL_DECLARE1(irq_req, id); + /** @} */ /** @@ -1,10 +1,11 @@ /* SPDX-License-Identifier: copyleft-next-0.3.1 */ /* Copyright 2023 Kim Kuparinen < kimi.h.kuparinen@gmail.com > */ +#include <kmi/notify.h> #include <kmi/ipi.h> -#include <arch/cpu.h> #include <arch/proc.h> +#include <arch/cpu.h> /** * @file ipi.c @@ -30,6 +31,9 @@ void handle_ipi() struct tcb *t = cur_tcb(); adjust_ipi(t); - /** @todo use rpc stack */ - set_return(t, t->callback); + /** @todo how do we get the target thread? What if multiple threads send + * ipis at the same time? */ + struct tcb *r = NULL; + notify(r); + /* notify didn't take for whatever reason so return whence we came from */ } @@ -10,6 +10,7 @@ #include <kmi/pmem.h> #include <kmi/debug.h> #include <kmi/assert.h> +#include <kmi/notify.h> #include <kmi/string.h> #include <arch/irq.h> @@ -59,9 +60,19 @@ void handle_irq() id_t tid = irq_map[id]; if (!tid) { - bug("unregistered irq: %llu\n", (unsigned long long)id); + bug("unregistered irq %llu\n", (unsigned long long)id); return; } - /** @todo switch to thread */ + struct tcb *t = get_tcb(tid); + if (!t) { + error("tcb %llu dead at irq %llu\n", + (unsigned long long)tid, + (unsigned long long)id); + return; + } + + disable_irqs(); + notify(t); + error("misc error when trying to notify irq"); } @@ -48,6 +48,8 @@ stat_t init_proc(void *fdt) /* init process has all capabilities */ set_caps(t->caps, 0, CAP_CAPS | CAP_PROC | CAP_CALL | CAP_POWER); + t->notify_id = t->tid; + /* allocate stacks after ELF file to make sure nothing of importance * clashes */ return prepare_proc(t, get_init_base(fdt), 0); diff --git a/src/timer.c b/src/timer.c index 474d995..5af03e8 100644 --- a/src/timer.c +++ b/src/timer.c @@ -16,12 +16,13 @@ */ #include <kmi/sp_tree.h> +#include <arch/timer.h> #include <kmi/string.h> +#include <kmi/notify.h> #include <kmi/nodes.h> #include <kmi/utils.h> #include <kmi/timer.h> #include <kmi/debug.h> -#include <arch/timer.h> #include <arch/cpu.h> /** Timer resolution. */ @@ -199,5 +200,9 @@ void handle_timer() struct timer *t = newest_timer(); remove_timer(t); - /** \todo handle timer thread ID */ + struct tcb *r = get_tcb(t->tid); + if (!r) + return; + + notify(r); } diff --git a/src/uapi/dispatch.c b/src/uapi/dispatch.c index f160091..a7f0322 100644 --- a/src/uapi/dispatch.c +++ b/src/uapi/dispatch.c @@ -56,6 +56,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, case SYS_FREE_MEM: sys_free_mem(t, a, b, c, d, e); break; case SYS_TIMEBASE: sys_timebase(t, a, b, c, d, e); break; case SYS_TICKS: sys_ticks(t, a, b, c, d, e); break; + case SYS_REQ_NOTIFICATION: sys_req_notification(t, a, b, c, d, e); break; case SYS_REQ_REL_TIMER: sys_req_rel_timer(t, a, b, c, d, e); break; case SYS_REQ_ABS_TIMER: sys_req_abs_timer(t, a, b, c, d, e); break; case SYS_IPC_SERVER: sys_ipc_server(t, a, b, c, d, e); break; @@ -63,6 +64,7 @@ void handle_syscall(sys_arg_t syscall, sys_arg_t a, sys_arg_t b, case SYS_IPC_FWD: sys_ipc_fwd(t, a, b, c, d, e); break; case SYS_IPC_KICK: sys_ipc_kick(t, a, b, c, d, e); break; case SYS_IPC_RESP: sys_ipc_resp(t, a, b, c, d, e); break; + case SYS_IPC_GHOST: sys_ipc_ghost(t, a, b, c, d, e); break; case SYS_IPC_NOTIFY: sys_ipc_notify(t, a, b, c, d, e); break; case SYS_CREATE: sys_create(t, a, b, c, d, e); break; case SYS_FORK: sys_fork(t, a, b, c, d, e); break; diff --git a/src/uapi/ipc.c b/src/uapi/ipc.c index bc836fc..8df0e3f 100644 --- a/src/uapi/ipc.c +++ b/src/uapi/ipc.c @@ -9,6 +9,7 @@ #include <kmi/uapi.h> #include <kmi/tcb.h> #include <kmi/ipi.h> +#include <kmi/irq.h> #include <kmi/conf.h> /** Structure for maintaining the required context data for an rpc call. */ @@ -120,7 +121,48 @@ static vm_t enter_rpc(struct tcb *t, struct sys_ret a, } /** + * Check that there's enough stack left for an rpc invocation. + * + * @param t Thread whose migration to check. + * @return \c true if there's enough stack left to safely do migration, + * \c false otherwise. + */ +static bool enough_rpc_stack(struct tcb *t) +{ + /* get top of call stack */ + vm_t top = rpc_position(t); + + /* if we can still fit an rpc stack into the call stack, we can safely + * do the migration. */ + return top - BASE_PAGE_SIZE - __rpc_stack_size >= RPC_STACK_BASE; +} + +void notify(struct tcb *t) +{ + /* some duplication from do_ipc, but not too bad I guess */ + struct tcb *notify = get_tcb(t->notify_id); + if (!notify || !notify->callback) { + t->notify_state = NOTIFY_WAITING; + return; + } + + if (unlikely(!enough_rpc_stack(t))) { + t->notify_state = NOTIFY_WAITING; + return; + } + + /* signal to whoever is receiving us that we're from the kernel + * ("pid 0"), and we are notifying the current thread */ + vm_t s = enter_rpc(t, SYS_RET4(0, SYS_USER_NOTIFY, t->eid, t->tid), IPC_REQ); + finalize_rpc(t, notify, s); + t->notify_state = NOTIFY_RUNNING; + ret_userspace_fast(); + unreachable(); +} + +/** * Jump back to process where rpc came from, assuming such a thing exists. + * If we're queued for a notification, jump to it instead. * * @param t Thread to do return migration on. * @param a Arguments to pass along. @@ -150,27 +192,23 @@ static void leave_rpc(struct tcb *t, struct sys_ret a) t->pid = ctx->pid; t->eid = ctx->eid; - if (is_rpc(t)) + if (is_rpc(t)) { use_vmem(t->rpc.vmem); - else + return; + } + + if (t->notify_state != NOTIFY_QUEUED) { + /* turn a potential NOTIFY_RUNNING into NOTIFY_WAITING */ + t->notify_state = NOTIFY_WAITING; use_vmem(t->proc.vmem); -} + return; + } -/** - * Check that there's enough stack left for an rpc invocation. - * - * @param t Thread whose migration to check. - * @return \c true if there's enough stack left to safely do migration, - * \c false otherwise. - */ -static bool enough_rpc_stack(struct tcb *t) -{ - /* get top of call stack */ - vm_t top = rpc_position(t); + notify(t); - /* if we can still fit an rpc stack into the call stack, we can safely - * do the migration. */ - return top - BASE_PAGE_SIZE - __rpc_stack_size >= RPC_STACK_BASE; + /* we failed in notifying the thread, so just return back to the + * process normally */ + use_vmem(t->proc.vmem); } /** @@ -320,6 +358,16 @@ SYSCALL_DEFINE4(ipc_resp)(struct tcb *t, sys_arg_t d0, sys_arg_t d1, leave_rpc(t, SYS_RET6(OK, t->pid, d0, d1, d2, d3)); } +SYSCALL_DEFINE0(ipc_ghost)(struct tcb *t) +{ + if (unlikely(!is_rpc(t))) + return_args1(t, ERR_MISC); + + /** @todo this should also enable interrupts when leaving kernel */ + enable_irqs(); + leave_rpc(t, get_args(t)); +} + /** * Notify syscall handler. * @@ -330,6 +378,10 @@ SYSCALL_DEFINE4(ipc_resp)(struct tcb *t, sys_arg_t d0, sys_arg_t d1, * @return \ref OK and 0. */ SYSCALL_DEFINE1(ipc_notify)(struct tcb *t, sys_arg_t tid){ + if (t->tid == tid) { + /** @todo notify self */ + } + if (!has_cap(t->caps, CAP_CALL)) return_args1(t, ERR_PERM); @@ -343,7 +395,8 @@ SYSCALL_DEFINE1(ipc_notify)(struct tcb *t, sys_arg_t tid){ } r->notify_state = NOTIFY_QUEUED; - if (running(r)) + /* only interrupt if thread is in owning process */ + if (running(r) && r->rid == r->pid) send_ipi(r); return_args1(t, OK); diff --git a/src/uapi/irq.c b/src/uapi/irq.c index 6687826..9bd8ec1 100644 --- a/src/uapi/irq.c +++ b/src/uapi/irq.c @@ -13,7 +13,6 @@ * Actual IRQ handling request syscall handler. * * @param t Current tcb. - * @param id IRQ id to request to handle. * * @return OK on success, non-zero otherwise. */ @@ -27,3 +26,16 @@ SYSCALL_DEFINE1(irq_req)(struct tcb *t, sys_arg_t id) return_args1(t, register_irq(t, id)); } + +SYSCALL_DEFINE2(req_notification)(struct tcb *t, sys_arg_t tid, sys_arg_t pid) +{ + if (!has_cap(t->caps, CAP_NOTIFICATION)) + return_args1(t, ERR_PERM); + + struct tcb *r = get_tcb(tid); + if (!r) + return_args1(t, ERR_INVAL); + + t->notify_id = pid; + return_args1(t, OK); +} diff --git a/src/uapi/proc.c b/src/uapi/proc.c index e7fa49d..153b183 100644 --- a/src/uapi/proc.c +++ b/src/uapi/proc.c @@ -37,6 +37,7 @@ SYSCALL_DEFINE5(create)(struct tcb *t, sys_arg_t func, set_args5(c, c->tid, d0, d1, d2, d3); set_return(c, func); + c->notify_id = t->notify_id; return_args2(t, OK, c->tid); } @@ -70,6 +71,7 @@ SYSCALL_DEFINE0(fork)(struct tcb *t) * parent ID as third return value */ set_args3(n, OK, 0, get_eproc(t)->pid); + n->notify_id = c->notify_id; return_args2(t, OK, n->pid); } @@ -132,6 +134,7 @@ SYSCALL_DEFINE2(spawn)(struct tcb *t, sys_arg_t bin, sys_arg_t interp) if (!n) return_args1(t, ERR_OOMEM); + n->notify_id = c->notify_id; return_args2(t, prepare_proc(n, bin, interp), n->pid); } |
