aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xarch/riscv64/conf/initbin3512 -> 5312 bytes
-rw-r--r--arch/riscv64/conf/init.c85
-rw-r--r--arch/riscv64/conf/initrdbin4096 -> 5632 bytes
-rw-r--r--arch/riscv64/kernel/csr.h2
-rw-r--r--arch/riscv64/kernel/irq.c10
-rw-r--r--include/kmi/caps.h5
-rw-r--r--include/kmi/notify.h9
-rw-r--r--include/kmi/syscalls.h12
-rw-r--r--include/kmi/tcb.h5
-rw-r--r--include/kmi/uapi.h30
-rw-r--r--src/ipi.c10
-rw-r--r--src/irq.c15
-rw-r--r--src/proc.c2
-rw-r--r--src/timer.c9
-rw-r--r--src/uapi/dispatch.c2
-rw-r--r--src/uapi/ipc.c89
-rw-r--r--src/uapi/irq.c14
-rw-r--r--src/uapi/proc.c3
18 files changed, 222 insertions, 80 deletions
diff --git a/arch/riscv64/conf/init b/arch/riscv64/conf/init
index d04c492..ea63935 100755
--- a/arch/riscv64/conf/init
+++ b/arch/riscv64/conf/init
Binary files differ
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
index c8d7253..72260ef 100644
--- a/arch/riscv64/conf/initrd
+++ b/arch/riscv64/conf/initrd
Binary files differ
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);
+
/** @} */
/**
diff --git a/src/ipi.c b/src/ipi.c
index 59f9fd1..79b363f 100644
--- a/src/ipi.c
+++ b/src/ipi.c
@@ -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 */
}
diff --git a/src/irq.c b/src/irq.c
index db90d34..8d01fbd 100644
--- a/src/irq.c
+++ b/src/irq.c
@@ -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");
}
diff --git a/src/proc.c b/src/proc.c
index b91c486..7bfab0a 100644
--- a/src/proc.c
+++ b/src/proc.c
@@ -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);
}