+ return true;
+}
+
+__DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
+{
+ struct sigctx* sigctx = ¤t_thread->sigctx;
+ struct sigact* active = active_signal(current_thread);
+
+ /* We choose signal#0 as our base case, that is sig#0 means no signal.
+ Therefore, it is an ill situation to return from such sigctx.
+ */
+ if (!active) {
+ signal_terminate(SIGSEGV);
+ schedule();
+ }
+
+ current_thread->intr_ctx = sig_ctx->saved_ictx;
+ if (proc_terminated(__current)) {
+ __current->exit_code |= PEXITSIG;
+ } else if (sigset_test(CORE, sig_ctx->sig_num)) {
+ signal_terminate(sig_ctx->sig_num);
+ }
+
+ ptr_t ictx = (ptr_t)current_thread->intr_ctx;
+
+ /*
+ Ensure our restored context is within kernel stack
+
+ This prevent user to forge their own context such that arbitrary code
+ can be executed as supervisor level
+ */
+ if (!within_kstack(ictx)) {
+ signal_terminate(SIGSEGV);
+ }
+
+ sigactive_pop(current_thread);
+
+ schedule();
+
+ // never reach!
+ return 0;
+}
+
+__DEFINE_LXSYSCALL3(
+ int, sigprocmask, int, how, const sigset_t, *set, sigset_t, *oldset)
+{
+ // TODO maybe it is a good opportunity to introduce a process-wide
+ // signal mask?
+
+ if (signal_set_sigmask(current_thread, how, oldset, set)) {
+ return 0;
+ }
+
+ syscall_result(EINVAL);
+ return -1;
+}
+
+__DEFINE_LXSYSCALL3(
+ int, th_sigmask, int, how, const sigset_t, *set, sigset_t, *oldset)
+{
+ if (signal_set_sigmask(current_thread, how, oldset, set)) {
+ return 0;
+ }
+
+ return EINVAL;