diff options
author | Ian Moffett <ian@osmora.org> | 2024-03-07 17:28:00 -0500 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-03-07 17:28:32 -0500 |
commit | bd5969fc876a10b18613302db7087ef3c40f18e1 (patch) | |
tree | 7c2b8619afe902abf99570df2873fbdf40a4d1a1 /lib/mlibc/sysdeps/lemon/generic | |
parent | a95b38b1b92b172e6cc4e8e56a88a30cc65907b0 (diff) |
lib: Add mlibc
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'lib/mlibc/sysdeps/lemon/generic')
-rw-r--r-- | lib/mlibc/sysdeps/lemon/generic/entry.cpp | 33 | ||||
-rwxr-xr-x | lib/mlibc/sysdeps/lemon/generic/filesystem.cpp | 406 | ||||
-rw-r--r-- | lib/mlibc/sysdeps/lemon/generic/lemon.cpp | 199 | ||||
-rw-r--r-- | lib/mlibc/sysdeps/lemon/generic/pty.cpp | 63 | ||||
-rw-r--r-- | lib/mlibc/sysdeps/lemon/generic/signals.cpp | 38 | ||||
-rwxr-xr-x | lib/mlibc/sysdeps/lemon/generic/sockets.cpp | 132 | ||||
-rw-r--r-- | lib/mlibc/sysdeps/lemon/generic/thread.cpp | 53 | ||||
-rw-r--r-- | lib/mlibc/sysdeps/lemon/generic/thread_entry.S | 11 |
8 files changed, 935 insertions, 0 deletions
diff --git a/lib/mlibc/sysdeps/lemon/generic/entry.cpp b/lib/mlibc/sysdeps/lemon/generic/entry.cpp new file mode 100644 index 0000000..f4cf144 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/entry.cpp @@ -0,0 +1,33 @@ +#include <stdint.h> +#include <stdlib.h> +#include <bits/ensure.h> +#include <mlibc/elf/startup.h> + +// defined by the POSIX library +void __mlibc_initLocale(); + +extern "C" uintptr_t *__dlapi_entrystack(); + +extern char **environ; +static mlibc::exec_stack_data __mlibc_stack_data; + +struct LibraryGuard { + LibraryGuard(); +}; + +static LibraryGuard guard; + +LibraryGuard::LibraryGuard() { + __mlibc_initLocale(); + + // Parse the exec() stack. + mlibc::parse_exec_stack(__dlapi_entrystack(), &__mlibc_stack_data); + mlibc::set_startup_data(__mlibc_stack_data.argc, __mlibc_stack_data.argv, + __mlibc_stack_data.envp); +} + +extern "C" void __mlibc_entry(int (*main_fn)(int argc, char *argv[], char *env[])) { + // TODO: call __dlapi_enter, otherwise static builds will break (see Linux sysdeps) + auto result = main_fn(__mlibc_stack_data.argc, __mlibc_stack_data.argv, environ); + exit(result); +} diff --git a/lib/mlibc/sysdeps/lemon/generic/filesystem.cpp b/lib/mlibc/sysdeps/lemon/generic/filesystem.cpp new file mode 100755 index 0000000..4a7d780 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/filesystem.cpp @@ -0,0 +1,406 @@ +#include <lemon/syscall.h> + +#include <asm/ioctls.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <dirent.h> +#include <limits.h> +#include <fcntl.h> +#include <string.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> + +namespace mlibc{ + +typedef struct { + dev_t st_dev; + ino_t st_ino; + mode_t st_mode; + nlink_t st_nlink; + uid_t st_uid; + uid_t st_gid; + dev_t st_rdev; + off_t st_size; + int64_t st_blksize; + int64_t st_blocks; +} lemon_stat_t; + +int sys_write(int fd, const void* buffer, size_t count, ssize_t* written){ + long ret = syscall(SYS_WRITE, fd, (uintptr_t)buffer, count); + + if(ret < 0) + return -ret; + + *written = ret; + return 0; +} + +int sys_read(int fd, void *buf, size_t count, ssize_t *bytes_read) { + long ret = syscall(SYS_READ, fd, (uintptr_t)buf, count); + + if(ret < 0){ + *bytes_read = 0; + return -ret; + } + + *bytes_read = ret; + return 0; +} + +int sys_pwrite(int fd, const void* buffer, size_t count, off_t off, ssize_t* written){ + int ret = syscall(SYS_PWRITE, fd, (uintptr_t)buffer, count, 0, off); + + + if(ret < 0){ + return -ret; + } + + *written = ret; + return 0; +} + +int sys_pread(int fd, void *buf, size_t count, off_t off, ssize_t *bytes_read) { + int ret = syscall(SYS_PREAD, fd, (uintptr_t)buf, count, 0, off); + + if(ret < 0){ + return -ret; + } + + *bytes_read = ret; + return 0; +} + +int sys_seek(int fd, off_t offset, int whence, off_t *new_offset) { + long ret = syscall(SYS_LSEEK, fd, offset, whence); + + if(ret < 0){ + return -ret; + } + + *new_offset = ret; + return 0; +} + + +int sys_open(const char* filename, int flags, mode_t mode, int* fd){ + long ret = syscall(SYS_OPEN, (uintptr_t)filename, flags); + + if(ret < 0) + return -ret; + + *fd = ret; + + return 0; +} + +int sys_close(int fd){ + syscall(SYS_CLOSE, fd); + return 0; +} + +int sys_access(const char* filename, int mode){ + int fd; + if(int e = sys_open(filename, O_RDONLY, 0, &fd)){ + return e; + } + + sys_close(fd); + return 0; +} + +int sys_stat(fsfd_target fsfdt, int fd, const char *path, int flags, struct stat *statbuf){ + long ret = 0; + + lemon_stat_t lemonStat; + switch(fsfdt){ + case fsfd_target::fd: + ret = syscall(SYS_FSTAT, &lemonStat, fd); + break; + case fsfd_target::path: + ret = syscall(SYS_STAT, &lemonStat, path); + break; + default: + mlibc::infoLogger() << "mlibc warning: sys_stat: unsupported fsfd target" << frg::endlog; + return EINVAL; + } + + statbuf->st_dev = lemonStat.st_dev; + statbuf->st_ino = lemonStat.st_ino; + statbuf->st_mode = lemonStat.st_mode; + statbuf->st_nlink = lemonStat.st_nlink; + statbuf->st_uid = lemonStat.st_uid; + statbuf->st_gid = lemonStat.st_gid; + statbuf->st_rdev = lemonStat.st_rdev; + statbuf->st_size = lemonStat.st_size; + statbuf->st_blksize = lemonStat.st_blksize; + statbuf->st_blocks = lemonStat.st_blocks; + + return -ret; +} + +int sys_ioctl(int fd, unsigned long request, void *arg, int *result){ + long ret = syscall(SYS_IOCTL, fd, request, arg, result); + + if(ret < 0) + return -ret; + + return 0; +} + +#ifndef MLIBC_BUILDING_RTDL + +int sys_poll(struct pollfd *fds, nfds_t count, int timeout, int *num_events){ + long ret = syscall(SYS_POLL, fds, count, timeout); + + if(ret < 0){ + return -ret; + } + + *num_events = ret; + + return 0; +} + +int sys_mkdir(const char* path, mode_t){ + long ret = syscall(SYS_MKDIR, path); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_rmdir(const char* path){ + long ret = syscall(SYS_RMDIR, path); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_link(const char* srcpath, const char* destpath){ + long ret = syscall(SYS_LINK, srcpath, destpath); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_unlinkat(int fd, const char *path, int flags) { + long ret = syscall(SYS_UNLINK, fd, path, flags); + + if(ret < 0) { + return -ret; + } + + return 0; +} + +typedef struct lemon_dirent { + uint32_t inode; // Inode number + uint32_t type; + char name[NAME_MAX]; // Filename +} lemon_dirent_t; + +int sys_read_entries(int handle, void *buffer, size_t max_size, size_t *bytes_read){ + lemon_dirent_t lemonDirent; + long ret = syscall(SYS_READDIR_NEXT, handle, &lemonDirent); + + if(!ret){ + *bytes_read = 0; + return 0; + } else if(ret > 0){ + dirent* dir = (dirent*)buffer; + strcpy(dir->d_name, lemonDirent.name); + dir->d_ino = lemonDirent.inode; + dir->d_off = 0; + dir->d_reclen = sizeof(dirent); + dir->d_type = lemonDirent.type; + + *bytes_read = sizeof(dirent); + return 0; + } else { + return -ret; + } +} + +int sys_open_dir(const char* path, int* handle){ + return sys_open(path, O_DIRECTORY, 0, handle); +} + +int sys_rename(const char* path, const char* new_path){ + return -syscall(SYS_RENAME, path, new_path); +} + +int sys_readlink(const char *path, void *buffer, size_t max_size, ssize_t *length){ + long ret = syscall(SYS_READLINK, path, buffer, max_size); + if(ret < 0){ + return -ret; + } + + *length = ret; + return 0; +} + +int sys_dup(int fd, int flags, int* newfd){ + int ret = syscall(SYS_DUP, fd, flags, -1); + if(ret < 0){ + return -ret; + } + + *newfd = ret; + return 0; +} + +int sys_dup2(int fd, int flags, int newfd){ + int ret = syscall(SYS_DUP, fd, flags, newfd); + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_fcntl(int fd, int request, va_list args, int* result){ + if(request == F_DUPFD){ + return sys_dup(fd, 0, result); + } else if (request == F_DUPFD_CLOEXEC) { + return sys_dup(fd, O_CLOEXEC, result); + } else if(request == F_GETFD){ + *result = 0; + return 0; + } else if(request == F_SETFD){ + if(va_arg(args, int) & FD_CLOEXEC) { + return sys_ioctl(fd, FIOCLEX, NULL, result); + } else { + return sys_ioctl(fd, FIONCLEX, NULL, result); + } + } else if(request == F_GETFL){ + int ret = syscall(SYS_GET_FILE_STATUS_FLAGS, fd); + if(ret < 0){ + return -ret; + } + + *result = ret; + return 0; + } else if(request == F_SETFL){ + int ret = syscall(SYS_SET_FILE_STATUS_FLAGS, fd, va_arg(args, int)); + return -ret; + } else { + infoLogger() << "mlibc: sys_fcntl unsupported request (" << request << ")" << frg::endlog; + return EINVAL; + } +} + +int sys_pselect(int nfds, fd_set* readfds, fd_set* writefds, + fd_set *exceptfds, const struct timespec* timeout, const sigset_t* sigmask, int *num_events){ + int ret = syscall(SYS_SELECT, nfds, readfds, writefds, exceptfds, timeout); + if(ret < 0){ + return -ret; + } + + *num_events = ret; + return 0; +} + +int sys_chmod(const char *pathname, mode_t mode){ + int ret = syscall(SYS_CHMOD, pathname, mode); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_pipe(int *fds, int flags){ + return -syscall(SYS_PIPE, fds, flags); +} + +int sys_epoll_create(int flags, int *fd) { + int ret = syscall(SYS_EPOLL_CREATE, flags); + + if(ret < 0){ + return -ret; + } + + *fd = ret; + + return 0; +} + +int sys_epoll_ctl(int epfd, int mode, int fd, struct epoll_event *ev) { + int ret = syscall(SYS_EPOLL_CTL, epfd, mode, fd, ev); + + if(ret < 0) { + return -ret; + } + + return 0; +} + +int sys_epoll_pwait(int epfd, struct epoll_event *ev, int n, + int timeout, const sigset_t *sigmask, int *raised) { + int ret = syscall(SYS_EPOLL_WAIT, epfd, ev, n, timeout, sigmask); + + if(ret < 0) { + return -ret; + } + + *raised = ret; + + return 0; +} + +int sys_ttyname(int tty, char *buf, size_t size) { + char path[PATH_MAX] = {"/dev/pts/"}; + + struct stat stat; + if(int e = sys_stat(fsfd_target::fd, tty, nullptr, 0, &stat)) { + return e; + } + + if(!S_ISCHR(stat.st_mode)) { + return ENOTTY; // Not a char device, isn't a tty + } + + if(sys_isatty(tty)) { + return ENOTTY; + } + + // Look for tty in /dev/pts + int ptDir = open("/dev/pts", O_DIRECTORY); + __ensure(ptDir >= 0); + + struct dirent dirent; + size_t direntBytesRead; + while(!sys_read_entries(ptDir, &dirent, sizeof(dirent), &direntBytesRead) && direntBytesRead) { + // Compare the inodes + if(dirent.d_ino == stat.st_ino) { + __ensure(strlen(path) + strlen(dirent.d_name) < PATH_MAX); + strcat(path, dirent.d_name); + + strncpy(buf, path, size); + return 0; + } + } + + // Could not find corresponding TTY in /dev/pts + return ENODEV; +} + +int sys_fchdir(int fd) { + return syscall(SYS_FCHDIR, fd); +} +#endif + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/lemon.cpp b/lib/mlibc/sysdeps/lemon/generic/lemon.cpp new file mode 100644 index 0000000..8f15ff1 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/lemon.cpp @@ -0,0 +1,199 @@ +#include <lemon/syscall.h> +#include <stddef.h> +#include <bits/ensure.h> +#include <abi-bits/pid_t.h> +#include <mlibc/debug.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/thread-entry.hpp> +#include <errno.h> +#include <sys/resource.h> + +namespace mlibc{ + +int sys_futex_tid(){ + return syscall(SYS_GETTID); +} + +int sys_futex_wait(int *pointer, int expected, const struct timespec *time){ + return syscall(SYS_FUTEX_WAIT, pointer, expected); +} + +int sys_futex_wake(int *pointer) { + return syscall(SYS_FUTEX_WAKE, pointer); +} + +int sys_tcb_set(void* pointer){ + syscall(SYS_SET_FS_BASE, (uintptr_t)pointer); + return 0; +} + +int sys_vm_map(void *hint, size_t size, int prot, int flags, int fd, off_t offset, void **window) { + __ensure(flags & MAP_ANONYMOUS); + + return syscall(SYS_MMAP, (uintptr_t)window, (size + 0xFFF) & ~static_cast<size_t>(0xFFF), (uintptr_t)hint, flags); +} + +int sys_vm_unmap(void* address, size_t size) { + __ensure(!(size & 0xFFF)); + + long ret = syscall(SYS_MUNMAP, (uintptr_t)address, (size + 0xFFF) & ~static_cast<size_t>(0xFFF)); + + return ret; +} + +int sys_anon_allocate(size_t size, void **pointer) { + return sys_vm_map(nullptr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, -1, 0, pointer); +} + +int sys_anon_free(void *pointer, size_t size) { + return sys_vm_unmap(pointer, size); +} + +void sys_libc_panic(){ + sys_libc_log("libc panic!"); + __builtin_trap(); + for(;;); +} + +void sys_libc_log(const char* msg){ + syscall(0, (uintptr_t)msg); +} + +#ifndef MLIBC_BUILDING_RTDL + +void sys_exit(int status){ + syscall(SYS_EXIT, status); + + __builtin_unreachable(); +} + +pid_t sys_getpid(){ + uint64_t _pid; + syscall(SYS_GETPID, (uintptr_t)&_pid); + + pid_t pid = _pid; + return pid; +} + +pid_t sys_getppid(){ + return syscall(SYS_GETPPID); +} + +int sys_clock_get(int clock, time_t *secs, long *nanos) { + syscall(SYS_UPTIME, nanos); + + *secs = (*nanos) / 1000000000; + *nanos = (*nanos) - (*secs) * 1000000000; + + return 0; +} + +int sys_getcwd(char *buffer, size_t size){ + return syscall(SYS_GET_CWD, buffer, size); +} + +int sys_chdir(const char *path){ + syscall(SYS_CHDIR, path); + return 0; +} + +int sys_sleep(time_t* sec, long* nanosec){ + syscall(SYS_NANO_SLEEP, (*sec) * 1000000000 + (*nanosec)); + return 0; +} + +uid_t sys_getuid(){ + return syscall(SYS_GETUID); +} + +uid_t sys_geteuid(){ + return syscall(SYS_GETEUID); +} + +int sys_setuid(uid_t uid){ + return -syscall(SYS_SETUID, uid); +} + +int sys_seteuid(uid_t euid){ + return -syscall(SYS_SETEUID, euid); +} + +gid_t sys_getgid(){ + return syscall(SYS_GETGID); +} + +gid_t sys_getegid(){ + return syscall(SYS_GETEGID); +} + +int sys_setgid(gid_t gid){ + mlibc::infoLogger() << "mlibc: sys_setgid is a stub" << frg::endlog; + return 0; +} + +int sys_setegid(gid_t egid){ + mlibc::infoLogger() << "mlibc: sys_setegid is a stub" << frg::endlog; + return 0; +} + +void sys_yield(){ + syscall(SYS_YIELD); +} + +int sys_clone(void *tcb, pid_t *tid_out, void *stack){ + pid_t tid = syscall(SYS_SPAWN_THREAD, __mlibc_start_thread, stack); + + if(tid < 0){ + errno = tid; + return -1; + } + + *tid_out = tid; + + return 0; +} + +void sys_thread_exit(){ + syscall(SYS_EXIT_THREAD); + + __builtin_unreachable(); +} + +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; + } + + pid_t ret = syscall(SYS_WAIT_PID, pid, status, flags); + + if(ret < 0){ + return -ret; + } + + *ret_pid = ret; + + return 0; +} + +int sys_fork(pid_t *child){ + long pid = syscall(SYS_FORK, 0); + if(pid < 0){ + errno = pid; + return -1; + } + + *child = pid; + return 0; +} + +int sys_execve(const char *path, char *const argv[], char *const envp[]){ + return -syscall(SYS_EXECVE, path, argv, envp); +} + +int sys_getentropy(void *buffer, size_t length){ + return -syscall(SYS_GETENTROPY, buffer, length); +} +#endif + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/pty.cpp b/lib/mlibc/sysdeps/lemon/generic/pty.cpp new file mode 100644 index 0000000..794f74f --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/pty.cpp @@ -0,0 +1,63 @@ +#include <asm/ioctls.h> +#include <sys/ioctl.h> + +#include <errno.h> + +#include <bits/ensure.h> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/debug.hpp> + +#include <stdio.h> + +namespace mlibc { + +int sys_isatty(int fd) { + struct winsize ws; + long ret = sys_ioctl(fd, TIOCGWINSZ, &ws, 0); + + if(!ret) return 0; + + return ENOTTY; +} + +int sys_tcgetattr(int fd, struct termios *attr) { + if(int e = sys_isatty(fd)) + return e; + + int ret; + sys_ioctl(fd, TCGETS, attr, &ret); + + if(ret) + return -ret; + + return 0; +} + +int sys_tcsetattr(int fd, int optional_action, const struct termios *attr) { + if(int e = sys_isatty(fd)) + return e; + + if(optional_action){ + mlibc::infoLogger() << "mlibc warning: sys_tcsetattr ignores optional_action" << frg::endlog; + } + + int ret; + sys_ioctl(fd, TCSETS, const_cast<struct termios*>(attr), &ret); + + if(ret) + return -ret; + + return 0; +} + +int sys_ptsname(int fd, char *buffer, size_t length) { + int index; + if(int e = sys_ioctl(fd, TIOCGPTN, &index, NULL); e) + return e; + if((size_t)snprintf(buffer, length, "/dev/pts/%d", index) >= length) { + return ERANGE; + } + return 0; +} + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/signals.cpp b/lib/mlibc/sysdeps/lemon/generic/signals.cpp new file mode 100644 index 0000000..46b4714 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/signals.cpp @@ -0,0 +1,38 @@ +#include <lemon/syscall.h> + +#include <sys/types.h> + +#include <mlibc/ansi-sysdeps.hpp> + +namespace mlibc{ + +int sys_sigprocmask(int how, const sigset_t *__restrict set, + sigset_t *__restrict retrieve){ + int ret = syscall(SYS_SIGPROCMASK, how, set, retrieve); + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_sigaction(int signal, const struct sigaction *__restrict action, + struct sigaction *__restrict oldAction) { + int ret = syscall(SYS_SIGNAL_ACTION, signal, action, oldAction); + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_kill(int pid, int signal){ + int ret = syscall(SYS_KILL, pid, signal); + if(ret < 0){ + return -ret; + } + + return 0; +} + +}
\ No newline at end of file diff --git a/lib/mlibc/sysdeps/lemon/generic/sockets.cpp b/lib/mlibc/sysdeps/lemon/generic/sockets.cpp new file mode 100755 index 0000000..7244218 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/sockets.cpp @@ -0,0 +1,132 @@ +#include <lemon/syscall.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> + +#include <mlibc/all-sysdeps.hpp> + +namespace { + +int fcntl_helper(int fd, int request, int *result, ...) { + va_list args; + va_start(args, result); + if(!mlibc::sys_fcntl) { + return ENOSYS; + } + int ret = mlibc::sys_fcntl(fd, request, args, result); + va_end(args); + return ret; +} + +} + +namespace mlibc{ + +int sys_socket(int domain, int type, int protocol, int *fd){ + long ret = syscall(SYS_SOCKET, domain, type, protocol); + + if(ret < 0){ + return -ret; + } + + *fd = ret; + + return 0; +} + +int sys_bind(int sockfd, const struct sockaddr *addr_ptr, socklen_t addrlen){ + return syscall(SYS_BIND, sockfd, addr_ptr, addrlen); +} + +int sys_connect(int sockfd, const struct sockaddr *addr_ptr, socklen_t addrlen){ + return syscall(SYS_CONNECT, sockfd, addr_ptr, addrlen); +} + +int sys_accept(int fd, int *newfd, struct sockaddr *addr_ptr, socklen_t *addr_length, int flags){ + long ret = syscall(SYS_ACCEPT, fd); + + if(ret < 0){ + return -ret; + } + + *newfd = ret; + + if(flags & SOCK_NONBLOCK) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFL, &fcntl_ret); + fcntl_helper(*newfd, F_SETFL, &fcntl_ret, fcntl_ret | O_NONBLOCK); + } + + if(flags & SOCK_CLOEXEC) { + int fcntl_ret = 0; + fcntl_helper(*newfd, F_GETFD, &fcntl_ret); + fcntl_helper(*newfd, F_SETFD, &fcntl_ret, fcntl_ret | FD_CLOEXEC); + } + + return 0; +} + +int sys_listen(int fd, int backlog){ + return syscall(SYS_LISTEN, fd, backlog); +} + +int sys_msg_recv(int sockfd, struct msghdr *hdr, int flags, ssize_t *length){ + long ret = syscall(SYS_RECVMSG, sockfd, hdr, flags); + + if(ret < 0){ + return -ret; + } + + *length = ret; + + return 0; +} + +int sys_msg_send(int sockfd, const struct msghdr *hdr, int flags, ssize_t *length){ + long ret = syscall(SYS_SENDMSG, sockfd, hdr, flags); + + if(ret < 0){ + return -ret; + } + + *length = ret; + + return 0; +} + +int sys_setsockopt(int fd, int layer, int number, const void *buffer, socklen_t size){ + long ret = syscall(SYS_SET_SOCKET_OPTIONS, fd, layer, number, buffer, size); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_getsockopt(int fd, int layer, int number, void *__restrict buffer, socklen_t *__restrict size){ + long ret = syscall(SYS_GET_SOCKET_OPTIONS, fd, layer, number, buffer, size); + + if(ret < 0){ + return -ret; + } + + return 0; +} + +int sys_socketpair(int domain, int type_and_flags, int proto, int *fds){ + return -syscall(SYS_SOCKETPAIR, domain, type_and_flags, proto, fds); +} + +int sys_sockname(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + return -syscall(SYS_SOCKNAME, fd, addr_ptr, max_addr_length); +} + +int sys_peername(int fd, struct sockaddr *addr_ptr, socklen_t max_addr_length, + socklen_t *actual_length) { + return -syscall(SYS_PEERNAME, fd, addr_ptr, max_addr_length); +} + +} diff --git a/lib/mlibc/sysdeps/lemon/generic/thread.cpp b/lib/mlibc/sysdeps/lemon/generic/thread.cpp new file mode 100644 index 0000000..42cd758 --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/thread.cpp @@ -0,0 +1,53 @@ +#include <mlibc/thread-entry.hpp> +#include <mlibc/all-sysdeps.hpp> +#include <mlibc/tcb.hpp> +#include <bits/ensure.h> +#include <sys/mman.h> +#include <stdint.h> +#include <stddef.h> + +extern "C" void __mlibc_enter_thread(void *entry, void *user_arg, Tcb *tcb) { + // Wait until our parent sets up the TID. + while(!__atomic_load_n(&tcb->tid, __ATOMIC_RELAXED)) + mlibc::sys_futex_wait(&tcb->tid, 0, nullptr); + + if(mlibc::sys_tcb_set(tcb)) + __ensure(!"sys_tcb_set() failed"); + + tcb->invokeThreadFunc(entry, user_arg); + + auto self = reinterpret_cast<Tcb *>(tcb); + + __atomic_store_n(&self->didExit, 1, __ATOMIC_RELEASE); + mlibc::sys_futex_wake(&self->didExit); + + mlibc::sys_thread_exit(); +} + +namespace mlibc { + +static constexpr size_t default_stacksize = 0x200000; + +int sys_prepare_stack(void **stack, void *entry, void *user_arg, void *tcb, size_t *stack_size, size_t *guard_size, void **stack_base) { + if (!*stack_size) + *stack_size = default_stacksize; + *guard_size = 0; + + if (*stack) { + *stack_base = *stack; + } else { + *stack_base = mmap(nullptr, *stack_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + } + + uintptr_t *sp = reinterpret_cast<uintptr_t *>(reinterpret_cast<uintptr_t>(*stack_base) + *stack_size); + + *--sp = reinterpret_cast<uintptr_t>(tcb); + *--sp = reinterpret_cast<uintptr_t>(user_arg); + *--sp = reinterpret_cast<uintptr_t>(entry); + *stack = reinterpret_cast<void*>(sp); + return 0; +} + +} //namespace mlibc diff --git a/lib/mlibc/sysdeps/lemon/generic/thread_entry.S b/lib/mlibc/sysdeps/lemon/generic/thread_entry.S new file mode 100644 index 0000000..51e703b --- /dev/null +++ b/lib/mlibc/sysdeps/lemon/generic/thread_entry.S @@ -0,0 +1,11 @@ + +.section .text +.global __mlibc_start_thread +__mlibc_start_thread: + pop %rdi + pop %rsi + pop %rdx + call __mlibc_enter_thread + +.section .note.GNU-stack,"",%progbits + |