diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index ede05bda5f..a5701b452f 100644 --- a/Kernel/Syscall.cpp +++ b/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(); diff --git a/Kernel/Syscall.h b/Kernel/Syscall.h index 095fc507e7..edc24d610b 100644 --- a/Kernel/Syscall.h +++ b/Kernel/Syscall.h @@ -23,6 +23,7 @@ enum Function { PosixExit = 0x1991, PosixGetgid = 0x1992, PosixGetpid = 0x1993, + PosixWaitpid = 0x1994, }; void initialize(); diff --git a/Kernel/Task.cpp b/Kernel/Task.cpp index 075c4709a8..6c0ba1d43d 100644 --- a/Kernel/Task.cpp +++ b/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()); diff --git a/Kernel/Task.h b/Kernel/Task.h index 06c8dc8212..7427daee80 100644 --- a/Kernel/Task.h +++ b/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&&, String&&); diff --git a/Kernel/_fs_contents b/Kernel/_fs_contents index e74551456e..70277d8a7b 100644 Binary files a/Kernel/_fs_contents and b/Kernel/_fs_contents differ diff --git a/LibC/unistd.cpp b/LibC/unistd.cpp index 6efa2da1b2..81570ece70 100644 --- a/LibC/unistd.cpp +++ b/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); +} + } diff --git a/LibC/unistd.h b/LibC/unistd.h index 2395eadf13..078a90fe0e 100644 --- a/LibC/unistd.h +++ b/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); } diff --git a/Userland/sh.cpp b/Userland/sh.cpp index 6ec7a5e42a..68d4cc24b3 100644 --- a/Userland/sh.cpp +++ b/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; }