#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C" void __mlibc_signal_restore(); namespace mlibc { int sys_sigprocmask(int how, const sigset_t *set, sigset_t *retrieve) { // This implementation is inherently signal-safe. uint64_t former, unused; if (set) { HEL_CHECK(helSyscall2_2( kHelObserveSuperCall + posix::superSigMask, how, *reinterpret_cast(set), &former, &unused )); } else { HEL_CHECK(helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, 0, 0, &former, &unused) ); } if (retrieve) *reinterpret_cast(retrieve) = former; return 0; } int sys_sigaction( int number, const struct sigaction *__restrict action, struct sigaction *__restrict saved_action ) { SignalGuard sguard; // TODO: Respect restorer. __ensure(!(action->sa_flags & SA_RESTORER)); managarm::posix::CntRequest req(getSysdepsAllocator()); req.set_request_type(managarm::posix::CntReqType::SIG_ACTION); req.set_sig_number(number); if (action) { req.set_mode(1); req.set_flags(action->sa_flags); req.set_sig_mask(*reinterpret_cast(&action->sa_mask)); if (action->sa_flags & SA_SIGINFO) { req.set_sig_handler(reinterpret_cast(action->sa_sigaction)); } else { req.set_sig_handler(reinterpret_cast(action->sa_handler)); } req.set_sig_restorer(reinterpret_cast(&__mlibc_signal_restore)); } else { req.set_mode(0); } auto [offer, send_req, recv_resp] = exchangeMsgsSync( getPosixLane(), helix_ng::offer( helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), helix_ng::recvInline() ) ); HEL_CHECK(offer.error()); HEL_CHECK(send_req.error()); HEL_CHECK(recv_resp.error()); managarm::posix::SvrResponse resp(getSysdepsAllocator()); resp.ParseFromArray(recv_resp.data(), recv_resp.length()); if (resp.error() == managarm::posix::Errors::ILLEGAL_REQUEST) { // This is only returned for servers, not for normal userspace. return ENOSYS; } else if (resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { return EINVAL; } __ensure(resp.error() == managarm::posix::Errors::SUCCESS); if (saved_action) { saved_action->sa_flags = resp.flags(); *reinterpret_cast(&saved_action->sa_mask) = resp.sig_mask(); if (resp.flags() & SA_SIGINFO) { saved_action->sa_sigaction = reinterpret_cast(resp.sig_handler()); } else { saved_action->sa_handler = reinterpret_cast(resp.sig_handler()); } // TODO: saved_action->sa_restorer = resp.sig_restorer; } return 0; } int sys_kill(int pid, int number) { // This implementation is inherently signal-safe. HelWord out; HEL_CHECK(helSyscall2_1(kHelObserveSuperCall + posix::superSigKill, pid, number, &out)); return out; } int sys_tgkill(int, int tid, int number) { return sys_kill(tid, number); } int sys_sigaltstack(const stack_t *ss, stack_t *oss) { HelWord out; // This implementation is inherently signal-safe. HEL_CHECK(helSyscall2_1( kHelObserveSuperCall + posix::superSigAltStack, reinterpret_cast(ss), reinterpret_cast(oss), &out )); return out; } int sys_sigsuspend(const sigset_t *set) { // SignalGuard sguard; uint64_t former, seq, unused; HEL_CHECK(helSyscall2_2( kHelObserveSuperCall + posix::superSigMask, SIG_SETMASK, *reinterpret_cast(set), &former, &seq )); HEL_CHECK(helSyscall1(kHelObserveSuperCall + posix::superSigSuspend, seq)); HEL_CHECK(helSyscall2_2( kHelObserveSuperCall + posix::superSigMask, SIG_SETMASK, former, &unused, &unused )); return EINTR; } int sys_sigpending(sigset_t *set) { uint64_t pendingMask; HEL_CHECK(helSyscall0_1(kHelObserveSuperCall + posix::superSigGetPending, &pendingMask)); *reinterpret_cast(set) = pendingMask; return 0; } int sys_pause() { HelWord set = 0; uint64_t former, seq; // no-op to obtain a seqnum HEL_CHECK( helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, SIG_BLOCK, set, &former, &seq) ); HEL_CHECK(helSyscall1(kHelObserveSuperCall + posix::superSigSuspend, seq)); return EINTR; } int sys_sigtimedwait( const sigset_t *__restrict set, siginfo_t *__restrict info, const struct timespec *__restrict timeout, int *out_signal ) { uint64_t nanos = timeout ? (timeout->tv_nsec + timeout->tv_sec * 1'000'000'000) : UINT64_MAX; HelWord status; HelWord signal; HEL_CHECK(helSyscall3_2( kHelObserveSuperCall + posix::superSigTimedWait, *reinterpret_cast(set), nanos, reinterpret_cast(info), &status, &signal )); if (status) return status; *out_signal = signal; return 0; } } // namespace mlibc