summaryrefslogtreecommitdiff
path: root/Kernel/Process.h
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-01 13:10:12 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-01 13:10:12 +0100
commit4e60551aec48297c29bda3718ade03b4e4063080 (patch)
tree0c96bd77b90fef9d4a42930d233ed30c9d53660a /Kernel/Process.h
parent8525cdd6a2b9d19db6616e844bc330fee6b7467a (diff)
downloadserenity-4e60551aec48297c29bda3718ade03b4e4063080.zip
Rename Task to Process.
Diffstat (limited to 'Kernel/Process.h')
-rw-r--r--Kernel/Process.h239
1 files changed, 239 insertions, 0 deletions
diff --git a/Kernel/Process.h b/Kernel/Process.h
new file mode 100644
index 0000000000..e114ec8702
--- /dev/null
+++ b/Kernel/Process.h
@@ -0,0 +1,239 @@
+#pragma once
+
+#include "types.h"
+#include "InlineLinkedList.h"
+#include <AK/String.h>
+#include "TSS.h"
+#include <AK/Vector.h>
+#include "i386.h"
+#include <VirtualFileSystem/VirtualFileSystem.h>
+#include "TTY.h"
+
+//#define TASK_SANITY_CHECKS
+
+class FileHandle;
+class Zone;
+
+class Task : public InlineLinkedListNode<Task> {
+ friend class InlineLinkedListNode<Task>;
+ struct Region;
+ struct Subregion;
+public:
+ static Task* createKernelTask(void (*entry)(), String&& name);
+ static Task* createUserTask(const String& path, uid_t, gid_t, pid_t parentPID, int& error, const char** args = nullptr, TTY* = nullptr);
+ ~Task();
+
+ static Vector<Task*> allTasks();
+
+#ifdef TASK_SANITY_CHECKS
+ static void checkSanity(const char* msg = nullptr);
+#else
+ static void checkSanity(const char*) { }
+#endif
+
+ enum State {
+ Invalid = 0,
+ Runnable = 1,
+ Running = 2,
+ Terminated = 3,
+ Crashing = 4,
+ Exiting = 5,
+ BlockedSleep = 6,
+ BlockedWait = 7,
+ BlockedRead = 8,
+ };
+
+ enum RingLevel {
+ Ring0 = 0,
+ Ring3 = 3,
+ };
+
+ bool isRing0() const { return m_ring == Ring0; }
+ bool isRing3() const { return m_ring == Ring3; }
+
+ static Task* fromPID(pid_t);
+ static Task* kernelTask();
+
+ const String& name() const { return m_name; }
+ pid_t pid() const { return m_pid; }
+ DWORD ticks() const { return m_ticks; }
+ WORD selector() const { return m_farPtr.selector; }
+ TSS32& tss() { return m_tss; }
+ State state() const { return m_state; }
+ uid_t uid() const { return m_uid; }
+ uid_t gid() const { return m_gid; }
+
+ pid_t parentPID() const { return m_parentPID; }
+
+ const FarPtr& farPtr() const { return m_farPtr; }
+
+ FileHandle* fileHandleIfExists(int fd);
+
+ static void doHouseKeeping();
+
+ void block(Task::State);
+ void unblock();
+
+ void setWakeupTime(DWORD t) { m_wakeupTime = t; }
+ DWORD wakeupTime() const { return m_wakeupTime; }
+
+ static void prepForIRETToNewTask();
+
+ bool tick() { ++m_ticks; return --m_ticksLeft; }
+ void setTicksLeft(DWORD t) { m_ticksLeft = t; }
+
+ void setSelector(WORD s) { m_farPtr.selector = s; }
+ void setState(State s) { m_state = s; }
+
+ uid_t sys$getuid();
+ gid_t sys$getgid();
+ pid_t sys$getpid();
+ int sys$open(const char* path, int options);
+ int sys$close(int fd);
+ ssize_t sys$read(int fd, void* outbuf, size_t nread);
+ ssize_t sys$write(int fd, const void*, size_t);
+ int sys$lstat(const char*, Unix::stat*);
+ int sys$stat(const char*, Unix::stat*);
+ int sys$lseek(int fd, off_t, int whence);
+ int sys$kill(pid_t pid, int sig);
+ int sys$geterror() { return m_error; }
+ void sys$exit(int status);
+ int sys$spawn(const char* path, const char** args);
+ pid_t sys$waitpid(pid_t, int* wstatus, int options);
+ void* sys$mmap(void*, size_t size);
+ int sys$munmap(void*, size_t size);
+ int sys$set_mmap_name(void*, size_t, const char*);
+ int sys$get_dir_entries(int fd, void*, size_t);
+ int sys$getcwd(char*, size_t);
+ int sys$chdir(const char*);
+ int sys$sleep(unsigned seconds);
+ int sys$gettimeofday(timeval*);
+ int sys$gethostname(char* name, size_t length);
+ int sys$get_arguments(int* argc, char*** argv);
+ int sys$get_environment(char*** environ);
+ int sys$uname(utsname*);
+ int sys$readlink(const char*, char*, size_t);
+ int sys$ttyname_r(int fd, char*, size_t);
+
+ static void initialize();
+
+ static void taskDidCrash(Task*);
+
+ const TTY* tty() const { return m_tty; }
+
+ size_t regionCount() const { return m_regions.size(); }
+ const Vector<RetainPtr<Region>>& regions() const { return m_regions; }
+ size_t subregionCount() const { return m_regions.size(); }
+ const Vector<OwnPtr<Subregion>>& subregions() const { return m_subregions; }
+ void dumpRegions();
+
+ void didSchedule() { ++m_timesScheduled; }
+ dword timesScheduled() const { return m_timesScheduled; }
+
+ pid_t waitee() const { return m_waitee; }
+
+ size_t fileHandleCount() const { return m_fileHandles.size(); }
+
+ dword framePtr() const { return m_tss.ebp; }
+ dword stackPtr() const { return m_tss.esp; }
+ dword stackTop() const { return m_tss.ss == 0x10 ? m_stackTop0 : m_stackTop3; }
+
+ bool isValidAddressForKernel(LinearAddress) const;
+ bool validate_user_read(LinearAddress) const;
+ bool validate_user_write(LinearAddress) const;
+
+ InodeIdentifier cwdInode() const { return m_cwd ? m_cwd->inode : InodeIdentifier(); }
+ InodeIdentifier executableInode() const { return m_executable ? m_executable->inode : InodeIdentifier(); }
+
+private:
+ friend class MemoryManager;
+ friend bool scheduleNewTask();
+
+ Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& cwd = nullptr, RetainPtr<VirtualFileSystem::Node>&& executable = nullptr, TTY* = nullptr);
+
+ void allocateLDT();
+
+ dword* m_pageDirectory { nullptr };
+
+ Task* m_prev { nullptr };
+ Task* m_next { nullptr };
+
+ String m_name;
+ void (*m_entry)() { nullptr };
+ pid_t m_pid { 0 };
+ uid_t m_uid { 0 };
+ gid_t m_gid { 0 };
+ DWORD m_ticks { 0 };
+ DWORD m_ticksLeft { 0 };
+ DWORD m_stackTop0 { 0 };
+ DWORD m_stackTop3 { 0 };
+ FarPtr m_farPtr;
+ State m_state { Invalid };
+ DWORD m_wakeupTime { 0 };
+ TSS32 m_tss;
+ Descriptor* m_ldtEntries { nullptr };
+ Vector<OwnPtr<FileHandle>> m_fileHandles;
+ RingLevel m_ring { Ring0 };
+ int m_error { 0 };
+ void* m_kernelStack { nullptr };
+ dword m_timesScheduled { 0 };
+ pid_t m_waitee { -1 };
+ int m_waiteeStatus { 0 };
+ int m_fdBlockedOnRead { -1 };
+ size_t m_maxFileHandles { 16 };
+
+ RetainPtr<VirtualFileSystem::Node> m_cwd;
+ RetainPtr<VirtualFileSystem::Node> m_executable;
+
+ TTY* m_tty { nullptr };
+
+ struct Region : public Retainable<Region> {
+ Region(LinearAddress, size_t, RetainPtr<Zone>&&, String&&);
+ ~Region();
+ LinearAddress linearAddress;
+ size_t size { 0 };
+ RetainPtr<Zone> zone;
+ String name;
+ };
+
+ struct Subregion {
+ Subregion(Region&, dword offset, size_t, LinearAddress, String&& name);
+ ~Subregion();
+
+ RetainPtr<Region> region;
+ dword offset;
+ size_t size { 0 };
+ LinearAddress linearAddress;
+ String name;
+ };
+
+ Region* allocateRegion(size_t, String&& name);
+ Region* allocateRegion(size_t, String&& name, LinearAddress);
+ bool deallocateRegion(Region& region);
+
+ Region* regionFromRange(LinearAddress, size_t);
+
+ Vector<RetainPtr<Region>> m_regions;
+ Vector<OwnPtr<Subregion>> m_subregions;
+
+ // FIXME: Implement some kind of ASLR?
+ LinearAddress m_nextRegion;
+
+ pid_t m_parentPID { 0 };
+
+ static void notify_waiters(pid_t waitee, int exit_status, int signal);
+ void murder(int signal);
+
+ Vector<String> m_arguments;
+ Vector<String> m_initialEnvironment;
+};
+
+extern void task_init();
+extern void yield();
+extern bool scheduleNewTask();
+extern void switchNow();
+extern void block(Task::State);
+extern void sleep(DWORD ticks);
+
+/* The currently executing task. NULL during kernel bootup. */
+extern Task* current;