9a9b91c940
It's finally done.. Signed-off-by: kaguya <vpshinomiya@protonmail.com>
196 lines
5.1 KiB
C++
196 lines
5.1 KiB
C++
#include <bits/ensure.h>
|
|
#include <errno.h>
|
|
#include <signal.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include <hel-syscalls.h>
|
|
#include <hel.h>
|
|
|
|
#include <mlibc/all-sysdeps.hpp>
|
|
#include <mlibc/allocator.hpp>
|
|
#include <mlibc/debug.hpp>
|
|
#include <mlibc/posix-pipe.hpp>
|
|
#include <posix.frigg_bragi.hpp>
|
|
|
|
#include <bragi/helpers-frigg.hpp>
|
|
#include <helix/ipc-structs.hpp>
|
|
|
|
#include <protocols/posix/supercalls.hpp>
|
|
|
|
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<const HelWord *>(set),
|
|
&former,
|
|
&unused
|
|
));
|
|
} else {
|
|
HEL_CHECK(helSyscall2_2(kHelObserveSuperCall + posix::superSigMask, 0, 0, &former, &unused)
|
|
);
|
|
}
|
|
if (retrieve)
|
|
*reinterpret_cast<uint64_t *>(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<MemoryAllocator> 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<const uint64_t *>(&action->sa_mask));
|
|
if (action->sa_flags & SA_SIGINFO) {
|
|
req.set_sig_handler(reinterpret_cast<uintptr_t>(action->sa_sigaction));
|
|
} else {
|
|
req.set_sig_handler(reinterpret_cast<uintptr_t>(action->sa_handler));
|
|
}
|
|
req.set_sig_restorer(reinterpret_cast<uintptr_t>(&__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<MemoryAllocator> 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<uint64_t *>(&saved_action->sa_mask) = resp.sig_mask();
|
|
if (resp.flags() & SA_SIGINFO) {
|
|
saved_action->sa_sigaction =
|
|
reinterpret_cast<void (*)(int, siginfo_t *, void *)>(resp.sig_handler());
|
|
} else {
|
|
saved_action->sa_handler = reinterpret_cast<void (*)(int)>(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<HelWord>(ss),
|
|
reinterpret_cast<HelWord>(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<const HelWord *>(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<uint64_t *>(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<const HelWord *>(set),
|
|
nanos,
|
|
reinterpret_cast<HelWord>(info),
|
|
&status,
|
|
&signal
|
|
));
|
|
|
|
if (status)
|
|
return status;
|
|
|
|
*out_signal = signal;
|
|
return 0;
|
|
}
|
|
|
|
} // namespace mlibc
|