Просмотр исходного кода

Allow processes to go into a BeingInspected state (used by procfs.)

This ensures that the process won't get scheduled, and so inspecting
it is safe and easy without blocking interrupts.
Andreas Kling 6 лет назад
Родитель
Сommit
52607aa086
3 измененных файлов с 37 добавлено и 19 удалено
  1. 8 9
      Kernel/ProcFileSystem.cpp
  2. 6 6
      Kernel/Process.cpp
  3. 23 4
      Kernel/Process.h

+ 8 - 9
Kernel/ProcFileSystem.cpp

@@ -27,8 +27,9 @@ ProcFileSystem::~ProcFileSystem()
 {
 }
 
-ByteBuffer procfs$pid_fds(const Process& process)
+ByteBuffer procfs$pid_fds(Process& process)
 {
+    ProcessInspectionScope scope(process);
     char* buffer;
     auto stringImpl = StringImpl::createUninitialized(process.number_of_open_file_descriptors() * 80, buffer);
     memset(buffer, 0, stringImpl->length());
@@ -43,9 +44,9 @@ ByteBuffer procfs$pid_fds(const Process& process)
     return ByteBuffer::copy((byte*)buffer, ptr - buffer);
 }
 
-ByteBuffer procfs$pid_vm(const Process& process)
+ByteBuffer procfs$pid_vm(Process& process)
 {
-    InterruptDisabler disabler;
+    ProcessInspectionScope scope(process);
     char* buffer;
     auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80 + 80 + process.subregionCount() * 80, buffer);
     memset(buffer, 0, stringImpl->length());
@@ -76,7 +77,7 @@ ByteBuffer procfs$pid_vm(const Process& process)
 
 ByteBuffer procfs$pid_stack(Process& process)
 {
-    InterruptDisabler disabler;
+    ProcessInspectionScope scope(process);
     OtherProcessPagingScope pagingScope(process);
     struct RecognizedSymbol {
         dword address;
@@ -108,11 +109,8 @@ ByteBuffer procfs$pid_stack(Process& process)
 
 ByteBuffer procfs$pid_exe(Process& process)
 {
-    InodeIdentifier inode;
-    {
-        InterruptDisabler disabler;
-        inode = process.executableInode();
-    }
+    ProcessInspectionScope scope(process);
+    auto inode = process.executableInode();
     return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
 }
 
@@ -201,6 +199,7 @@ static const char* toString(Process::State state)
     case Process::BlockedSleep: return "Sleep";
     case Process::BlockedWait: return "Wait";
     case Process::BlockedRead: return "Read";
+    case Process::BeingInspected: return "Inspect";
     }
     ASSERT_NOT_REACHED();
     return nullptr;

+ 6 - 6
Kernel/Process.cpp

@@ -533,7 +533,7 @@ void Process::sys$exit(int status)
     kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
 #endif
 
-    setState(Exiting);
+    set_state(Exiting);
 
     s_processes->remove(this);
 
@@ -553,7 +553,7 @@ void Process::murder(int signal)
 {
     ASSERT_INTERRUPTS_DISABLED();
     bool wasCurrent = current == this;
-    setState(Exiting);
+    set_state(Exiting);
     s_processes->remove(this);
 
     notify_waiters(m_pid, 0, signal);
@@ -579,7 +579,7 @@ void Process::processDidCrash(Process* crashedProcess)
         HANG;
     }
 
-    crashedProcess->setState(Crashing);
+    crashedProcess->set_state(Crashing);
     crashedProcess->dumpRegions();
 
     s_processes->remove(crashedProcess);
@@ -741,11 +741,11 @@ static bool contextSwitch(Process* t)
         // If the last process hasn't blocked (still marked as running),
         // mark it as runnable for the next round.
         if (current->state() == Process::Running)
-            current->setState(Process::Runnable);
+            current->set_state(Process::Runnable);
     }
 
     current = t;
-    t->setState(Process::Running);
+    t->set_state(Process::Running);
 
     if (!t->selector()) {
         t->setSelector(allocateGDTEntry());
@@ -1074,7 +1074,7 @@ void Process::block(Process::State state)
 {
     ASSERT(current->state() == Process::Running);
     system.nblocked++;
-    current->setState(state);
+    current->set_state(state);
 }
 
 void block(Process::State state)

+ 23 - 4
Kernel/Process.h

@@ -30,9 +30,10 @@ public:
         Terminated = 3,
         Crashing = 4,
         Exiting = 5,
-        BlockedSleep = 6,
-        BlockedWait = 7,
-        BlockedRead = 8,
+        BeingInspected = 6,
+        BlockedSleep = 7,
+        BlockedWait = 8,
+        BlockedRead = 9,
     };
 
     enum RingLevel {
@@ -75,7 +76,7 @@ public:
     void setTicksLeft(DWORD t) { m_ticksLeft = t; }
 
     void setSelector(WORD s) { m_farPtr.selector = s; }
-    void setState(State s) { m_state = s; }
+    void set_state(State s) { m_state = s; }
 
     uid_t sys$getuid();
     gid_t sys$getgid();
@@ -203,6 +204,24 @@ private:
     Vector<String> m_initialEnvironment;
 };
 
+class ProcessInspectionScope {
+public:
+    ProcessInspectionScope(Process& process)
+        : m_process(process)
+        , m_original_state(process.state())
+    {
+        m_process.set_state(Process::BeingInspected);
+    }
+
+    ~ProcessInspectionScope()
+    {
+        m_process.set_state(m_original_state);
+    }
+private:
+    Process& m_process;
+    Process::State m_original_state { Process::Invalid };
+};
+
 extern void yield();
 extern bool scheduleNewProcess();
 extern void switchNow();