Browse Source

Use a freelist for GDT entries.

Tweak the kmalloc space layout a bit. Get the spawn stress test up
and running again.
Andreas Kling 6 năm trước cách đây
mục cha
commit
c70afd045e
6 tập tin đã thay đổi với 40 bổ sung21 xóa
  1. 14 8
      Kernel/Process.cpp
  2. 1 0
      Kernel/Process.h
  3. 17 6
      Kernel/i386.cpp
  4. 2 1
      Kernel/i386.h
  5. 3 3
      Kernel/init.cpp
  6. 3 3
      Kernel/kmalloc.cpp

+ 14 - 8
Kernel/Process.cpp

@@ -62,7 +62,7 @@ static bool contextSwitch(Process*);
 static void redoKernelProcessTSS()
 {
     if (!s_kernelProcess->selector())
-        s_kernelProcess->setSelector(allocateGDTEntry());
+        s_kernelProcess->setSelector(gdt_alloc_entry());
 
     auto& tssDescriptor = getGDTEntry(s_kernelProcess->selector());
 
@@ -109,14 +109,14 @@ void Process::allocateLDT()
 {
     ASSERT(!m_tss.ldt);
     static const WORD numLDTEntries = 4;
-    WORD newLDTSelector = allocateGDTEntry();
+    m_ldt_selector = gdt_alloc_entry();
     m_ldtEntries = new Descriptor[numLDTEntries];
 #if 0
-    kprintf("new ldt selector = %x\n", newLDTSelector);
+    kprintf("new ldt selector = %x\n", m_ldt_selector);
     kprintf("new ldt table at = %p\n", m_ldtEntries);
     kprintf("new ldt table size = %u\n", (numLDTEntries * 8) - 1);
 #endif
-    Descriptor& ldt = getGDTEntry(newLDTSelector);
+    Descriptor& ldt = getGDTEntry(m_ldt_selector);
     ldt.setBase(m_ldtEntries);
     ldt.setLimit(numLDTEntries * 8 - 1);
     ldt.dpl = 0;
@@ -126,7 +126,7 @@ void Process::allocateLDT()
     ldt.operation_size = 1;
     ldt.descriptor_type = 0;
     ldt.type = Descriptor::LDT;
-    m_tss.ldt = newLDTSelector;
+    m_tss.ldt = m_ldt_selector;
 }
 
 Vector<Process*> Process::allProcesses()
@@ -489,8 +489,14 @@ Process::~Process()
     InterruptDisabler disabler;
     ProcFileSystem::the().removeProcess(*this);
     system.nprocess--;
-    delete [] m_ldtEntries;
-    m_ldtEntries = nullptr;
+
+    if (isRing3()) {
+        delete [] m_ldtEntries;
+        m_ldtEntries = nullptr;
+        gdt_free_entry(m_ldt_selector);
+    }
+
+    gdt_free_entry(selector());
 
     if (m_kernelStack) {
         kfree(m_kernelStack);
@@ -754,7 +760,7 @@ static bool contextSwitch(Process* t)
     t->set_state(Process::Running);
 
     if (!t->selector()) {
-        t->setSelector(allocateGDTEntry());
+        t->setSelector(gdt_alloc_entry());
         auto& descriptor = getGDTEntry(t->selector());
         descriptor.setBase(&t->tss());
         descriptor.setLimit(0xffff);

+ 1 - 0
Kernel/Process.h

@@ -167,6 +167,7 @@ private:
     State m_state { Invalid };
     DWORD m_wakeupTime { 0 };
     TSS32 m_tss;
+    word m_ldt_selector { 0 };
     Descriptor* m_ldtEntries { nullptr };
     Vector<OwnPtr<FileHandle>> m_file_descriptors;
     RingLevel m_ring { Ring0 };

+ 17 - 6
Kernel/i386.cpp

@@ -20,15 +20,20 @@ static Descriptor* s_gdt;
 
 static IRQHandler** s_irqHandler;
 
+static Vector<word, KmallocEternalAllocator>* s_gdt_freelist;
+
 static WORD s_gdtLength;
 
-WORD allocateGDTEntry()
+word gdt_alloc_entry()
 {
-    // FIXME: This should not grow indefinitely.
-    ASSERT(s_gdtLength < 256);
-    WORD newGDTEntry = s_gdtLength * 8;
-    s_gdtLength++;
-    return newGDTEntry;
+    ASSERT(s_gdt_freelist);
+    ASSERT(!s_gdt_freelist->isEmpty());
+    return s_gdt_freelist->takeLast();
+}
+
+void gdt_free_entry(word entry)
+{
+    s_gdt_freelist->append(entry);
 }
 
 extern "C" void handleIRQ();
@@ -310,6 +315,12 @@ void gdt_init()
     s_gdt = static_cast<Descriptor*>(kmalloc_eternal(sizeof(Descriptor) * 256));
     s_gdtLength = 5;
 
+    s_gdt_freelist = new Vector<word, KmallocEternalAllocator>();
+    s_gdt_freelist->ensureCapacity(256);
+    for (size_t i = s_gdtLength; i < 256; ++i)
+        s_gdt_freelist->uncheckedAppend(i * 8);
+
+    s_gdtLength = 256;
     s_gdtr.address = s_gdt;
     s_gdtr.size = (s_gdtLength * 8) - 1;
 

+ 2 - 1
Kernel/i386.h

@@ -66,7 +66,8 @@ void unregisterIRQHandler(BYTE number, IRQHandler&);
 void flushIDT();
 void flushGDT();
 void loadTaskRegister(WORD selector);
-WORD allocateGDTEntry();
+word gdt_alloc_entry();
+void gdt_free_entry(word);
 Descriptor& getGDTEntry(WORD selector);
 void writeGDTEntry(WORD selector, Descriptor&);
 

+ 3 - 3
Kernel/init.cpp

@@ -106,13 +106,13 @@ static void spawn_stress()
 {
     dword lastAlloc = sum_alloc;
 
-    for (unsigned i = 0; i < 100; ++i) {
+    for (unsigned i = 0; i < 10000; ++i) {
         int error;
         Process::createUserProcess("/bin/id", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty0);
-        kprintf("malloc stats: alloc:%u free:%u\n", sum_alloc, sum_free);
+        kprintf("malloc stats: alloc:%u free:%u page_aligned:%u eternal:%u\n", sum_alloc, sum_free, kmalloc_page_aligned, kmalloc_sum_eternal);
         kprintf("delta:%u\n", sum_alloc - lastAlloc);
         lastAlloc = sum_alloc;
-        sleep(600);
+        sleep(60);
     }
     for (;;) {
         asm volatile("hlt");

+ 3 - 3
Kernel/kmalloc.cpp

@@ -22,9 +22,9 @@ typedef struct
 #define CHUNK_SIZE  128
 #define POOL_SIZE   (1024 * 1024)
 
-#define PAGE_ALIGNED_BASE_PHYSICAL 0x380000
-#define ETERNAL_BASE_PHYSICAL 0x300000
-#define BASE_PHYS   0x200000
+#define PAGE_ALIGNED_BASE_PHYSICAL 0x300000
+#define ETERNAL_BASE_PHYSICAL 0x200000
+#define BASE_PHYS   0x100000
 
 PRIVATE BYTE alloc_map[POOL_SIZE / CHUNK_SIZE / 8];