Browse Source

feat(syscall): add syscalls, change syscall ids

add set_tid_address
add writev
add exit_group (the same as exit)
rename wait to waitpid
greatbridf 1 year ago
parent
commit
da4fc9c087

+ 12 - 2
gblibc/include/bits/ioctl.h

@@ -1,13 +1,23 @@
 #ifndef __GBLIBC_BITS_IOCTL_H_
 #define __GBLIBC_BITS_IOCTL_H_
 
-#define TIOCSPGRP (0)
-#define TIOCGPGRP (1)
+#include <sys/uio.h>
+
+#define TIOCGPGRP (0x540f)
+#define TIOCSPGRP (0x5410)
+#define TIOCGWINSZ (0x5413)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct winsize {
+    unsigned short ws_row;
+    unsigned short ws_col;
+    unsigned short ws_xpixel;
+    unsigned short ws_ypixel;
+};
+
 #ifdef __cplusplus
 }
 #endif

+ 19 - 0
gblibc/include/sys/uio.h

@@ -0,0 +1,19 @@
+#ifndef __GBLIBC_SYS_UIO_H
+#define __GBLIBC_SYS_UIO_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct iovec {
+    void* iov_base;
+    size_t iov_len;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 1 - 0
gblibc/include/sys/wait.h

@@ -8,6 +8,7 @@ extern "C" {
 #endif
 
 pid_t wait(int* code);
+pid_t waitpid(pid_t pid, int* code, int options);
 
 #ifdef __cplusplus
 }

+ 24 - 21
gblibc/private-include/syscall.h

@@ -3,27 +3,30 @@
 
 #include <stdint.h>
 
-#define SYS_read (0)
-#define SYS_write (1)
-#define SYS_open (2)
-#define SYS_close (3)
-#define SYS_ioctl (16)
-#define SYS_pipe (22)
-#define SYS_dup (32)
-#define SYS_dup2 (33)
-#define SYS_sleep (35)
-#define SYS_getpid (39)
-#define SYS_fork (57)
-#define SYS_execve (59)
-#define SYS_exit (60)
-#define SYS_wait (61)
-#define SYS_getdents (78)
-#define SYS_getcwd (79)
-#define SYS_chdir (80)
-#define SYS_setpgid (109)
-#define SYS_getppid (110)
-#define SYS_setsid (112)
-#define SYS_getsid (124)
+#define SYS_exit (0x01)
+#define SYS_fork (0x02)
+#define SYS_read (0x03)
+#define SYS_write (0x04)
+#define SYS_open (0x05)
+#define SYS_close (0x06)
+#define SYS_waitpid (0x07)
+#define SYS_execve (0x0b)
+#define SYS_chdir (0x0c)
+#define SYS_getpid (0x14)
+#define SYS_dup (0x29)
+#define SYS_pipe (0x2a)
+#define SYS_ioctl (0x36)
+#define SYS_setpgid (0x39)
+#define SYS_dup2 (0x3f)
+#define SYS_getppid (0x40)
+#define SYS_setsid (0x42)
+#define SYS_getdents (0x84)
+#define SYS_writev (0x92)
+#define SYS_getsid (0x93)
+#define SYS_getcwd (0xb7)
+#define SYS_set_thread_area (0xf3)
+#define SYS_exit_group (0xfc)
+#define SYS_set_tid_address (0x102)
 
 #ifdef __cplusplus
 extern "C" {

+ 2 - 2
gblibc/src/crt0.s

@@ -22,6 +22,6 @@ _start:
 
     call main
 
-    movl %eax, %edi  # code
-    movl $60, %eax # SYS_exit
+    movl %eax, %ebx  # code
+    movl $0xfc, %eax # SYS_exit_group
     int $0x80        # syscall

+ 4 - 4
gblibc/src/unistd.c

@@ -50,10 +50,10 @@ int execve(const char* pathname, char* const argv[], char* const envp[])
     return syscall3(SYS_execve, (uint32_t)pathname, (uint32_t)argv, (uint32_t)envp);
 }
 
