فهرست منبع

feat: poll() and llseek() for busybox shell

update init_script so that we use busybox shell

we now support .profile so we don't need to type busybox ls now!
greatbridf 11 ماه پیش
والد
کامیت
7efa80fa12
6فایلهای تغییر یافته به همراه145 افزوده شده و 3 حذف شده
  1. 35 0
      gblibc/include/poll.h
  2. 2 0
      gblibc/include/sys/types.h
  3. 3 0
      include/kernel/tty.hpp
  4. 15 1
      init_script.sh
  5. 71 0
      src/kernel/syscall.cpp
  6. 19 2
      src/kernel/tty.cpp

+ 35 - 0
gblibc/include/poll.h

@@ -0,0 +1,35 @@
+#ifndef __GBLIBC_POLL_H_
+#define __GBLIBC_POLL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int nfds_t;
+
+#define POLLIN          0x0001          /* any readable data available */
+#define POLLPRI         0x0002          /* OOB/Urgent readable data */
+#define POLLOUT         0x0004          /* file descriptor is writeable */
+#define POLLRDNORM      0x0040          /* non-OOB/URG data available */
+#define POLLWRNORM      POLLOUT         /* no write type differentiation */
+#define POLLRDBAND      0x0080          /* OOB/Urgent readable data */
+#define POLLWRBAND      0x0100          /* OOB/Urgent data can be written */
+
+#define POLLERR         0x0008          /* some poll error occurred */
+#define POLLHUP         0x0010          /* file descriptor was "hung up" */
+#define POLLNVAL        0x0020          /* requested events "invalid" */
+
+#define POLLSTANDARD    (POLLIN|POLLPRI|POLLOUT|POLLRDNORM|POLLRDBAND|\
+	                 POLLWRBAND|POLLERR|POLLHUP|POLLNVAL)
+
+struct pollfd {
+	int     fd;
+	short   events;
+	short   revents;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 2 - 0
gblibc/include/sys/types.h

@@ -19,6 +19,8 @@ typedef unsigned long nlink_t;
 typedef uint64_t ino64_t;
 typedef int64_t off64_t;
 
+typedef off64_t loff_t;
+
 #ifdef __cplusplus
 }
 #endif

+ 3 - 0
include/kernel/tty.hpp

@@ -38,6 +38,9 @@ public:
 
     void clear_read_buf(void);
 
+    // TODO: formal poll support
+    int poll();
+
     constexpr void set_pgrp(pid_t pgid)
     {
         fg_pgroup = pgid;

+ 15 - 1
init_script.sh

@@ -22,5 +22,19 @@ cat > /etc/group <<EOF
 root:x:0:root
 EOF
 
-exec /mnt/init /mnt/busybox_ sh \
+cat > /root/.profile <<EOF
+export PATH=/mnt
+export HOME=/root
+
+export BUSYBOX=/mnt/busybox
+
+alias ls="$BUSYBOX ls "
+alias ll="$BUSYBOX ls -l "
+alias la="$BUSYBOX ls -la "
+
+alias cat="$BUSYBOX cat "
+alias clear="$BUSYBOX clear "
+EOF
+
+exec /mnt/init /mnt/busybox sh -l \
     < /dev/console > /dev/console 2> /dev/console

+ 71 - 0
src/kernel/syscall.cpp

@@ -3,6 +3,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <poll.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
@@ -1065,6 +1066,74 @@ int _syscall_mknod(interrupt_stack* data)
     return fs::vfs_mknode(dent, filename.c_str(), mode, dev);
 }
 
