user: implement mlibc as the libc, finally.

It's finally done..

Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
kaguya
2026-05-02 03:31:49 -04:00
parent 2fa39ad85a
commit 9a9b91c940
2387 changed files with 152741 additions and 315 deletions
@@ -0,0 +1,195 @@
#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