-unsigned int sleep(unsigned int seconds)
-{
-    return syscall1(SYS_sleep, seconds);
-}
+// unsigned int sleep(unsigned int seconds)
+// {
+//     return syscall1(SYS_sleep, seconds);
+// }
 
 int chdir(const char* path)
 {

+ 6 - 1
gblibc/src/wait.c

@@ -1,7 +1,12 @@
 #include <sys/wait.h>
 #include <syscall.h>
 
+pid_t waitpid(pid_t pid, int* code, int options)
+{
+    return syscall3(SYS_waitpid, (uint32_t)pid, (uint32_t)code, (uint32_t)options);
+}
+
 pid_t wait(int* code)
 {
-    return syscall1(SYS_wait, (uint32_t)code);
+    return waitpid(-1, code, 0);
 }

+ 7 - 0
include/kernel/process.hpp

@@ -56,6 +56,8 @@ struct thread_attr {
 
 namespace kernel::tasks {
 
+using tid_t = uint32_t;
+
 struct thread {
 private:
     void alloc_kstack(void);
@@ -67,6 +69,9 @@ public:
     pid_t owner;
     thread_attr attr;
 
+    int* __user set_child_tid {};
+    int* __user clear_child_tid {};
+
     explicit inline thread(pid_t owner)
         : owner { owner }
         , attr { .system = 1, .ready = 1, .wait = 0, }
@@ -83,6 +88,8 @@ public:
     constexpr thread(thread&& val) = default;
     inline ~thread() { free_kstack(pkstack); }
 
+    constexpr tid_t tid() const { return pkstack; }
+
     constexpr bool operator==(const thread& rhs) const
     { return pkstack == rhs.pkstack; }
     constexpr bool operator<(const thread& rhs) const

+ 2 - 0
include/types/types.h

@@ -4,6 +4,8 @@
 #include "status.h"
 #include "stdint.h"
 
+#define __user
+
 #ifdef __GNUC__
 #define NORETURN __attribute__((noreturn))
 #else

+ 99 - 26
src/kernel/syscall.cpp

@@ -214,17 +214,24 @@ int NORETURN _syscall_exit(interrupt_stack* data)
         assert(false);
 
     // terminating a whole process:
-    procs->kill(current_process->pid, exit_code);
+    procs->kill(current_process->pid, exit_code & 0xff);
 
     // switch to new process and continue
     schedule_noreturn();
 }
 
-// @param address of exit code: int*
+// @param pid: pid of the process to wait
+// @param status: the exit code of the exited process
+// @param options: options for waitpid
 // @return pid of the exited process
-int _syscall_wait(interrupt_stack* data)
+int _syscall_waitpid(interrupt_stack* data)
 {
-    SYSCALL_ARG1(int*, arg1);
+    SYSCALL_ARG1(pid_t, pid_to_wait);
+    SYSCALL_ARG2(int*, arg1);
+    SYSCALL_ARG3(int, options);
+
+    if (pid_to_wait != -1 || options != 0)
+        return -EINVAL;
 
     auto& cv = current_process->cv_wait;
     auto& mtx = cv.mtx();
@@ -428,6 +435,12 @@ int _syscall_ioctl(interrupt_stack* data)
         ctrl_tty->set_pgrp(*pgid);
         break;
     }
+    case TIOCGWINSZ: {
+        SYSCALL_ARG3(winsize*, ws);
+        ws->ws_col = 80;
+        ws->ws_row = 10;
+        break;
+    }
     default:
         return -EINVAL;
     }
@@ -451,6 +464,63 @@ int _syscall_set_thread_area(interrupt_stack* data)
     return kernel::user::set_thread_area(ptr);
 }
 
+int _syscall_set_tid_address(interrupt_stack* data)
+{
+    SYSCALL_ARG1(int* __user, tidptr);
+    current_thread->set_child_tid = tidptr;
+    return current_thread->tid();
+}
+
+// TODO: this operation SHOULD be atomic
+ssize_t _syscall_writev(interrupt_stack* data)
+{
+    SYSCALL_ARG1(int, fd);
+    SYSCALL_ARG2(const iovec*, iov);
+    SYSCALL_ARG3(int, iovcnt);
+
+    auto* file = current_process->files[fd];
+
+    if (!file || !file->flags.write)
+        return -EBADF;
+
+    switch (file->type) {
+    case fs::file::types::ind: {
+        if (file->ptr.ind->flags.in.directory)
+            return -EBADF;
+
+        ssize_t n_wrote = 0;
+        for (int i = 0; i < iovcnt; ++i) {
+            int ret = fs::vfs_write(file->ptr.ind,
+                (const char*)iov[i].iov_base,
+                file->cursor, iov[i].iov_len);
+            if (ret < 0)
+                return ret;
+            n_wrote += ret;
+        }
+        file->cursor += n_wrote;
+        return n_wrote;
+    }
+    case fs::file::types::pipe: {
+        ssize_t tot = 0;
+        for (int i = 0; i < iovcnt; ++i) {
+            int retval = file->ptr.pp->write(
+                (const char*)iov->iov_base, iovcnt);
+            if (retval < 0)
+                return retval;
+            tot += retval;
+        }
+        return tot;
+    }
+
+    case fs::file::types::socket:
+        // TODO
+        return -EINVAL;
+    default:
+        assert(false);
+        for ( ; ; ) ;
+    }
+}
+
 extern "C" void syscall_entry(interrupt_stack* data)
 {
     int syscall_no = SYSCALL_NO;
@@ -469,26 +539,29 @@ void init_syscall(void)
 {
     memset(syscall_handlers, 0x00, sizeof(syscall_handlers));
 
-    syscall_handlers[0] = _syscall_read;
-    syscall_handlers[1] = _syscall_write;
-    syscall_handlers[2] = _syscall_open;
-    syscall_handlers[3] = _syscall_close;
-    syscall_handlers[16] = _syscall_ioctl;
-    syscall_handlers[22] = _syscall_pipe;
-    syscall_handlers[32] = _syscall_dup;
-    syscall_handlers[33] = _syscall_dup2;
-    syscall_handlers[35] = _syscall_sleep;
-    syscall_handlers[39] = _syscall_getpid;
-    syscall_handlers[57] = _syscall_fork;
-    syscall_handlers[59] = _syscall_execve;
-    syscall_handlers[60] = _syscall_exit;
-    syscall_handlers[61] = _syscall_wait;
-    syscall_handlers[78] = _syscall_getdents;
-    syscall_handlers[79] = _syscall_getcwd;
-    syscall_handlers[80] = _syscall_chdir;
-    syscall_handlers[109] = _syscall_setpgid;
-    syscall_handlers[110] = _syscall_getppid;
-    syscall_handlers[112] = _syscall_setsid;
-    syscall_handlers[124] = _syscall_getsid;
-    syscall_handlers[243] = _syscall_set_thread_area;
+    syscall_handlers[0x01] = _syscall_exit;
+    syscall_handlers[0x02] = _syscall_fork;
+    syscall_handlers[0x03] = _syscall_read;
+    syscall_handlers[0x04] = _syscall_write;
+    syscall_handlers[0x05] = _syscall_open;
+    syscall_handlers[0x06] = _syscall_close;
+    syscall_handlers[0x07] = _syscall_waitpid;
+    syscall_handlers[0x0b] = _syscall_execve;
+    syscall_handlers[0x0c] = _syscall_chdir;
+    syscall_handlers[0x14] = _syscall_getpid;
+    syscall_handlers[0x29] = _syscall_dup;
+    syscall_handlers[0x2a] = _syscall_pipe;
+    syscall_handlers[0x36] = _syscall_ioctl;
+    syscall_handlers[0x39] = _syscall_setpgid;
+    syscall_handlers[0x3f] = _syscall_dup2;
+    syscall_handlers[0x40] = _syscall_getppid;
+    syscall_handlers[0x42] = _syscall_setsid;
+    syscall_handlers[0x84] = _syscall_getdents;
+    syscall_handlers[0x92] = _syscall_writev;
+    syscall_handlers[0x93] = _syscall_getsid;
+    syscall_handlers[0xb7] = _syscall_getcwd;
+    syscall_handlers[0xf3] = _syscall_set_thread_area;
+    syscall_handlers[0xfc] = _syscall_exit; // we implement exit_group as exit for now
+    syscall_handlers[0x102] = _syscall_set_tid_address;
+    // syscall_handlers[35] = _syscall_sleep;
 }

+ 5 - 5
user-space-program/hello-world.s

@@ -7,11 +7,11 @@ main:
 	movl $0xcbcbcbcb, %eax
 	movl $0xacacacac, %edx
 
-	movl $1, %eax
-	movl $1, %edi
-	movl $_str, %esi
-	movl $_str_size, %ecx
-	movl (%ecx), %edx
+	movl $0x04, %eax
+	movl $1, %ebx
+	movl $_str, %ecx
+	movl $_str_size, %edx
+	movl (%edx), %edx
 	int $0x80
 
 	xorl %eax, %eax

+ 5 - 5
user-space-program/interrupt-test.s

@@ -5,17 +5,17 @@
 .globl main
 main:
 # fork 1 -> 2
-	movl $57, %eax
+	movl $0x02, %eax
 	int $0x80
 	movl %eax, %esi
 # fork 2 -> 4
-	movl $57, %eax
+	movl $0x02, %eax
 	int $0x80
 	movl %eax, %ecx
 # write
-	movl $1, %eax
-	movl $1, %edi
-	movl $__user_interrupt_test_string, %esi
+	movl $0x04, %eax
+	movl $1, %ebx
+	movl $__user_interrupt_test_string, %ecx
 	movl $(__user_interrupt_test_string_end - __user_interrupt_test_string), %edx
 	int $0x80
 

+ 1 - 0
user-space-program/sh.c

@@ -234,6 +234,7 @@ main(void)
     int code;
     wait(&code);
     tcsetpgrp(STDOUT_FILENO, getpid());
+    printf("[status: %d] ", code);
   }
   _exit(0);
 }