+int _syscall_poll(interrupt_stack* data)
+{
+    SYSCALL_ARG1(struct pollfd* __user, fds);
+    SYSCALL_ARG2(nfds_t, nfds);
+    SYSCALL_ARG3(int, timeout);
+
+    if (nfds == 0)
+        return 0;
+
+    if (nfds > 1) {
+        NOT_IMPLEMENTED;
+        return -EINVAL;
+    }
+
+    // TODO: handle timeout
+    // if (timeout != -1) {
+    // }
+
+    // for now, we will poll from console only
+    int ret = console->poll();
+    if (ret < 0)
+        return ret;
+
+    fds[0].revents = POLLIN;
+    return ret;
+
+    // TODO: check address validity
+    // TODO: poll multiple fds and other type of files
+    // for (nfds_t i = 0; i < nfds; ++i) {
+    //     auto& pfd = fds[i];
+
+    //     auto* file = current_process->files[pfd.fd];
+    //     if (!file || !S_ISCHR(file->mode))
+    //         return -EINVAL;
+
+    //     // poll the fds
+    // }
+    //
+    // return 0;
+}
+
+int _syscall_llseek(interrupt_stack* data)
+{
+    SYSCALL_ARG1(unsigned int, fd);
+    SYSCALL_ARG2(unsigned long, offset_high);
+    SYSCALL_ARG3(unsigned long, offset_low);
+    SYSCALL_ARG4(loff_t*, result);
+    SYSCALL_ARG5(unsigned int, whence);
+
+    auto* file = current_process->files[fd];
+    if (!file)
+        return -EBADF;
+
+    if (!result)
+        return -EFAULT;
+
+    if (offset_high != 0 || offset_low != 0 || whence != SEEK_END) {
+        NOT_IMPLEMENTED;
+        return -EINVAL;
+    }
+
+    // the function is used for check file size for now
+    // we return all 0
+    *result = 0;
+
+    return 0;
+}
+
 extern "C" void syscall_entry(
     interrupt_stack* data,
     mmx_registers* mmxregs)
@@ -1124,9 +1193,11 @@ void init_syscall(void)
     syscall_handlers[0x72] = _syscall_wait4;
     syscall_handlers[0x7a] = _syscall_newuname;
     syscall_handlers[0x84] = _syscall_getpgid;
+    syscall_handlers[0x8c] = _syscall_llseek;
     syscall_handlers[0x8d] = _syscall_getdents;
     syscall_handlers[0x92] = _syscall_writev;
     syscall_handlers[0x93] = _syscall_getsid;
+    syscall_handlers[0xa8] = _syscall_poll;
     syscall_handlers[0xac] = _syscall_prctl;
     syscall_handlers[0xae] = _syscall_rt_sigaction;
     syscall_handlers[0xaf] = _syscall_rt_sigprocmask;

+ 19 - 2
src/kernel/tty.cpp

@@ -54,6 +54,19 @@ void tty::print(const char* str)
         this->putchar(*(str++));
 }
 
+int tty::poll()
+{
+    types::lock_guard lck(this->mtx_buf);
+    if (this->buf.empty()) {
+        bool interrupted = this->waitlist.wait(this->mtx_buf);
+
+        if (interrupted)
+            return -EINTR;
+    }
+
+    return 1;
+}
+
 size_t tty::read(char* buf, size_t buf_size, size_t n)
 {
     n = std::max(buf_size, n);
@@ -133,8 +146,9 @@ void tty::_real_commit_char(int c)
         if (TERMIOS_LSET(this->termio, ECHONL) || TERMIOS_LSET(this->termio, ECHO))
             this->_echo_char(c);
 
-        if (TERMIOS_LSET(this->termio, ICANON))
-            this->waitlist.notify_all();
+        // if ICANON is set, we notify all waiting processes
+        // if ICANON is not set, since there are data ready, we notify as well
+        this->waitlist.notify_all();
 
         break;
 
@@ -144,6 +158,9 @@ void tty::_real_commit_char(int c)
         if (TERMIOS_LSET(this->termio, ECHO))
             this->_echo_char(c);
 
+        if (!TERMIOS_LSET(this->termio, ICANON))
+            this->waitlist.notify_all();
+
         break;
     }
 }