diff options
Diffstat (limited to 'lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp')
-rw-r--r-- | lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp | 744 |
1 files changed, 0 insertions, 744 deletions
diff --git a/lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp b/lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp deleted file mode 100644 index 8da0e1e..0000000 --- a/lib/mlibc/sysdeps/managarm/generic/fork-exec.cpp +++ /dev/null @@ -1,744 +0,0 @@ - -// for _Exit() -#include <stdlib.h> - -#include <string.h> -#include <errno.h> - -// for fork() and execve() -#include <unistd.h> -// for sched_yield() -#include <sched.h> -#include <stdio.h> -// for getrusage() -#include <sys/resource.h> -// for waitpid() -#include <sys/wait.h> -#include <pthread.h> - -#include <bits/ensure.h> -#include <mlibc/allocator.hpp> -#include <mlibc/debug.hpp> -#include <mlibc/posix-pipe.hpp> -#include <mlibc/thread-entry.hpp> -#include <mlibc/all-sysdeps.hpp> -#include <posix.frigg_bragi.hpp> -#include <protocols/posix/supercalls.hpp> - -namespace mlibc { - -int sys_futex_tid() { - HelWord tid = 0; - HEL_CHECK(helSyscall0_1(kHelCallSuper + posix::superGetTid, - &tid)); - - return tid; -} - -int sys_futex_wait(int *pointer, int expected, const struct timespec *time) { - // This implementation is inherently signal-safe. - if(time) { - if(helFutexWait(pointer, expected, time->tv_nsec + time->tv_sec * 1000000000)) - return -1; - return 0; - } - if(helFutexWait(pointer, expected, -1)) - return -1; - return 0; -} - -int sys_futex_wake(int *pointer) { - // This implementation is inherently signal-safe. - if(helFutexWake(pointer)) - return -1; - return 0; -} - -int sys_waitpid(pid_t pid, int *status, int flags, struct rusage *ru, pid_t *ret_pid) { - if(ru) { - mlibc::infoLogger() << "mlibc: struct rusage in sys_waitpid is unsupported" << frg::endlog; - return ENOSYS; - } - - SignalGuard sguard; - - managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); - req.set_request_type(managarm::posix::CntReqType::WAIT); - req.set_pid(pid); - req.set_flags(flags); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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_ARGUMENTS) { - return EINVAL; - } - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - if(status) - *status = resp.mode(); - *ret_pid = resp.pid(); - return 0; -} - -int sys_waitid(idtype_t idtype, id_t id, siginfo_t *info, int options) { - SignalGuard sguard; - - managarm::posix::WaitIdRequest<MemoryAllocator> req(getSysdepsAllocator()); - - req.set_idtype(idtype); - req.set_id(id); - req.set_flags(options); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::WaitIdResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { - return EINVAL; - } - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - info->si_pid = resp.pid(); - info->si_uid = resp.uid(); - info->si_signo = SIGCHLD; - info->si_status = resp.sig_status(); - info->si_code = resp.sig_code(); - return 0; -} - -void sys_exit(int status) { - // This implementation is inherently signal-safe. - HEL_CHECK(helSyscall1(kHelCallSuper + posix::superExit, status)); - __builtin_trap(); -} - -void sys_yield() { - // This implementation is inherently signal-safe. - HEL_CHECK(helYield()); -} - -int sys_sleep(time_t *secs, long *nanos) { - SignalGuard sguard; - globalQueue.trim(); - - uint64_t now; - HEL_CHECK(helGetClock(&now)); - - uint64_t async_id; - HEL_CHECK(helSubmitAwaitClock(now + uint64_t(*secs) * 1000000000 + uint64_t(*nanos), - globalQueue.getQueue(), 0, &async_id)); - - auto element = globalQueue.dequeueSingle(); - auto result = parseSimple(element); - HEL_CHECK(result->error); - - *secs = 0; - *nanos = 0; - - return 0; -} - -int sys_fork(pid_t *child) { - // This implementation is inherently signal-safe. - int res; - - sigset_t full_sigset; - res = sigfillset(&full_sigset); - __ensure(!res); - - sigset_t former_sigset; - res = sigprocmask(SIG_SETMASK, &full_sigset, &former_sigset); - __ensure(!res); - - HelWord out; - HEL_CHECK(helSyscall0_1(kHelCallSuper + posix::superFork, &out)); - *child = out; - - if(!out) { - clearCachedInfos(); - globalQueue.recreateQueue(); - } - - res = sigprocmask(SIG_SETMASK, &former_sigset, nullptr); - __ensure(!res); - - return 0; -} - -int sys_execve(const char *path, char *const argv[], char *const envp[]) { - // TODO: Make this function signal-safe! - frg::string<MemoryAllocator> args_area(getSysdepsAllocator()); - for(auto it = argv; *it; ++it) - args_area += frg::string_view{*it, strlen(*it) + 1}; - - frg::string<MemoryAllocator> env_area(getSysdepsAllocator()); - for(auto it = envp; *it; ++it) - env_area += frg::string_view{*it, strlen(*it) + 1}; - - uintptr_t out; - - HEL_CHECK(helSyscall6_1(kHelCallSuper + posix::superExecve, - reinterpret_cast<uintptr_t>(path), - strlen(path), - reinterpret_cast<uintptr_t>(args_area.data()), - args_area.size(), - reinterpret_cast<uintptr_t>(env_area.data()), - env_area.size(), - &out)); - - return out; -} - -gid_t sys_getgid() { - SignalGuard sguard; - - managarm::posix::GetGidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return resp.uid(); -} - -int sys_setgid(gid_t gid) { - SignalGuard sguard; - - managarm::posix::SetGidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - req.set_uid(gid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::ACCESS_DENIED) { - return EPERM; - }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { - return EINVAL; - }else{ - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return 0; - } -} - -gid_t sys_getegid() { - SignalGuard sguard; - - managarm::posix::GetEgidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return resp.uid(); -} - -int sys_setegid(gid_t egid) { - SignalGuard sguard; - - managarm::posix::SetEgidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - req.set_uid(egid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::ACCESS_DENIED) { - return EPERM; - }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { - return EINVAL; - }else{ - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return 0; - } -} - -uid_t sys_getuid() { - SignalGuard sguard; - - managarm::posix::GetUidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return resp.uid(); -} - -int sys_setuid(uid_t uid) { - SignalGuard sguard; - - managarm::posix::SetUidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - req.set_uid(uid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::ACCESS_DENIED) { - return EPERM; - }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { - return EINVAL; - }else{ - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return 0; - } -} - -uid_t sys_geteuid() { - SignalGuard sguard; - - managarm::posix::GetEuidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return resp.uid(); -} - -int sys_seteuid(uid_t euid) { - SignalGuard sguard; - - managarm::posix::SetEuidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - req.set_uid(euid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::ACCESS_DENIED) { - return EPERM; - }else if(resp.error() == managarm::posix::Errors::ILLEGAL_ARGUMENTS) { - return EINVAL; - }else{ - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return 0; - } -} - -pid_t sys_gettid() { - // TODO: use an actual gettid syscall. - return sys_getpid(); -} - -pid_t sys_getpid() { - SignalGuard sguard; - - managarm::posix::GetPidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return resp.pid(); -} - -pid_t sys_getppid() { - SignalGuard sguard; - - managarm::posix::GetPpidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return resp.pid(); -} - -int sys_getsid(pid_t pid, pid_t *sid) { - SignalGuard sguard; - - managarm::posix::GetSidRequest<MemoryAllocator> req(getSysdepsAllocator()); - req.set_pid(pid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::NO_SUCH_RESOURCE) { - *sid = 0; - return ESRCH; - } else { - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - *sid = resp.pid(); - return 0; - } -} - -int sys_getpgid(pid_t pid, pid_t *pgid) { - SignalGuard sguard; - - managarm::posix::GetPgidRequest<MemoryAllocator> req(getSysdepsAllocator()); - req.set_pid(pid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::NO_SUCH_RESOURCE) { - *pgid = 0; - return ESRCH; - } else { - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - *pgid = resp.pid(); - return 0; - } -} - -int sys_setpgid(pid_t pid, pid_t pgid) { - SignalGuard sguard; - - managarm::posix::SetPgidRequest<MemoryAllocator> req(getSysdepsAllocator()); - - req.set_pid(pid); - req.set_pgid(pgid); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.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::INSUFFICIENT_PERMISSION) { - return EPERM; - }else if(resp.error() == managarm::posix::Errors::NO_SUCH_RESOURCE) { - return ESRCH; - }else if(resp.error() == managarm::posix::Errors::ACCESS_DENIED) { - return EACCES; - }else{ - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - return 0; - } -} - -int sys_getrusage(int scope, struct rusage *usage) { - memset(usage, 0, sizeof(struct rusage)); - - SignalGuard sguard; - - managarm::posix::CntRequest<MemoryAllocator> req(getSysdepsAllocator()); - req.set_request_type(managarm::posix::CntReqType::GET_RESOURCE_USAGE); - req.set_mode(scope); - - auto [offer, send_head, recv_resp] = - exchangeMsgsSync( - getPosixLane(), - helix_ng::offer( - helix_ng::sendBragiHeadOnly(req, getSysdepsAllocator()), - helix_ng::recvInline() - ) - ); - - HEL_CHECK(offer.error()); - HEL_CHECK(send_head.error()); - HEL_CHECK(recv_resp.error()); - - managarm::posix::SvrResponse<MemoryAllocator> resp(getSysdepsAllocator()); - resp.ParseFromArray(recv_resp.data(), recv_resp.length()); - __ensure(resp.error() == managarm::posix::Errors::SUCCESS); - - usage->ru_utime.tv_sec = resp.ru_user_time() / 1'000'000'000; - usage->ru_utime.tv_usec = (resp.ru_user_time() % 1'000'000'000) / 1'000; - - return 0; -} - -int sys_getschedparam(void *tcb, int *policy, struct sched_param *param) { - if(tcb != mlibc::get_current_tcb()) { - return ESRCH; - } - - *policy = SCHED_OTHER; - int prio = 0; - // TODO(no92): use helGetPriority(kHelThisThread) here - mlibc::infoLogger() << "\e[31mlibc: sys_getschedparam always returns priority 0\e[39m" << frg::endlog; - param->sched_priority = prio; - - return 0; -} - -int sys_setschedparam(void *tcb, int policy, const struct sched_param *param) { - if(tcb != mlibc::get_current_tcb()) { - return ESRCH; - } - - if(policy != SCHED_OTHER) { - return EINVAL; - } - - HEL_CHECK(helSetPriority(kHelThisThread, param->sched_priority)); - - return 0; -} - -int sys_clone(void *tcb, pid_t *pid_out, void *stack) { - HelWord pid = 0; - HEL_CHECK(helSyscall2_1(kHelCallSuper + posix::superClone, - reinterpret_cast<HelWord>(__mlibc_start_thread), - reinterpret_cast<HelWord>(stack), - &pid)); - - if (pid_out) - *pid_out = pid; - - return 0; -} - -int sys_tcb_set(void *pointer) { -#if defined(__aarch64__) - uintptr_t addr = reinterpret_cast<uintptr_t>(pointer); - addr += sizeof(Tcb) - 0x10; - asm volatile ("msr tpidr_el0, %0" :: "r"(addr)); -#else - HEL_CHECK(helWriteFsBase(pointer)); -#endif - return 0; -} - -void sys_thread_exit() { - // This implementation is inherently signal-safe. - HEL_CHECK(helSyscall1(kHelCallSuper + posix::superExit, 0)); - __builtin_trap(); -} - -int sys_thread_setname(void *tcb, const char *name) { - if(strlen(name) > 15) { - return ERANGE; - } - - auto t = reinterpret_cast<Tcb *>(tcb); - char *path; - int cs = 0; - - if(asprintf(&path, "/proc/self/task/%d/comm", t->tid) < 0) { - return ENOMEM; - } - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - - int fd; - if(int e = sys_open(path, O_WRONLY, 0, &fd); e) { - return e; - } - - if(int e = sys_write(fd, name, strlen(name) + 1, NULL)) { - return e; - } - - sys_close(fd); - - pthread_setcancelstate(cs, 0); - - return 0; -} - -int sys_thread_getname(void *tcb, char *name, size_t size) { - auto t = reinterpret_cast<Tcb *>(tcb); - char *path; - int cs = 0; - ssize_t real_size = 0; - - if(asprintf(&path, "/proc/self/task/%d/comm", t->tid) < 0) { - return ENOMEM; - } - - pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); - - int fd; - if(int e = sys_open(path, O_RDONLY | O_CLOEXEC, 0, &fd); e) { - return e; - } - - if(int e = sys_read(fd, name, size, &real_size)) { - return e; - } - - name[real_size - 1] = 0; - sys_close(fd); - - pthread_setcancelstate(cs, 0); - - if(static_cast<ssize_t>(size) <= real_size) { - return ERANGE; - } - - return 0; -} - - -} //namespace mlibc - |