Bladeren bron

Add a simplified waitpid() so that sh can wait on spawned commands.

Andreas Kling 6 jaren geleden
bovenliggende
commit
3253a23b91
8 gewijzigde bestanden met toevoegingen van 42 en 7 verwijderingen
  1. 2 0
      Kernel/Syscall.cpp
  2. 1 0
      Kernel/Syscall.h
  3. 26 7
      Kernel/Task.cpp
  4. 5 0
      Kernel/Task.h
  5. BIN
      Kernel/_fs_contents
  6. 5 0
      LibC/unistd.cpp
  7. 1 0
      LibC/unistd.h
  8. 2 0
      Userland/sh.cpp

+ 2 - 0
Kernel/Syscall.cpp

@@ -88,6 +88,8 @@ DWORD handle(DWORD function, DWORD arg1, DWORD arg2, DWORD arg3)
         return current->sys$getgid();
     case Syscall::PosixGetpid:
         return current->sys$getpid();
+    case Syscall::PosixWaitpid:
+        return current->sys$waitpid((pid_t)arg1);
     case Syscall::PosixExit:
         cli();
         locker.unlock();

+ 1 - 0
Kernel/Syscall.h

@@ -23,6 +23,7 @@ enum Function {
     PosixExit = 0x1991,
     PosixGetgid = 0x1992,
     PosixGetpid = 0x1993,
+    PosixWaitpid = 0x1994,
 };
 
 void initialize();

+ 26 - 7
Kernel/Task.cpp

@@ -11,6 +11,9 @@
 #include "MemoryManager.h"
 
 //#define DEBUG_IO
+//#define TASK_DEBUG
+
+static const DWORD defaultStackSize = 16384;
 
 Task* current;
 Task* s_kernelTask;
@@ -169,7 +172,9 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid)
 
     s_tasks->prepend(t);
     system.nprocess++;
+#ifdef TASK_DEBUG
     kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
+#endif
     sti();
 
     return t;
@@ -206,9 +211,6 @@ Task::Task(String&& name, uid_t uid, gid_t gid)
 
     m_tss.cr3 = MemoryManager::the().pageDirectoryBase().get();
 
-    // NOTE: Each task gets 16KB of stack.
-    static const DWORD defaultStackSize = 16384;
-
     auto* region = allocateRegion(defaultStackSize, "stack");
     ASSERT(region);
     m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
@@ -287,9 +289,6 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
         m_tss.eip = codeRegion->linearAddress.get();
     }
 
-    // NOTE: Each task gets 16KB of stack.
-    static const DWORD defaultStackSize = 16384;
-
     if (isRing0()) {
         // FIXME: This memory is leaked.
         // But uh, there's also no kernel task termination, so I guess it's not technically leaked...
@@ -327,8 +326,9 @@ Task::Task(void (*e)(), const char* n, IPC::Handle h, RingLevel ring)
     s_tasks->prepend(this);
 
     system.nprocess++;
-
+#ifdef TASK_DEBUG
     kprintf("Task %u (%s) spawned @ %p\n", m_pid, m_name.characters(), m_tss.eip);
+#endif
 }
 
 Task::~Task()
@@ -359,7 +359,9 @@ void Task::dumpRegions()
 void Task::sys$exit(int status)
 {
     cli();
+#ifdef TASK_DEBUG
     kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
+#endif
 
     setState(Exiting);
 
@@ -473,6 +475,13 @@ bool scheduleNewTask()
                 continue;
             }
         }
+
+        if (task->state() == Task::BlockedWait) {
+            if (!Task::fromPID(task->waitee())) {
+                task->unblock();
+                continue;
+            }
+        }
     }
 
     auto* prevHead = s_tasks->head();
@@ -693,6 +702,16 @@ pid_t Task::sys$getpid()
     return m_pid;
 }
 
+pid_t Task::sys$waitpid(pid_t waitee)
+{
+    if (!Task::fromPID(waitee))
+        return -1;
+    m_waitee = waitee;
+    block(BlockedWait);
+    yield();
+    return m_waitee;
+}
+
 bool Task::acceptsMessageFrom(Task& peer)
 {
     return !ipc.msg.isValid() && (ipc.src == IPC::Handle::Any || ipc.src == peer.handle());

+ 5 - 0
Kernel/Task.h

@@ -37,6 +37,7 @@ public:
         Terminated = 6,
         Crashing = 7,
         Exiting = 8,
+        BlockedWait = 9,
     };
 
     enum RingLevel {
@@ -97,6 +98,7 @@ public:
     void sys$sleep(DWORD ticks);
     void sys$exit(int status);
     int sys$spawn(const char* path);
+    pid_t sys$waitpid(pid_t);
 
     struct
     {
@@ -116,6 +118,8 @@ public:
     void didSchedule() { ++m_timesScheduled; }
     dword timesScheduled() const { return m_timesScheduled; }
 
+    pid_t waitee() const { return m_waitee; }
+
 private:
     friend class MemoryManager;
 
@@ -145,6 +149,7 @@ private:
     int m_error { 0 };
     void* m_kernelStack { nullptr };
     dword m_timesScheduled { 0 };
+    pid_t m_waitee { -1 };
 
     struct Region {
         Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);

BIN
Kernel/_fs_contents


+ 5 - 0
LibC/unistd.cpp

@@ -35,5 +35,10 @@ int close(int fd)
     return Syscall::invoke(Syscall::PosixClose, fd);
 }
 
+pid_t waitpid(pid_t waitee)
+{
+    return Syscall::invoke(Syscall::PosixWaitpid, waitee);
+}
+
 }
 

+ 1 - 0
LibC/unistd.h

@@ -10,6 +10,7 @@ pid_t getpid();
 int open(const char* path);
 ssize_t read(int fd, void* buf, size_t count);
 int close(int fd);
+pid_t waitpid(pid_t);
 
 }
 

+ 2 - 0
Userland/sh.cpp

@@ -18,7 +18,9 @@ static int runcmd(char* cmd)
     int ret = spawn(buf);
     if (ret == -1) {
         printf("spawn failed: %s\n", cmd);
+        return 1;
     }
+    waitpid(ret);
     return 0;
 }