mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-30 00:31:14 +00:00
Process now maps regions immediately when they are allocated.
This avoids having to do a separate MM.mapRegionsForTask() pass. Also, more Task => Process renaming that I apparently hadn't saved yet.
This commit is contained in:
parent
4e60551aec
commit
3e532ac7b6
Notes:
sideshowbarker
2024-07-19 18:34:59 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/3e532ac7b6f
|
@ -1,5 +1,5 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include "VGA.h"
|
#include "VGA.h"
|
||||||
#include "Disk.h"
|
#include "Disk.h"
|
||||||
#include "kmalloc.h"
|
#include "kmalloc.h"
|
||||||
|
@ -145,8 +145,6 @@ bool readSectors(DWORD startSector, WORD count, BYTE* outbuf)
|
||||||
count,
|
count,
|
||||||
startSector);
|
startSector);
|
||||||
#endif
|
#endif
|
||||||
Task::checkSanity("Disk::readSectors");
|
|
||||||
|
|
||||||
disableIRQ();
|
disableIRQ();
|
||||||
|
|
||||||
CHS chs = lba2chs(IDE0_DISK0, startSector);
|
CHS chs = lba2chs(IDE0_DISK0, startSector);
|
||||||
|
|
|
@ -5,7 +5,7 @@ KERNEL_OBJS = \
|
||||||
kmalloc.o \
|
kmalloc.o \
|
||||||
StdLib.o \
|
StdLib.o \
|
||||||
i386.o \
|
i386.o \
|
||||||
Task.o \
|
Process.o \
|
||||||
i8253.o \
|
i8253.o \
|
||||||
Keyboard.o \
|
Keyboard.o \
|
||||||
CMOS.o \
|
CMOS.o \
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <AK/kmalloc.h>
|
#include <AK/kmalloc.h>
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "StdLib.h"
|
#include "StdLib.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
|
|
||||||
//#define MM_DEBUG
|
//#define MM_DEBUG
|
||||||
|
|
||||||
|
@ -30,12 +30,12 @@ MemoryManager::~MemoryManager()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::populate_page_directory(Task& task)
|
void MemoryManager::populate_page_directory(Process& process)
|
||||||
{
|
{
|
||||||
memset(task.m_pageDirectory, 0, 4096);
|
memset(process.m_pageDirectory, 0, 4096);
|
||||||
|
|
||||||
task.m_pageDirectory[0] = m_kernel_page_directory[0];
|
process.m_pageDirectory[0] = m_kernel_page_directory[0];
|
||||||
task.m_pageDirectory[1] = m_kernel_page_directory[1];
|
process.m_pageDirectory[1] = m_kernel_page_directory[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::initializePaging()
|
void MemoryManager::initializePaging()
|
||||||
|
@ -214,11 +214,11 @@ void MemoryManager::enter_kernel_paging_scope()
|
||||||
asm volatile("movl %%eax, %%cr3"::"a"(m_kernel_page_directory));
|
asm volatile("movl %%eax, %%cr3"::"a"(m_kernel_page_directory));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::enter_task_paging_scope(Task& task)
|
void MemoryManager::enter_process_paging_scope(Process& process)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
current->m_tss.cr3 = (dword)task.m_pageDirectory;
|
current->m_tss.cr3 = (dword)process.m_pageDirectory;
|
||||||
asm volatile("movl %%eax, %%cr3"::"a"(task.m_pageDirectory));
|
asm volatile("movl %%eax, %%cr3"::"a"(process.m_pageDirectory));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::flushEntireTLB()
|
void MemoryManager::flushEntireTLB()
|
||||||
|
@ -234,7 +234,7 @@ void MemoryManager::flushTLB(LinearAddress laddr)
|
||||||
asm volatile("invlpg %0": :"m" (*(char*)laddr.get()));
|
asm volatile("invlpg %0": :"m" (*(char*)laddr.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::map_region_at_address(dword* page_directory, Task::Region& region, LinearAddress laddr)
|
void MemoryManager::map_region_at_address(dword* page_directory, Process::Region& region, LinearAddress laddr, bool user_allowed)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto& zone = *region.zone;
|
auto& zone = *region.zone;
|
||||||
|
@ -244,7 +244,7 @@ void MemoryManager::map_region_at_address(dword* page_directory, Task::Region& r
|
||||||
pte.setPhysicalPageBase(zone.m_pages[i].get());
|
pte.setPhysicalPageBase(zone.m_pages[i].get());
|
||||||
pte.setPresent(true);
|
pte.setPresent(true);
|
||||||
pte.setWritable(true);
|
pte.setWritable(true);
|
||||||
pte.setUserAllowed(true);
|
pte.setUserAllowed(user_allowed);
|
||||||
flushTLB(page_laddr);
|
flushTLB(page_laddr);
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: >> map_region_at_address (PD=%x) L%x => P%x\n", page_directory, page_laddr, zone.m_pages[i].get());
|
dbgprintf("MM: >> map_region_at_address (PD=%x) L%x => P%x\n", page_directory, page_laddr, zone.m_pages[i].get());
|
||||||
|
@ -282,26 +282,26 @@ LinearAddress MemoryManager::allocate_linear_address_range(size_t size)
|
||||||
return laddr;
|
return laddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte* MemoryManager::create_kernel_alias_for_region(Task::Region& region)
|
byte* MemoryManager::create_kernel_alias_for_region(Process::Region& region)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto laddr = allocate_linear_address_range(region.size);
|
auto laddr = allocate_linear_address_range(region.size);
|
||||||
map_region_at_address(m_kernel_page_directory, region, laddr);
|
map_region_at_address(m_kernel_page_directory, region, laddr, false);
|
||||||
return laddr.asPtr();
|
return laddr.asPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemoryManager::remove_kernel_alias_for_region(Task::Region& region, byte* addr)
|
void MemoryManager::remove_kernel_alias_for_region(Process::Region& region, byte* addr)
|
||||||
{
|
{
|
||||||
unmap_range(m_kernel_page_directory, LinearAddress((dword)addr), region.size);
|
unmap_range(m_kernel_page_directory, LinearAddress((dword)addr), region.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::unmapRegion(Task& task, Task::Region& region)
|
bool MemoryManager::unmapRegion(Process& process, Process::Region& region)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto& zone = *region.zone;
|
auto& zone = *region.zone;
|
||||||
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
|
for (size_t i = 0; i < zone.m_pages.size(); ++i) {
|
||||||
auto laddr = region.linearAddress.offset(i * PAGE_SIZE);
|
auto laddr = region.linearAddress.offset(i * PAGE_SIZE);
|
||||||
auto pte = ensurePTE(task.m_pageDirectory, laddr);
|
auto pte = ensurePTE(process.m_pageDirectory, laddr);
|
||||||
pte.setPhysicalPageBase(0);
|
pte.setPhysicalPageBase(0);
|
||||||
pte.setPresent(false);
|
pte.setPresent(false);
|
||||||
pte.setWritable(false);
|
pte.setWritable(false);
|
||||||
|
@ -314,14 +314,14 @@ bool MemoryManager::unmapRegion(Task& task, Task::Region& region)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::unmapSubregion(Task& task, Task::Subregion& subregion)
|
bool MemoryManager::unmapSubregion(Process& process, Process::Subregion& subregion)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
size_t numPages = subregion.size / 4096;
|
size_t numPages = subregion.size / 4096;
|
||||||
ASSERT(numPages);
|
ASSERT(numPages);
|
||||||
for (size_t i = 0; i < numPages; ++i) {
|
for (size_t i = 0; i < numPages; ++i) {
|
||||||
auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
|
auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
|
||||||
auto pte = ensurePTE(task.m_pageDirectory, laddr);
|
auto pte = ensurePTE(process.m_pageDirectory, laddr);
|
||||||
pte.setPhysicalPageBase(0);
|
pte.setPhysicalPageBase(0);
|
||||||
pte.setPresent(false);
|
pte.setPresent(false);
|
||||||
pte.setWritable(false);
|
pte.setWritable(false);
|
||||||
|
@ -334,7 +334,7 @@ bool MemoryManager::unmapSubregion(Task& task, Task::Subregion& subregion)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::mapSubregion(Task& task, Task::Subregion& subregion)
|
bool MemoryManager::mapSubregion(Process& process, Process::Subregion& subregion)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto& region = *subregion.region;
|
auto& region = *subregion.region;
|
||||||
|
@ -344,7 +344,7 @@ bool MemoryManager::mapSubregion(Task& task, Task::Subregion& subregion)
|
||||||
ASSERT(numPages);
|
ASSERT(numPages);
|
||||||
for (size_t i = 0; i < numPages; ++i) {
|
for (size_t i = 0; i < numPages; ++i) {
|
||||||
auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
|
auto laddr = subregion.linearAddress.offset(i * PAGE_SIZE);
|
||||||
auto pte = ensurePTE(task.m_pageDirectory, laddr);
|
auto pte = ensurePTE(process.m_pageDirectory, laddr);
|
||||||
pte.setPhysicalPageBase(zone.m_pages[firstPage + i].get());
|
pte.setPhysicalPageBase(zone.m_pages[firstPage + i].get());
|
||||||
pte.setPresent(true);
|
pte.setPresent(true);
|
||||||
pte.setWritable(true);
|
pte.setWritable(true);
|
||||||
|
@ -357,17 +357,17 @@ bool MemoryManager::mapSubregion(Task& task, Task::Subregion& subregion)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::mapRegion(Task& task, Task::Region& region)
|
bool MemoryManager::mapRegion(Process& process, Process::Region& region)
|
||||||
{
|
{
|
||||||
map_region_at_address(task.m_pageDirectory, region, region.linearAddress);
|
map_region_at_address(process.m_pageDirectory, region, region.linearAddress, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::validate_user_read(const Task& task, LinearAddress laddr) const
|
bool MemoryManager::validate_user_read(const Process& process, LinearAddress laddr) const
|
||||||
{
|
{
|
||||||
dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff;
|
dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff;
|
||||||
dword pageTableIndex = (laddr.get() >> 12) & 0x3ff;
|
dword pageTableIndex = (laddr.get() >> 12) & 0x3ff;
|
||||||
auto pde = PageDirectoryEntry(&task.m_pageDirectory[pageDirectoryIndex]);
|
auto pde = PageDirectoryEntry(&process.m_pageDirectory[pageDirectoryIndex]);
|
||||||
if (!pde.isPresent())
|
if (!pde.isPresent())
|
||||||
return false;
|
return false;
|
||||||
auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
|
auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
|
||||||
|
@ -378,11 +378,11 @@ bool MemoryManager::validate_user_read(const Task& task, LinearAddress laddr) co
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::validate_user_write(const Task& task, LinearAddress laddr) const
|
bool MemoryManager::validate_user_write(const Process& process, LinearAddress laddr) const
|
||||||
{
|
{
|
||||||
dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff;
|
dword pageDirectoryIndex = (laddr.get() >> 22) & 0x3ff;
|
||||||
dword pageTableIndex = (laddr.get() >> 12) & 0x3ff;
|
dword pageTableIndex = (laddr.get() >> 12) & 0x3ff;
|
||||||
auto pde = PageDirectoryEntry(&task.m_pageDirectory[pageDirectoryIndex]);
|
auto pde = PageDirectoryEntry(&process.m_pageDirectory[pageDirectoryIndex]);
|
||||||
if (!pde.isPresent())
|
if (!pde.isPresent())
|
||||||
return false;
|
return false;
|
||||||
auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
|
auto pte = PageTableEntry(&pde.pageTableBase()[pageTableIndex]);
|
||||||
|
@ -394,17 +394,3 @@ bool MemoryManager::validate_user_write(const Task& task, LinearAddress laddr) c
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MemoryManager::mapRegionsForTask(Task& task)
|
|
||||||
{
|
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
|
||||||
for (auto& region : task.m_regions) {
|
|
||||||
if (!mapRegion(task, *region))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (auto& subregion : task.m_subregions) {
|
|
||||||
if (!mapSubregion(task, *subregion))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
#include <AK/RetainPtr.h>
|
#include <AK/RetainPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <AK/HashTable.h>
|
#include <AK/HashTable.h>
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
|
|
||||||
class Task;
|
class Process;
|
||||||
|
|
||||||
enum class PageFaultResponse {
|
enum class PageFaultResponse {
|
||||||
ShouldCrash,
|
ShouldCrash,
|
||||||
|
@ -46,33 +46,32 @@ public:
|
||||||
|
|
||||||
RetainPtr<Zone> createZone(size_t);
|
RetainPtr<Zone> createZone(size_t);
|
||||||
|
|
||||||
bool mapSubregion(Task&, Task::Subregion&);
|
bool mapSubregion(Process&, Process::Subregion&);
|
||||||
bool unmapSubregion(Task&, Task::Subregion&);
|
bool unmapSubregion(Process&, Process::Subregion&);
|
||||||
|
|
||||||
bool mapRegion(Task&, Task::Region&);
|
bool mapRegion(Process&, Process::Region&);
|
||||||
bool unmapRegion(Task&, Task::Region&);
|
bool unmapRegion(Process&, Process::Region&);
|
||||||
bool mapRegionsForTask(Task&);
|
|
||||||
|
|
||||||
void registerZone(Zone&);
|
void registerZone(Zone&);
|
||||||
void unregisterZone(Zone&);
|
void unregisterZone(Zone&);
|
||||||
|
|
||||||
void populate_page_directory(Task&);
|
void populate_page_directory(Process&);
|
||||||
|
|
||||||
byte* create_kernel_alias_for_region(Task::Region&);
|
byte* create_kernel_alias_for_region(Process::Region&);
|
||||||
void remove_kernel_alias_for_region(Task::Region&, byte*);
|
void remove_kernel_alias_for_region(Process::Region&, byte*);
|
||||||
|
|
||||||
void enter_kernel_paging_scope();
|
void enter_kernel_paging_scope();
|
||||||
void enter_task_paging_scope(Task&);
|
void enter_process_paging_scope(Process&);
|
||||||
|
|
||||||
bool validate_user_read(const Task&, LinearAddress) const;
|
bool validate_user_read(const Process&, LinearAddress) const;
|
||||||
bool validate_user_write(const Task&, LinearAddress) const;
|
bool validate_user_write(const Process&, LinearAddress) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryManager();
|
MemoryManager();
|
||||||
~MemoryManager();
|
~MemoryManager();
|
||||||
|
|
||||||
LinearAddress allocate_linear_address_range(size_t);
|
LinearAddress allocate_linear_address_range(size_t);
|
||||||
void map_region_at_address(dword* page_directory, Task::Region&, LinearAddress);
|
void map_region_at_address(dword* page_directory, Process::Region&, LinearAddress, bool user_accessible);
|
||||||
void unmap_range(dword* page_directory, LinearAddress, size_t);
|
void unmap_range(dword* page_directory, LinearAddress, size_t);
|
||||||
|
|
||||||
void initializePaging();
|
void initializePaging();
|
||||||
|
@ -179,10 +178,10 @@ private:
|
||||||
|
|
||||||
struct KernelPagingScope {
|
struct KernelPagingScope {
|
||||||
KernelPagingScope() { MM.enter_kernel_paging_scope(); }
|
KernelPagingScope() { MM.enter_kernel_paging_scope(); }
|
||||||
~KernelPagingScope() { MM.enter_task_paging_scope(*current); }
|
~KernelPagingScope() { MM.enter_process_paging_scope(*current); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OtherTaskPagingScope {
|
struct OtherProcessPagingScope {
|
||||||
OtherTaskPagingScope(Task& task) { MM.enter_task_paging_scope(task); }
|
OtherProcessPagingScope(Process& process) { MM.enter_process_paging_scope(process); }
|
||||||
~OtherTaskPagingScope() { MM.enter_task_paging_scope(*current); }
|
~OtherProcessPagingScope() { MM.enter_process_paging_scope(*current); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "ProcFileSystem.h"
|
#include "ProcFileSystem.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
|
@ -27,24 +27,24 @@ ProcFileSystem::~ProcFileSystem()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer procfs$pid_vm(const Task& task)
|
ByteBuffer procfs$pid_vm(const Process& process)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
auto stringImpl = StringImpl::createUninitialized(80 + task.regionCount() * 80 + 80 + task.subregionCount() * 80, buffer);
|
auto stringImpl = StringImpl::createUninitialized(80 + process.regionCount() * 80 + 80 + process.subregionCount() * 80, buffer);
|
||||||
memset(buffer, 0, stringImpl->length());
|
memset(buffer, 0, stringImpl->length());
|
||||||
char* ptr = buffer;
|
char* ptr = buffer;
|
||||||
ptr += ksprintf(ptr, "BEGIN END SIZE NAME\n");
|
ptr += ksprintf(ptr, "BEGIN END SIZE NAME\n");
|
||||||
for (auto& region : task.regions()) {
|
for (auto& region : process.regions()) {
|
||||||
ptr += ksprintf(ptr, "%x -- %x %x %s\n",
|
ptr += ksprintf(ptr, "%x -- %x %x %s\n",
|
||||||
region->linearAddress.get(),
|
region->linearAddress.get(),
|
||||||
region->linearAddress.offset(region->size - 1).get(),
|
region->linearAddress.offset(region->size - 1).get(),
|
||||||
region->size,
|
region->size,
|
||||||
region->name.characters());
|
region->name.characters());
|
||||||
}
|
}
|
||||||
if (task.subregionCount()) {
|
if (process.subregionCount()) {
|
||||||
ptr += ksprintf(ptr, "\nREGION OFFSET BEGIN END SIZE NAME\n");
|
ptr += ksprintf(ptr, "\nREGION OFFSET BEGIN END SIZE NAME\n");
|
||||||
for (auto& subregion : task.subregions()) {
|
for (auto& subregion : process.subregions()) {
|
||||||
ptr += ksprintf(ptr, "%x %x %x -- %x %x %s\n",
|
ptr += ksprintf(ptr, "%x %x %x -- %x %x %s\n",
|
||||||
subregion->region->linearAddress.get(),
|
subregion->region->linearAddress.get(),
|
||||||
subregion->offset,
|
subregion->offset,
|
||||||
|
@ -58,18 +58,18 @@ ByteBuffer procfs$pid_vm(const Task& task)
|
||||||
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
|
return ByteBuffer::copy((byte*)buffer, ptr - buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer procfs$pid_stack(Task& task)
|
ByteBuffer procfs$pid_stack(Process& process)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
OtherTaskPagingScope pagingScope(task);
|
OtherProcessPagingScope pagingScope(process);
|
||||||
struct RecognizedSymbol {
|
struct RecognizedSymbol {
|
||||||
dword address;
|
dword address;
|
||||||
const KSym* ksym;
|
const KSym* ksym;
|
||||||
};
|
};
|
||||||
Vector<RecognizedSymbol> recognizedSymbols;
|
Vector<RecognizedSymbol> recognizedSymbols;
|
||||||
if (auto* eipKsym = ksymbolicate(task.tss().eip))
|
if (auto* eipKsym = ksymbolicate(process.tss().eip))
|
||||||
recognizedSymbols.append({ task.tss().eip, eipKsym });
|
recognizedSymbols.append({ process.tss().eip, eipKsym });
|
||||||
for (dword* stackPtr = (dword*)task.framePtr(); task.isValidAddressForKernel(LinearAddress((dword)stackPtr)); stackPtr = (dword*)*stackPtr) {
|
for (dword* stackPtr = (dword*)process.framePtr(); process.isValidAddressForKernel(LinearAddress((dword)stackPtr)); stackPtr = (dword*)*stackPtr) {
|
||||||
dword retaddr = stackPtr[1];
|
dword retaddr = stackPtr[1];
|
||||||
if (auto* ksym = ksymbolicate(retaddr))
|
if (auto* ksym = ksymbolicate(retaddr))
|
||||||
recognizedSymbols.append({ retaddr, ksym });
|
recognizedSymbols.append({ retaddr, ksym });
|
||||||
|
@ -90,33 +90,33 @@ ByteBuffer procfs$pid_stack(Task& task)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer procfs$pid_exe(Task& task)
|
ByteBuffer procfs$pid_exe(Process& process)
|
||||||
{
|
{
|
||||||
InodeIdentifier inode;
|
InodeIdentifier inode;
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
inode = task.executableInode();
|
inode = process.executableInode();
|
||||||
}
|
}
|
||||||
return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
|
return VirtualFileSystem::the().absolutePath(inode).toByteBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcFileSystem::addProcess(Task& task)
|
void ProcFileSystem::addProcess(Process& process)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
char buf[16];
|
char buf[16];
|
||||||
ksprintf(buf, "%d", task.pid());
|
ksprintf(buf, "%d", process.pid());
|
||||||
auto dir = addFile(createDirectory(buf));
|
auto dir = addFile(createDirectory(buf));
|
||||||
m_pid2inode.set(task.pid(), dir.index());
|
m_pid2inode.set(process.pid(), dir.index());
|
||||||
addFile(createGeneratedFile("vm", [&task] { return procfs$pid_vm(task); }), dir.index());
|
addFile(createGeneratedFile("vm", [&process] { return procfs$pid_vm(process); }), dir.index());
|
||||||
addFile(createGeneratedFile("stack", [&task] { return procfs$pid_stack(task); }), dir.index());
|
addFile(createGeneratedFile("stack", [&process] { return procfs$pid_stack(process); }), dir.index());
|
||||||
if (task.executableInode().isValid())
|
if (process.executableInode().isValid())
|
||||||
addFile(createGeneratedFile("exe", [&task] { return procfs$pid_exe(task); }, 00120777), dir.index());
|
addFile(createGeneratedFile("exe", [&process] { return procfs$pid_exe(process); }, 00120777), dir.index());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcFileSystem::removeProcess(Task& task)
|
void ProcFileSystem::removeProcess(Process& process)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
auto pid = task.pid();
|
auto pid = process.pid();
|
||||||
auto it = m_pid2inode.find(pid);
|
auto it = m_pid2inode.find(pid);
|
||||||
ASSERT(it != m_pid2inode.end());
|
ASSERT(it != m_pid2inode.end());
|
||||||
bool success = removeFile((*it).value);
|
bool success = removeFile((*it).value);
|
||||||
|
@ -172,18 +172,18 @@ ByteBuffer procfs$kmalloc()
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* toString(Task::State state)
|
static const char* toString(Process::State state)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case Task::Invalid: return "Invalid";
|
case Process::Invalid: return "Invalid";
|
||||||
case Task::Runnable: return "Runnable";
|
case Process::Runnable: return "Runnable";
|
||||||
case Task::Running: return "Running";
|
case Process::Running: return "Running";
|
||||||
case Task::Terminated: return "Term";
|
case Process::Terminated: return "Term";
|
||||||
case Task::Crashing: return "Crash";
|
case Process::Crashing: return "Crash";
|
||||||
case Task::Exiting: return "Exit";
|
case Process::Exiting: return "Exit";
|
||||||
case Task::BlockedSleep: return "Sleep";
|
case Process::BlockedSleep: return "Sleep";
|
||||||
case Task::BlockedWait: return "Wait";
|
case Process::BlockedWait: return "Wait";
|
||||||
case Task::BlockedRead: return "Read";
|
case Process::BlockedRead: return "Read";
|
||||||
}
|
}
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -192,20 +192,20 @@ static const char* toString(Task::State state)
|
||||||
ByteBuffer procfs$summary()
|
ByteBuffer procfs$summary()
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto tasks = Task::allTasks();
|
auto processes = Process::allProcesses();
|
||||||
auto buffer = ByteBuffer::createUninitialized(tasks.size() * 256);
|
auto buffer = ByteBuffer::createUninitialized(processes.size() * 256);
|
||||||
char* ptr = (char*)buffer.pointer();
|
char* ptr = (char*)buffer.pointer();
|
||||||
ptr += ksprintf(ptr, "PID OWNER STATE PPID NSCHED FDS TTY NAME\n");
|
ptr += ksprintf(ptr, "PID OWNER STATE PPID NSCHED FDS TTY NAME\n");
|
||||||
for (auto* task : tasks) {
|
for (auto* process : processes) {
|
||||||
ptr += ksprintf(ptr, "% 5u % 4u % 8s % 5u % 10u % 3u % 4s %s\n",
|
ptr += ksprintf(ptr, "% 5u % 4u % 8s % 5u % 10u % 3u % 4s %s\n",
|
||||||
task->pid(),
|
process->pid(),
|
||||||
task->uid(),
|
process->uid(),
|
||||||
toString(task->state()),
|
toString(process->state()),
|
||||||
task->parentPID(),
|
process->parentPID(),
|
||||||
task->timesScheduled(),
|
process->timesScheduled(),
|
||||||
task->fileHandleCount(),
|
process->fileHandleCount(),
|
||||||
task->tty() ? strrchr(task->tty()->ttyName().characters(), '/') + 1 : "n/a",
|
process->tty() ? strrchr(process->tty()->ttyName().characters(), '/') + 1 : "n/a",
|
||||||
task->name().characters());
|
process->name().characters());
|
||||||
}
|
}
|
||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
buffer.trim(ptr - (char*)buffer.pointer());
|
buffer.trim(ptr - (char*)buffer.pointer());
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <VirtualFileSystem/SyntheticFileSystem.h>
|
#include <VirtualFileSystem/SyntheticFileSystem.h>
|
||||||
|
|
||||||
class Task;
|
class Process;
|
||||||
|
|
||||||
class ProcFileSystem final : public SyntheticFileSystem {
|
class ProcFileSystem final : public SyntheticFileSystem {
|
||||||
public:
|
public:
|
||||||
|
@ -15,8 +15,8 @@ public:
|
||||||
virtual bool initialize() override;
|
virtual bool initialize() override;
|
||||||
virtual const char* className() const override;
|
virtual const char* className() const override;
|
||||||
|
|
||||||
void addProcess(Task&);
|
void addProcess(Process&);
|
||||||
void removeProcess(Task&);
|
void removeProcess(Process&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProcFileSystem();
|
ProcFileSystem();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include "kmalloc.h"
|
#include "kmalloc.h"
|
||||||
#include "VGA.h"
|
#include "VGA.h"
|
||||||
#include "StdLib.h"
|
#include "StdLib.h"
|
||||||
|
@ -37,12 +37,12 @@
|
||||||
|
|
||||||
static const DWORD defaultStackSize = 16384;
|
static const DWORD defaultStackSize = 16384;
|
||||||
|
|
||||||
Task* current;
|
Process* current;
|
||||||
Task* s_kernelTask;
|
Process* s_kernelProcess;
|
||||||
|
|
||||||
static pid_t next_pid;
|
static pid_t next_pid;
|
||||||
static InlineLinkedList<Task>* s_tasks;
|
static InlineLinkedList<Process>* s_processes;
|
||||||
static InlineLinkedList<Task>* s_deadTasks;
|
static InlineLinkedList<Process>* s_deadProcesses;
|
||||||
static String* s_hostname;
|
static String* s_hostname;
|
||||||
|
|
||||||
static String& hostnameStorage(InterruptDisabler&)
|
static String& hostnameStorage(InterruptDisabler&)
|
||||||
|
@ -57,16 +57,16 @@ static String getHostname()
|
||||||
return hostnameStorage(disabler).isolatedCopy();
|
return hostnameStorage(disabler).isolatedCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool contextSwitch(Task*);
|
static bool contextSwitch(Process*);
|
||||||
|
|
||||||
static void redoKernelTaskTSS()
|
static void redoKernelProcessTSS()
|
||||||
{
|
{
|
||||||
if (!s_kernelTask->selector())
|
if (!s_kernelProcess->selector())
|
||||||
s_kernelTask->setSelector(allocateGDTEntry());
|
s_kernelProcess->setSelector(allocateGDTEntry());
|
||||||
|
|
||||||
auto& tssDescriptor = getGDTEntry(s_kernelTask->selector());
|
auto& tssDescriptor = getGDTEntry(s_kernelProcess->selector());
|
||||||
|
|
||||||
tssDescriptor.setBase(&s_kernelTask->tss());
|
tssDescriptor.setBase(&s_kernelProcess->tss());
|
||||||
tssDescriptor.setLimit(0xffff);
|
tssDescriptor.setLimit(0xffff);
|
||||||
tssDescriptor.dpl = 0;
|
tssDescriptor.dpl = 0;
|
||||||
tssDescriptor.segment_present = 1;
|
tssDescriptor.segment_present = 1;
|
||||||
|
@ -79,40 +79,26 @@ static void redoKernelTaskTSS()
|
||||||
flushGDT();
|
flushGDT();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::prepForIRETToNewTask()
|
void Process::prepForIRETToNewProcess()
|
||||||
{
|
{
|
||||||
redoKernelTaskTSS();
|
redoKernelProcessTSS();
|
||||||
s_kernelTask->tss().backlink = current->selector();
|
s_kernelProcess->tss().backlink = current->selector();
|
||||||
loadTaskRegister(s_kernelTask->selector());
|
loadTaskRegister(s_kernelProcess->selector());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::initialize()
|
void Process::initialize()
|
||||||
{
|
{
|
||||||
current = nullptr;
|
current = nullptr;
|
||||||
next_pid = 0;
|
next_pid = 0;
|
||||||
s_tasks = new InlineLinkedList<Task>;
|
s_processes = new InlineLinkedList<Process>;
|
||||||
s_deadTasks = new InlineLinkedList<Task>;
|
s_deadProcesses = new InlineLinkedList<Process>;
|
||||||
s_kernelTask = Task::createKernelTask(nullptr, "colonel");
|
s_kernelProcess = Process::createKernelProcess(nullptr, "colonel");
|
||||||
s_hostname = new String("birx");
|
s_hostname = new String("birx");
|
||||||
redoKernelTaskTSS();
|
redoKernelProcessTSS();
|
||||||
loadTaskRegister(s_kernelTask->selector());
|
loadTaskRegister(s_kernelProcess->selector());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TASK_SANITY_CHECKS
|
void Process::allocateLDT()
|
||||||
void Task::checkSanity(const char* msg)
|
|
||||||
{
|
|
||||||
char ch = current->name()[0];
|
|
||||||
kprintf("<%p> %s{%u}%b [%d] :%b: sanity check <%s>\n",
|
|
||||||
current->name().characters(),
|
|
||||||
current->name().characters(),
|
|
||||||
current->name().length(),
|
|
||||||
current->name()[current->name().length() - 1],
|
|
||||||
current->pid(), ch, msg ? msg : "");
|
|
||||||
ASSERT((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Task::allocateLDT()
|
|
||||||
{
|
{
|
||||||
ASSERT(!m_tss.ldt);
|
ASSERT(!m_tss.ldt);
|
||||||
static const WORD numLDTEntries = 4;
|
static const WORD numLDTEntries = 4;
|
||||||
|
@ -136,17 +122,17 @@ void Task::allocateLDT()
|
||||||
m_tss.ldt = newLDTSelector;
|
m_tss.ldt = newLDTSelector;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Task*> Task::allTasks()
|
Vector<Process*> Process::allProcesses()
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
Vector<Task*> tasks;
|
Vector<Process*> processes;
|
||||||
tasks.ensureCapacity(s_tasks->sizeSlow());
|
processes.ensureCapacity(s_processes->sizeSlow());
|
||||||
for (auto* task = s_tasks->head(); task; task = task->next())
|
for (auto* process = s_processes->head(); process; process = process->next())
|
||||||
tasks.append(task);
|
processes.append(process);
|
||||||
return tasks;
|
return processes;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Region* Task::allocateRegion(size_t size, String&& name)
|
Process::Region* Process::allocateRegion(size_t size, String&& name)
|
||||||
{
|
{
|
||||||
// FIXME: This needs sanity checks. What if this overlaps existing regions?
|
// FIXME: This needs sanity checks. What if this overlaps existing regions?
|
||||||
|
|
||||||
|
@ -154,10 +140,11 @@ Task::Region* Task::allocateRegion(size_t size, String&& name)
|
||||||
ASSERT(zone);
|
ASSERT(zone);
|
||||||
m_regions.append(adopt(*new Region(m_nextRegion, size, move(zone), move(name))));
|
m_regions.append(adopt(*new Region(m_nextRegion, size, move(zone), move(name))));
|
||||||
m_nextRegion = m_nextRegion.offset(size).offset(16384);
|
m_nextRegion = m_nextRegion.offset(size).offset(16384);
|
||||||
|
MM.mapRegion(*this, *m_regions.last());
|
||||||
return m_regions.last().ptr();
|
return m_regions.last().ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::deallocateRegion(Region& region)
|
bool Process::deallocateRegion(Region& region)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
for (size_t i = 0; i < m_regions.size(); ++i) {
|
for (size_t i = 0; i < m_regions.size(); ++i) {
|
||||||
|
@ -170,7 +157,7 @@ bool Task::deallocateRegion(Region& region)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Region* Task::regionFromRange(LinearAddress laddr, size_t size)
|
Process::Region* Process::regionFromRange(LinearAddress laddr, size_t size)
|
||||||
{
|
{
|
||||||
for (auto& region : m_regions) {
|
for (auto& region : m_regions) {
|
||||||
if (region->linearAddress == laddr && region->size == size)
|
if (region->linearAddress == laddr && region->size == size)
|
||||||
|
@ -179,7 +166,7 @@ Task::Region* Task::regionFromRange(LinearAddress laddr, size_t size)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$set_mmap_name(void* addr, size_t size, const char* name)
|
int Process::sys$set_mmap_name(void* addr, size_t size, const char* name)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_READ(name, strlen(name));
|
VALIDATE_USER_READ(name, strlen(name));
|
||||||
auto* region = regionFromRange(LinearAddress((dword)addr), size);
|
auto* region = regionFromRange(LinearAddress((dword)addr), size);
|
||||||
|
@ -189,7 +176,7 @@ int Task::sys$set_mmap_name(void* addr, size_t size, const char* name)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Task::sys$mmap(void* addr, size_t size)
|
void* Process::sys$mmap(void* addr, size_t size)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
// FIXME: Implement mapping at a client-preferred address.
|
// FIXME: Implement mapping at a client-preferred address.
|
||||||
|
@ -201,7 +188,7 @@ void* Task::sys$mmap(void* addr, size_t size)
|
||||||
return (void*)region->linearAddress.get();
|
return (void*)region->linearAddress.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$munmap(void* addr, size_t size)
|
int Process::sys$munmap(void* addr, size_t size)
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto* region = regionFromRange(LinearAddress((dword)addr), size);
|
auto* region = regionFromRange(LinearAddress((dword)addr), size);
|
||||||
|
@ -212,7 +199,7 @@ int Task::sys$munmap(void* addr, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$gethostname(char* buffer, size_t size)
|
int Process::sys$gethostname(char* buffer, size_t size)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(buffer, size);
|
VALIDATE_USER_WRITE(buffer, size);
|
||||||
auto hostname = getHostname();
|
auto hostname = getHostname();
|
||||||
|
@ -222,7 +209,7 @@ int Task::sys$gethostname(char* buffer, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$spawn(const char* path, const char** args)
|
int Process::sys$spawn(const char* path, const char** args)
|
||||||
{
|
{
|
||||||
if (args) {
|
if (args) {
|
||||||
for (size_t i = 0; args[i]; ++i) {
|
for (size_t i = 0; args[i]; ++i) {
|
||||||
|
@ -231,13 +218,13 @@ int Task::sys$spawn(const char* path, const char** args)
|
||||||
}
|
}
|
||||||
|
|
||||||
int error = 0;
|
int error = 0;
|
||||||
auto* child = Task::createUserTask(path, m_uid, m_gid, m_pid, error, args, m_tty);
|
auto* child = Process::createUserProcess(path, m_uid, m_gid, m_pid, error, args, m_tty);
|
||||||
if (child)
|
if (child)
|
||||||
return child->pid();
|
return child->pid();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t parentPID, int& error, const char** args, TTY* tty)
|
Process* Process::createUserProcess(const String& path, uid_t uid, gid_t gid, pid_t parentPID, int& error, const char** args, TTY* tty)
|
||||||
{
|
{
|
||||||
auto parts = path.split('/');
|
auto parts = path.split('/');
|
||||||
if (parts.isEmpty()) {
|
if (parts.isEmpty()) {
|
||||||
|
@ -248,8 +235,8 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
|
||||||
RetainPtr<VirtualFileSystem::Node> cwd;
|
RetainPtr<VirtualFileSystem::Node> cwd;
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
if (auto* parentTask = Task::fromPID(parentPID))
|
if (auto* parentProcess = Process::fromPID(parentPID))
|
||||||
cwd = parentTask->m_cwd.copyRef();
|
cwd = parentProcess->m_cwd.copyRef();
|
||||||
if (!cwd)
|
if (!cwd)
|
||||||
cwd = VirtualFileSystem::the().root();
|
cwd = VirtualFileSystem::the().root();
|
||||||
}
|
}
|
||||||
|
@ -269,27 +256,27 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String> taskArguments;
|
Vector<String> processArguments;
|
||||||
if (args) {
|
if (args) {
|
||||||
for (size_t i = 0; args[i]; ++i) {
|
for (size_t i = 0; args[i]; ++i) {
|
||||||
taskArguments.append(args[i]);
|
processArguments.append(args[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
taskArguments.append(parts.last());
|
processArguments.append(parts.last());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<String> taskEnvironment;
|
Vector<String> processEnvironment;
|
||||||
taskEnvironment.append("PATH=/bin");
|
processEnvironment.append("PATH=/bin");
|
||||||
taskEnvironment.append("SHELL=/bin/sh");
|
processEnvironment.append("SHELL=/bin/sh");
|
||||||
taskEnvironment.append("TERM=console");
|
processEnvironment.append("TERM=console");
|
||||||
taskEnvironment.append("HOME=/");
|
processEnvironment.append("HOME=/");
|
||||||
|
|
||||||
InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
|
InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
|
||||||
KernelPagingScope pagingScope;
|
KernelPagingScope pagingScope;
|
||||||
Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3, move(cwd), handle->vnode(), tty);
|
Process* t = new Process(parts.takeLast(), uid, gid, parentPID, Ring3, move(cwd), handle->vnode(), tty);
|
||||||
|
|
||||||
t->m_arguments = move(taskArguments);
|
t->m_arguments = move(processArguments);
|
||||||
t->m_initialEnvironment = move(taskEnvironment);
|
t->m_initialEnvironment = move(processEnvironment);
|
||||||
|
|
||||||
ExecSpace space;
|
ExecSpace space;
|
||||||
Region* region = nullptr;
|
Region* region = nullptr;
|
||||||
|
@ -343,18 +330,16 @@ Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t paren
|
||||||
ASSERT(region);
|
ASSERT(region);
|
||||||
MM.remove_kernel_alias_for_region(*region, region_alias);
|
MM.remove_kernel_alias_for_region(*region, region_alias);
|
||||||
|
|
||||||
MM.mapRegionsForTask(*t);
|
s_processes->prepend(t);
|
||||||
|
|
||||||
s_tasks->prepend(t);
|
|
||||||
system.nprocess++;
|
system.nprocess++;
|
||||||
#ifdef TASK_DEBUG
|
#ifdef TASK_DEBUG
|
||||||
kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
|
kprintf("Process %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
|
||||||
#endif
|
#endif
|
||||||
error = 0;
|
error = 0;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$get_environment(char*** environ)
|
int Process::sys$get_environment(char*** environ)
|
||||||
{
|
{
|
||||||
auto* region = allocateRegion(4096, "environ");
|
auto* region = allocateRegion(4096, "environ");
|
||||||
if (!region)
|
if (!region)
|
||||||
|
@ -373,7 +358,7 @@ int Task::sys$get_environment(char*** environ)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$get_arguments(int* argc, char*** argv)
|
int Process::sys$get_arguments(int* argc, char*** argv)
|
||||||
{
|
{
|
||||||
auto* region = allocateRegion(4096, "argv");
|
auto* region = allocateRegion(4096, "argv");
|
||||||
if (!region)
|
if (!region)
|
||||||
|
@ -392,24 +377,24 @@ int Task::sys$get_arguments(int* argc, char*** argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task* Task::createKernelTask(void (*e)(), String&& name)
|
Process* Process::createKernelProcess(void (*e)(), String&& name)
|
||||||
{
|
{
|
||||||
Task* task = new Task(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);
|
Process* process = new Process(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);
|
||||||
task->m_tss.eip = (dword)e;
|
process->m_tss.eip = (dword)e;
|
||||||
|
|
||||||
if (task->pid() != 0) {
|
if (process->pid() != 0) {
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
s_tasks->prepend(task);
|
s_processes->prepend(process);
|
||||||
system.nprocess++;
|
system.nprocess++;
|
||||||
#ifdef TASK_DEBUG
|
#ifdef TASK_DEBUG
|
||||||
kprintf("Kernel task %u (%s) spawned @ %p\n", task->pid(), task->name().characters(), task->m_tss.eip);
|
kprintf("Kernel process %u (%s) spawned @ %p\n", process->pid(), process->name().characters(), process->m_tss.eip);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return task;
|
return process;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring, RetainPtr<VirtualFileSystem::Node>&& cwd, RetainPtr<VirtualFileSystem::Node>&& executable, TTY* tty)
|
Process::Process(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring, RetainPtr<VirtualFileSystem::Node>&& cwd, RetainPtr<VirtualFileSystem::Node>&& executable, TTY* tty)
|
||||||
: m_name(move(name))
|
: m_name(move(name))
|
||||||
, m_pid(next_pid++)
|
, m_pid(next_pid++)
|
||||||
, m_uid(uid)
|
, m_uid(uid)
|
||||||
|
@ -443,7 +428,7 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring,
|
||||||
allocateLDT();
|
allocateLDT();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only IF is set when a task boots.
|
// Only IF is set when a process boots.
|
||||||
m_tss.eflags = 0x0202;
|
m_tss.eflags = 0x0202;
|
||||||
|
|
||||||
word cs, ds, ss;
|
word cs, ds, ss;
|
||||||
|
@ -469,7 +454,7 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring,
|
||||||
|
|
||||||
if (isRing0()) {
|
if (isRing0()) {
|
||||||
// FIXME: This memory is leaked.
|
// FIXME: This memory is leaked.
|
||||||
// But uh, there's also no kernel task termination, so I guess it's not technically leaked...
|
// But uh, there's also no kernel process termination, so I guess it's not technically leaked...
|
||||||
dword stackBottom = (dword)kmalloc_eternal(defaultStackSize);
|
dword stackBottom = (dword)kmalloc_eternal(defaultStackSize);
|
||||||
m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8;
|
m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8;
|
||||||
m_tss.esp = m_stackTop0;
|
m_tss.esp = m_stackTop0;
|
||||||
|
@ -481,7 +466,7 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRing3()) {
|
if (isRing3()) {
|
||||||
// Ring3 tasks need a separate stack for Ring0.
|
// Ring3 processes need a separate stack for Ring0.
|
||||||
m_kernelStack = kmalloc(defaultStackSize);
|
m_kernelStack = kmalloc(defaultStackSize);
|
||||||
m_stackTop0 = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
|
m_stackTop0 = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
|
||||||
m_tss.ss0 = 0x10;
|
m_tss.ss0 = 0x10;
|
||||||
|
@ -495,7 +480,7 @@ Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring,
|
||||||
ProcFileSystem::the().addProcess(*this);
|
ProcFileSystem::the().addProcess(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::~Task()
|
Process::~Process()
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
ProcFileSystem::the().removeProcess(*this);
|
ProcFileSystem::the().removeProcess(*this);
|
||||||
|
@ -509,9 +494,9 @@ Task::~Task()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::dumpRegions()
|
void Process::dumpRegions()
|
||||||
{
|
{
|
||||||
kprintf("Task %s(%u) regions:\n", name().characters(), pid());
|
kprintf("Process %s(%u) regions:\n", name().characters(), pid());
|
||||||
kprintf("BEGIN END SIZE NAME\n");
|
kprintf("BEGIN END SIZE NAME\n");
|
||||||
for (auto& region : m_regions) {
|
for (auto& region : m_regions) {
|
||||||
kprintf("%x -- %x %x %s\n",
|
kprintf("%x -- %x %x %s\n",
|
||||||
|
@ -521,7 +506,7 @@ void Task::dumpRegions()
|
||||||
region->name.characters());
|
region->name.characters());
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("Task %s(%u) subregions:\n", name().characters(), pid());
|
kprintf("Process %s(%u) subregions:\n", name().characters(), pid());
|
||||||
kprintf("REGION OFFSET BEGIN END SIZE NAME\n");
|
kprintf("REGION OFFSET BEGIN END SIZE NAME\n");
|
||||||
for (auto& subregion : m_subregions) {
|
for (auto& subregion : m_subregions) {
|
||||||
kprintf("%x %x %x -- %x %x %s\n",
|
kprintf("%x %x %x -- %x %x %s\n",
|
||||||
|
@ -534,16 +519,16 @@ void Task::dumpRegions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::notify_waiters(pid_t waitee, int exit_status, int signal)
|
void Process::notify_waiters(pid_t waitee, int exit_status, int signal)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
for (auto* task = s_tasks->head(); task; task = task->next()) {
|
for (auto* process = s_processes->head(); process; process = process->next()) {
|
||||||
if (task->waitee() == waitee)
|
if (process->waitee() == waitee)
|
||||||
task->m_waiteeStatus = (exit_status << 8) | (signal);
|
process->m_waiteeStatus = (exit_status << 8) | (signal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::sys$exit(int status)
|
void Process::sys$exit(int status)
|
||||||
{
|
{
|
||||||
cli();
|
cli();
|
||||||
#ifdef TASK_DEBUG
|
#ifdef TASK_DEBUG
|
||||||
|
@ -552,78 +537,78 @@ void Task::sys$exit(int status)
|
||||||
|
|
||||||
setState(Exiting);
|
setState(Exiting);
|
||||||
|
|
||||||
s_tasks->remove(this);
|
s_processes->remove(this);
|
||||||
|
|
||||||
notify_waiters(m_pid, status, 0);
|
notify_waiters(m_pid, status, 0);
|
||||||
|
|
||||||
if (!scheduleNewTask()) {
|
if (!scheduleNewProcess()) {
|
||||||
kprintf("Task::sys$exit: Failed to schedule a new task :(\n");
|
kprintf("Process::sys$exit: Failed to schedule a new process :(\n");
|
||||||
HANG;
|
HANG;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_deadTasks->append(this);
|
s_deadProcesses->append(this);
|
||||||
|
|
||||||
switchNow();
|
switchNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::murder(int signal)
|
void Process::murder(int signal)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
bool wasCurrent = current == this;
|
bool wasCurrent = current == this;
|
||||||
setState(Exiting);
|
setState(Exiting);
|
||||||
s_tasks->remove(this);
|
s_processes->remove(this);
|
||||||
|
|
||||||
notify_waiters(m_pid, 0, signal);
|
notify_waiters(m_pid, 0, signal);
|
||||||
|
|
||||||
if (wasCurrent) {
|
if (wasCurrent) {
|
||||||
kprintf("Current task committing suicide!\n");
|
kprintf("Current process committing suicide!\n");
|
||||||
if (!scheduleNewTask()) {
|
if (!scheduleNewProcess()) {
|
||||||
kprintf("Task::murder: Failed to schedule a new task :(\n");
|
kprintf("Process::murder: Failed to schedule a new process :(\n");
|
||||||
HANG;
|
HANG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s_deadTasks->append(this);
|
s_deadProcesses->append(this);
|
||||||
if (wasCurrent)
|
if (wasCurrent)
|
||||||
switchNow();
|
switchNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::taskDidCrash(Task* crashedTask)
|
void Process::processDidCrash(Process* crashedProcess)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
|
||||||
if (crashedTask->state() == Crashing) {
|
if (crashedProcess->state() == Crashing) {
|
||||||
kprintf("Double crash :(\n");
|
kprintf("Double crash :(\n");
|
||||||
HANG;
|
HANG;
|
||||||
}
|
}
|
||||||
|
|
||||||
crashedTask->setState(Crashing);
|
crashedProcess->setState(Crashing);
|
||||||
crashedTask->dumpRegions();
|
crashedProcess->dumpRegions();
|
||||||
|
|
||||||
s_tasks->remove(crashedTask);
|
s_processes->remove(crashedProcess);
|
||||||
|
|
||||||
notify_waiters(crashedTask->m_pid, 0, SIGSEGV);
|
notify_waiters(crashedProcess->m_pid, 0, SIGSEGV);
|
||||||
|
|
||||||
if (!scheduleNewTask()) {
|
if (!scheduleNewProcess()) {
|
||||||
kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
|
kprintf("Process::processDidCrash: Failed to schedule a new process :(\n");
|
||||||
HANG;
|
HANG;
|
||||||
}
|
}
|
||||||
|
|
||||||
s_deadTasks->append(crashedTask);
|
s_deadProcesses->append(crashedProcess);
|
||||||
|
|
||||||
switchNow();
|
switchNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::doHouseKeeping()
|
void Process::doHouseKeeping()
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
if (s_deadTasks->isEmpty())
|
if (s_deadProcesses->isEmpty())
|
||||||
return;
|
return;
|
||||||
Task* next = nullptr;
|
Process* next = nullptr;
|
||||||
for (auto* deadTask = s_deadTasks->head(); deadTask; deadTask = next) {
|
for (auto* deadProcess = s_deadProcesses->head(); deadProcess; deadProcess = next) {
|
||||||
next = deadTask->next();
|
next = deadProcess->next();
|
||||||
delete deadTask;
|
delete deadProcess;
|
||||||
}
|
}
|
||||||
s_deadTasks->clear();
|
s_deadProcesses->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield()
|
void yield()
|
||||||
|
@ -636,10 +621,10 @@ void yield()
|
||||||
//kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
|
//kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
|
||||||
|
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
if (!scheduleNewTask())
|
if (!scheduleNewProcess())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters());
|
//kprintf("yield() jumping to new process: %x (%s)\n", current->farPtr().selector, current->name().characters());
|
||||||
switchNow();
|
switchNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,36 +639,36 @@ void switchNow()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool scheduleNewTask()
|
bool scheduleNewProcess()
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
|
|
||||||
if (!current) {
|
if (!current) {
|
||||||
// XXX: The first ever context_switch() goes to the idle task.
|
// XXX: The first ever context_switch() goes to the idle process.
|
||||||
// This to setup a reliable place we can return to.
|
// This to setup a reliable place we can return to.
|
||||||
return contextSwitch(Task::kernelTask());
|
return contextSwitch(Process::kernelProcess());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and unblock tasks whose wait conditions have been met.
|
// Check and unblock processes whose wait conditions have been met.
|
||||||
for (auto* task = s_tasks->head(); task; task = task->next()) {
|
for (auto* process = s_processes->head(); process; process = process->next()) {
|
||||||
if (task->state() == Task::BlockedSleep) {
|
if (process->state() == Process::BlockedSleep) {
|
||||||
if (task->wakeupTime() <= system.uptime) {
|
if (process->wakeupTime() <= system.uptime) {
|
||||||
task->unblock();
|
process->unblock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->state() == Task::BlockedWait) {
|
if (process->state() == Process::BlockedWait) {
|
||||||
if (!Task::fromPID(task->waitee())) {
|
if (!Process::fromPID(process->waitee())) {
|
||||||
task->unblock();
|
process->unblock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->state() == Task::BlockedRead) {
|
if (process->state() == Process::BlockedRead) {
|
||||||
ASSERT(task->m_fdBlockedOnRead != -1);
|
ASSERT(process->m_fdBlockedOnRead != -1);
|
||||||
if (task->m_fileHandles[task->m_fdBlockedOnRead]->hasDataAvailableForRead()) {
|
if (process->m_fileHandles[process->m_fdBlockedOnRead]->hasDataAvailableForRead()) {
|
||||||
task->unblock();
|
process->unblock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -691,46 +676,46 @@ bool scheduleNewTask()
|
||||||
|
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbgprintf("Scheduler choices:\n");
|
dbgprintf("Scheduler choices:\n");
|
||||||
for (auto* task = s_tasks->head(); task; task = task->next()) {
|
for (auto* process = s_processes->head(); process; process = process->next()) {
|
||||||
//if (task->state() == Task::BlockedWait || task->state() == Task::BlockedSleep)
|
//if (process->state() == Process::BlockedWait || process->state() == Process::BlockedSleep)
|
||||||
// continue;
|
// continue;
|
||||||
dbgprintf("%w %s(%u)\n", task->state(), task->name().characters(), task->pid());
|
dbgprintf("%w %s(%u)\n", process->state(), process->name().characters(), process->pid());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto* prevHead = s_tasks->head();
|
auto* prevHead = s_processes->head();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Move head to tail.
|
// Move head to tail.
|
||||||
s_tasks->append(s_tasks->removeHead());
|
s_processes->append(s_processes->removeHead());
|
||||||
auto* task = s_tasks->head();
|
auto* process = s_processes->head();
|
||||||
|
|
||||||
if (task->state() == Task::Runnable || task->state() == Task::Running) {
|
if (process->state() == Process::Runnable || process->state() == Process::Running) {
|
||||||
#ifdef SCHEDULER_DEBUG
|
#ifdef SCHEDULER_DEBUG
|
||||||
dbgprintf("switch to %s(%u) (%p vs %p)\n", task->name().characters(), task->pid(), task, current);
|
dbgprintf("switch to %s(%u) (%p vs %p)\n", process->name().characters(), process->pid(), process, current);
|
||||||
#endif
|
#endif
|
||||||
return contextSwitch(task);
|
return contextSwitch(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task == prevHead) {
|
if (process == prevHead) {
|
||||||
// Back at task_head, nothing wants to run.
|
// Back at process_head, nothing wants to run.
|
||||||
kprintf("Nothing wants to run!\n");
|
kprintf("Nothing wants to run!\n");
|
||||||
kprintf("PID OWNER STATE NSCHED NAME\n");
|
kprintf("PID OWNER STATE NSCHED NAME\n");
|
||||||
for (auto* task = s_tasks->head(); task; task = task->next()) {
|
for (auto* process = s_processes->head(); process; process = process->next()) {
|
||||||
kprintf("%w %w:%w %b %w %s\n",
|
kprintf("%w %w:%w %b %w %s\n",
|
||||||
task->pid(),
|
process->pid(),
|
||||||
task->uid(),
|
process->uid(),
|
||||||
task->gid(),
|
process->gid(),
|
||||||
task->state(),
|
process->state(),
|
||||||
task->timesScheduled(),
|
process->timesScheduled(),
|
||||||
task->name().characters());
|
process->name().characters());
|
||||||
}
|
}
|
||||||
kprintf("Switch to kernel task\n");
|
kprintf("Switch to kernel process\n");
|
||||||
return contextSwitch(Task::kernelTask());
|
return contextSwitch(Process::kernelProcess());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool contextSwitch(Task* t)
|
static bool contextSwitch(Process* t)
|
||||||
{
|
{
|
||||||
t->setTicksLeft(5);
|
t->setTicksLeft(5);
|
||||||
t->didSchedule();
|
t->didSchedule();
|
||||||
|
@ -755,14 +740,14 @@ static bool contextSwitch(Task* t)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (current) {
|
if (current) {
|
||||||
// If the last task hasn't blocked (still marked as running),
|
// If the last process hasn't blocked (still marked as running),
|
||||||
// mark it as runnable for the next round.
|
// mark it as runnable for the next round.
|
||||||
if (current->state() == Task::Running)
|
if (current->state() == Process::Running)
|
||||||
current->setState(Task::Runnable);
|
current->setState(Process::Runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
current = t;
|
current = t;
|
||||||
t->setState(Task::Running);
|
t->setState(Process::Running);
|
||||||
|
|
||||||
if (!t->selector()) {
|
if (!t->selector()) {
|
||||||
t->setSelector(allocateGDTEntry());
|
t->setSelector(allocateGDTEntry());
|
||||||
|
@ -783,17 +768,17 @@ static bool contextSwitch(Task* t)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task* Task::fromPID(pid_t pid)
|
Process* Process::fromPID(pid_t pid)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_DISABLED();
|
ASSERT_INTERRUPTS_DISABLED();
|
||||||
for (auto* task = s_tasks->head(); task; task = task->next()) {
|
for (auto* process = s_processes->head(); process; process = process->next()) {
|
||||||
if (task->pid() == pid)
|
if (process->pid() == pid)
|
||||||
return task;
|
return process;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileHandle* Task::fileHandleIfExists(int fd)
|
FileHandle* Process::fileHandleIfExists(int fd)
|
||||||
{
|
{
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -802,7 +787,7 @@ FileHandle* Task::fileHandleIfExists(int fd)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
|
ssize_t Process::sys$get_dir_entries(int fd, void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(buffer, size);
|
VALIDATE_USER_WRITE(buffer, size);
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
|
@ -811,7 +796,7 @@ ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
|
||||||
return handle->get_dir_entries((byte*)buffer, size);
|
return handle->get_dir_entries((byte*)buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$lseek(int fd, off_t offset, int whence)
|
int Process::sys$lseek(int fd, off_t offset, int whence)
|
||||||
{
|
{
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
@ -819,7 +804,7 @@ int Task::sys$lseek(int fd, off_t offset, int whence)
|
||||||
return handle->seek(offset, whence);
|
return handle->seek(offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$ttyname_r(int fd, char* buffer, size_t size)
|
int Process::sys$ttyname_r(int fd, char* buffer, size_t size)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(buffer, size);
|
VALIDATE_USER_WRITE(buffer, size);
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
|
@ -834,34 +819,34 @@ int Task::sys$ttyname_r(int fd, char* buffer, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Task::sys$write(int fd, const void* data, size_t size)
|
ssize_t Process::sys$write(int fd, const void* data, size_t size)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_READ(data, size);
|
VALIDATE_USER_READ(data, size);
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$write: called(%d, %p, %u)\n", fd, data, size);
|
kprintf("Process::sys$write: called(%d, %p, %u)\n", fd, data, size);
|
||||||
#endif
|
#endif
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$write: handle=%p\n", handle);
|
kprintf("Process::sys$write: handle=%p\n", handle);
|
||||||
#endif
|
#endif
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
auto nwritten = handle->write((const byte*)data, size);
|
auto nwritten = handle->write((const byte*)data, size);
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$write: nwritten=%u\n", nwritten);
|
kprintf("Process::sys$write: nwritten=%u\n", nwritten);
|
||||||
#endif
|
#endif
|
||||||
return nwritten;
|
return nwritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
|
ssize_t Process::sys$read(int fd, void* outbuf, size_t nread)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(outbuf, nread);
|
VALIDATE_USER_WRITE(outbuf, nread);
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
|
kprintf("Process::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
|
||||||
#endif
|
#endif
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$read: handle=%p\n", handle);
|
kprintf("Process::sys$read: handle=%p\n", handle);
|
||||||
#endif
|
#endif
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
@ -874,12 +859,12 @@ ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
|
||||||
}
|
}
|
||||||
nread = handle->read((byte*)outbuf, nread);
|
nread = handle->read((byte*)outbuf, nread);
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$read: nread=%u\n", nread);
|
kprintf("Process::sys$read: nread=%u\n", nread);
|
||||||
#endif
|
#endif
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$close(int fd)
|
int Process::sys$close(int fd)
|
||||||
{
|
{
|
||||||
auto* handle = fileHandleIfExists(fd);
|
auto* handle = fileHandleIfExists(fd);
|
||||||
if (!handle)
|
if (!handle)
|
||||||
|
@ -888,7 +873,7 @@ int Task::sys$close(int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$lstat(const char* path, Unix::stat* statbuf)
|
int Process::sys$lstat(const char* path, Unix::stat* statbuf)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(statbuf, sizeof(Unix::stat));
|
VALIDATE_USER_WRITE(statbuf, sizeof(Unix::stat));
|
||||||
int error;
|
int error;
|
||||||
|
@ -899,7 +884,7 @@ int Task::sys$lstat(const char* path, Unix::stat* statbuf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$stat(const char* path, Unix::stat* statbuf)
|
int Process::sys$stat(const char* path, Unix::stat* statbuf)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(statbuf, sizeof(Unix::stat));
|
VALIDATE_USER_WRITE(statbuf, sizeof(Unix::stat));
|
||||||
int error;
|
int error;
|
||||||
|
@ -910,7 +895,7 @@ int Task::sys$stat(const char* path, Unix::stat* statbuf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$readlink(const char* path, char* buffer, size_t size)
|
int Process::sys$readlink(const char* path, char* buffer, size_t size)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_READ(path, strlen(path));
|
VALIDATE_USER_READ(path, strlen(path));
|
||||||
VALIDATE_USER_WRITE(buffer, size);
|
VALIDATE_USER_WRITE(buffer, size);
|
||||||
|
@ -933,7 +918,7 @@ int Task::sys$readlink(const char* path, char* buffer, size_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$chdir(const char* path)
|
int Process::sys$chdir(const char* path)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_READ(path, strlen(path));
|
VALIDATE_USER_READ(path, strlen(path));
|
||||||
int error;
|
int error;
|
||||||
|
@ -946,7 +931,7 @@ int Task::sys$chdir(const char* path)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$getcwd(char* buffer, size_t size)
|
int Process::sys$getcwd(char* buffer, size_t size)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(buffer, size);
|
VALIDATE_USER_WRITE(buffer, size);
|
||||||
auto path = VirtualFileSystem::the().absolutePath(cwdInode());
|
auto path = VirtualFileSystem::the().absolutePath(cwdInode());
|
||||||
|
@ -958,10 +943,10 @@ int Task::sys$getcwd(char* buffer, size_t size)
|
||||||
return -ENOTIMPL;
|
return -ENOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$open(const char* path, int options)
|
int Process::sys$open(const char* path, int options)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_IO
|
#ifdef DEBUG_IO
|
||||||
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
|
kprintf("Process::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
|
||||||
#endif
|
#endif
|
||||||
VALIDATE_USER_READ(path, strlen(path));
|
VALIDATE_USER_READ(path, strlen(path));
|
||||||
if (m_fileHandles.size() >= m_maxFileHandles)
|
if (m_fileHandles.size() >= m_maxFileHandles)
|
||||||
|
@ -979,7 +964,7 @@ int Task::sys$open(const char* path, int options)
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$uname(utsname* buf)
|
int Process::sys$uname(utsname* buf)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(buf, sizeof(utsname));
|
VALIDATE_USER_WRITE(buf, sizeof(utsname));
|
||||||
strcpy(buf->sysname, "Serenity");
|
strcpy(buf->sysname, "Serenity");
|
||||||
|
@ -990,7 +975,7 @@ int Task::sys$uname(utsname* buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$kill(pid_t pid, int sig)
|
int Process::sys$kill(pid_t pid, int sig)
|
||||||
{
|
{
|
||||||
(void) sig;
|
(void) sig;
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
|
@ -1003,7 +988,7 @@ int Task::sys$kill(pid_t pid, int sig)
|
||||||
}
|
}
|
||||||
ASSERT(pid != current->pid()); // FIXME: Support this scenario.
|
ASSERT(pid != current->pid()); // FIXME: Support this scenario.
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
auto* peer = Task::fromPID(pid);
|
auto* peer = Process::fromPID(pid);
|
||||||
if (!peer)
|
if (!peer)
|
||||||
return -ESRCH;
|
return -ESRCH;
|
||||||
if (sig == SIGKILL) {
|
if (sig == SIGKILL) {
|
||||||
|
@ -1015,7 +1000,7 @@ int Task::sys$kill(pid_t pid, int sig)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$sleep(unsigned seconds)
|
int Process::sys$sleep(unsigned seconds)
|
||||||
{
|
{
|
||||||
if (!seconds)
|
if (!seconds)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1023,7 +1008,7 @@ int Task::sys$sleep(unsigned seconds)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::sys$gettimeofday(timeval* tv)
|
int Process::sys$gettimeofday(timeval* tv)
|
||||||
{
|
{
|
||||||
VALIDATE_USER_WRITE(tv, sizeof(tv));
|
VALIDATE_USER_WRITE(tv, sizeof(tv));
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
|
@ -1033,28 +1018,28 @@ int Task::sys$gettimeofday(timeval* tv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uid_t Task::sys$getuid()
|
uid_t Process::sys$getuid()
|
||||||
{
|
{
|
||||||
return m_uid;
|
return m_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
gid_t Task::sys$getgid()
|
gid_t Process::sys$getgid()
|
||||||
{
|
{
|
||||||
return m_gid;
|
return m_gid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t Task::sys$getpid()
|
pid_t Process::sys$getpid()
|
||||||
{
|
{
|
||||||
return m_pid;
|
return m_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid_t Task::sys$waitpid(pid_t waitee, int* wstatus, int options)
|
pid_t Process::sys$waitpid(pid_t waitee, int* wstatus, int options)
|
||||||
{
|
{
|
||||||
if (wstatus)
|
if (wstatus)
|
||||||
VALIDATE_USER_WRITE(wstatus, sizeof(int));
|
VALIDATE_USER_WRITE(wstatus, sizeof(int));
|
||||||
|
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
if (!Task::fromPID(waitee))
|
if (!Process::fromPID(waitee))
|
||||||
return -1;
|
return -1;
|
||||||
m_waitee = waitee;
|
m_waitee = waitee;
|
||||||
m_waiteeStatus = 0;
|
m_waiteeStatus = 0;
|
||||||
|
@ -1065,21 +1050,21 @@ pid_t Task::sys$waitpid(pid_t waitee, int* wstatus, int options)
|
||||||
return m_waitee;
|
return m_waitee;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::unblock()
|
void Process::unblock()
|
||||||
{
|
{
|
||||||
ASSERT(m_state != Task::Runnable && m_state != Task::Running);
|
ASSERT(m_state != Process::Runnable && m_state != Process::Running);
|
||||||
system.nblocked--;
|
system.nblocked--;
|
||||||
m_state = Task::Runnable;
|
m_state = Process::Runnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::block(Task::State state)
|
void Process::block(Process::State state)
|
||||||
{
|
{
|
||||||
ASSERT(current->state() == Task::Running);
|
ASSERT(current->state() == Process::Running);
|
||||||
system.nblocked++;
|
system.nblocked++;
|
||||||
current->setState(state);
|
current->setState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void block(Task::State state)
|
void block(Process::State state)
|
||||||
{
|
{
|
||||||
current->block(state);
|
current->block(state);
|
||||||
yield();
|
yield();
|
||||||
|
@ -1087,19 +1072,19 @@ void block(Task::State state)
|
||||||
|
|
||||||
void sleep(DWORD ticks)
|
void sleep(DWORD ticks)
|
||||||
{
|
{
|
||||||
ASSERT(current->state() == Task::Running);
|
ASSERT(current->state() == Process::Running);
|
||||||
current->setWakeupTime(system.uptime + ticks);
|
current->setWakeupTime(system.uptime + ticks);
|
||||||
current->block(Task::BlockedSleep);
|
current->block(Process::BlockedSleep);
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
Task* Task::kernelTask()
|
Process* Process::kernelProcess()
|
||||||
{
|
{
|
||||||
ASSERT(s_kernelTask);
|
ASSERT(s_kernelProcess);
|
||||||
return s_kernelTask;
|
return s_kernelProcess;
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
|
Process::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
|
||||||
: linearAddress(a)
|
: linearAddress(a)
|
||||||
, size(s)
|
, size(s)
|
||||||
, zone(move(z))
|
, zone(move(z))
|
||||||
|
@ -1107,11 +1092,11 @@ Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Region::~Region()
|
Process::Region::~Region()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
|
Process::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
|
||||||
: region(r)
|
: region(r)
|
||||||
, offset(o)
|
, offset(o)
|
||||||
, size(s)
|
, size(s)
|
||||||
|
@ -1121,11 +1106,11 @@ Task::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Task::Subregion::~Subregion()
|
Process::Subregion::~Subregion()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::isValidAddressForKernel(LinearAddress laddr) const
|
bool Process::isValidAddressForKernel(LinearAddress laddr) const
|
||||||
{
|
{
|
||||||
// We check extra carefully here since the first 4MB of the address space is identity-mapped.
|
// We check extra carefully here since the first 4MB of the address space is identity-mapped.
|
||||||
// This code allows access outside of the known used address ranges to get caught.
|
// This code allows access outside of the known used address ranges to get caught.
|
||||||
|
@ -1138,13 +1123,13 @@ bool Task::isValidAddressForKernel(LinearAddress laddr) const
|
||||||
return validate_user_read(laddr);
|
return validate_user_read(laddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::validate_user_read(LinearAddress laddr) const
|
bool Process::validate_user_read(LinearAddress laddr) const
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
return MM.validate_user_read(*this, laddr);
|
return MM.validate_user_read(*this, laddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Task::validate_user_write(LinearAddress laddr) const
|
bool Process::validate_user_write(LinearAddress laddr) const
|
||||||
{
|
{
|
||||||
InterruptDisabler disabler;
|
InterruptDisabler disabler;
|
||||||
return MM.validate_user_write(*this, laddr);
|
return MM.validate_user_write(*this, laddr);
|
||||||
|
|
|
@ -9,27 +9,19 @@
|
||||||
#include <VirtualFileSystem/VirtualFileSystem.h>
|
#include <VirtualFileSystem/VirtualFileSystem.h>
|
||||||
#include "TTY.h"
|
#include "TTY.h"
|
||||||
|
|
||||||
//#define TASK_SANITY_CHECKS
|
|
||||||
|
|
||||||
class FileHandle;
|
class FileHandle;
|
||||||
class Zone;
|
class Zone;
|
||||||
|
|
||||||
class Task : public InlineLinkedListNode<Task> {
|
class Process : public InlineLinkedListNode<Process> {
|
||||||
friend class InlineLinkedListNode<Task>;
|
friend class InlineLinkedListNode<Process>;
|
||||||
struct Region;
|
struct Region;
|
||||||
struct Subregion;
|
struct Subregion;
|
||||||
public:
|
public:
|
||||||
static Task* createKernelTask(void (*entry)(), String&& name);
|
static Process* createKernelProcess(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);
|
static Process* createUserProcess(const String& path, uid_t, gid_t, pid_t parentPID, int& error, const char** args = nullptr, TTY* = nullptr);
|
||||||
~Task();
|
~Process();
|
||||||
|
|
||||||
static Vector<Task*> allTasks();
|
static Vector<Process*> allProcesses();
|
||||||
|
|
||||||
#ifdef TASK_SANITY_CHECKS
|
|
||||||
static void checkSanity(const char* msg = nullptr);
|
|
||||||
#else
|
|
||||||
static void checkSanity(const char*) { }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
Invalid = 0,
|
Invalid = 0,
|
||||||
|
@ -51,8 +43,8 @@ public:
|
||||||
bool isRing0() const { return m_ring == Ring0; }
|
bool isRing0() const { return m_ring == Ring0; }
|
||||||
bool isRing3() const { return m_ring == Ring3; }
|
bool isRing3() const { return m_ring == Ring3; }
|
||||||
|
|
||||||
static Task* fromPID(pid_t);
|
static Process* fromPID(pid_t);
|
||||||
static Task* kernelTask();
|
static Process* kernelProcess();
|
||||||
|
|
||||||
const String& name() const { return m_name; }
|
const String& name() const { return m_name; }
|
||||||
pid_t pid() const { return m_pid; }
|
pid_t pid() const { return m_pid; }
|
||||||
|
@ -71,13 +63,13 @@ public:
|
||||||
|
|
||||||
static void doHouseKeeping();
|
static void doHouseKeeping();
|
||||||
|
|
||||||
void block(Task::State);
|
void block(Process::State);
|
||||||
void unblock();
|
void unblock();
|
||||||
|
|
||||||
void setWakeupTime(DWORD t) { m_wakeupTime = t; }
|
void setWakeupTime(DWORD t) { m_wakeupTime = t; }
|
||||||
DWORD wakeupTime() const { return m_wakeupTime; }
|
DWORD wakeupTime() const { return m_wakeupTime; }
|
||||||
|
|
||||||
static void prepForIRETToNewTask();
|
static void prepForIRETToNewProcess();
|
||||||
|
|
||||||
bool tick() { ++m_ticks; return --m_ticksLeft; }
|
bool tick() { ++m_ticks; return --m_ticksLeft; }
|
||||||
void setTicksLeft(DWORD t) { m_ticksLeft = t; }
|
void setTicksLeft(DWORD t) { m_ticksLeft = t; }
|
||||||
|
@ -117,7 +109,7 @@ public:
|
||||||
|
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
static void taskDidCrash(Task*);
|
static void processDidCrash(Process*);
|
||||||
|
|
||||||
const TTY* tty() const { return m_tty; }
|
const TTY* tty() const { return m_tty; }
|
||||||
|
|
||||||
|
@ -147,16 +139,16 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
friend bool scheduleNewTask();
|
friend bool scheduleNewProcess();
|
||||||
|
|
||||||
Task(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& cwd = nullptr, RetainPtr<VirtualFileSystem::Node>&& executable = nullptr, TTY* = nullptr);
|
Process(String&& name, uid_t, gid_t, pid_t parentPID, RingLevel, RetainPtr<VirtualFileSystem::Node>&& cwd = nullptr, RetainPtr<VirtualFileSystem::Node>&& executable = nullptr, TTY* = nullptr);
|
||||||
|
|
||||||
void allocateLDT();
|
void allocateLDT();
|
||||||
|
|
||||||
dword* m_pageDirectory { nullptr };
|
dword* m_pageDirectory { nullptr };
|
||||||
|
|
||||||
Task* m_prev { nullptr };
|
Process* m_prev { nullptr };
|
||||||
Task* m_next { nullptr };
|
Process* m_next { nullptr };
|
||||||
|
|
||||||
String m_name;
|
String m_name;
|
||||||
void (*m_entry)() { nullptr };
|
void (*m_entry)() { nullptr };
|
||||||
|
@ -228,12 +220,10 @@ private:
|
||||||
Vector<String> m_initialEnvironment;
|
Vector<String> m_initialEnvironment;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void task_init();
|
|
||||||
extern void yield();
|
extern void yield();
|
||||||
extern bool scheduleNewTask();
|
extern bool scheduleNewProcess();
|
||||||
extern void switchNow();
|
extern void switchNow();
|
||||||
extern void block(Task::State);
|
extern void block(Process::State);
|
||||||
extern void sleep(DWORD ticks);
|
extern void sleep(DWORD ticks);
|
||||||
|
|
||||||
/* The currently executing task. NULL during kernel bootup. */
|
extern Process* current;
|
||||||
extern Task* current;
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include "Syscall.h"
|
#include "Syscall.h"
|
||||||
#include "Console.h"
|
#include "Console.h"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "IO.h"
|
#include "IO.h"
|
||||||
#include "StdLib.h"
|
#include "StdLib.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
|
|
||||||
static byte* vga_mem = nullptr;
|
static byte* vga_mem = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include "VGA.h"
|
#include "VGA.h"
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "Assertions.h"
|
#include "Assertions.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include "MemoryManager.h"
|
#include "MemoryManager.h"
|
||||||
#include "IRQHandler.h"
|
#include "IRQHandler.h"
|
||||||
#include "PIC.h"
|
#include "PIC.h"
|
||||||
|
@ -153,8 +153,7 @@ void exception_6_handler()
|
||||||
}
|
}
|
||||||
HANG;
|
HANG;
|
||||||
|
|
||||||
// NOTE: This will schedule a new task.
|
Process::processDidCrash(current);
|
||||||
Task::taskDidCrash(current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 13: General Protection Fault
|
// 13: General Protection Fault
|
||||||
|
@ -184,8 +183,7 @@ void exception_13_handler()
|
||||||
HANG;
|
HANG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: This will schedule a new task.
|
Process::processDidCrash(current);
|
||||||
Task::taskDidCrash(current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 14: Page Fault
|
// 14: Page Fault
|
||||||
|
@ -239,8 +237,7 @@ void exception_14_handler()
|
||||||
|
|
||||||
if (response == PageFaultResponse::ShouldCrash) {
|
if (response == PageFaultResponse::ShouldCrash) {
|
||||||
kprintf("Crashing after unresolved page fault\n");
|
kprintf("Crashing after unresolved page fault\n");
|
||||||
// NOTE: This will schedule a new task.
|
Process::processDidCrash(current);
|
||||||
Task::taskDidCrash(current);
|
|
||||||
} else if (response == PageFaultResponse::Continue) {
|
} else if (response == PageFaultResponse::Continue) {
|
||||||
kprintf("Continuing after resolved page fault\n");
|
kprintf("Continuing after resolved page fault\n");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "IO.h"
|
#include "IO.h"
|
||||||
#include "VGA.h"
|
#include "VGA.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "PIC.h"
|
#include "PIC.h"
|
||||||
|
|
||||||
|
@ -77,8 +77,6 @@ void clock_handle()
|
||||||
if (current->tick())
|
if (current->tick())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//return;
|
|
||||||
|
|
||||||
auto& regs = *reinterpret_cast<RegisterDump*>(state_dump);
|
auto& regs = *reinterpret_cast<RegisterDump*>(state_dump);
|
||||||
current->tss().gs = regs.gs;
|
current->tss().gs = regs.gs;
|
||||||
current->tss().fs = regs.fs;
|
current->tss().fs = regs.fs;
|
||||||
|
@ -95,31 +93,19 @@ void clock_handle()
|
||||||
current->tss().cs = regs.cs;
|
current->tss().cs = regs.cs;
|
||||||
current->tss().eflags = regs.eflags;
|
current->tss().eflags = regs.eflags;
|
||||||
|
|
||||||
// Compute task ESP.
|
// Compute process stack pointer.
|
||||||
// Add 12 for CS, EIP, EFLAGS (interrupt mechanic)
|
// Add 12 for CS, EIP, EFLAGS (interrupt mechanic)
|
||||||
|
|
||||||
// FIXME: Hmm. Should we add an extra 8 here for SS:ESP in some cases?
|
|
||||||
// If this IRQ occurred while in a user task, wouldn't that also push the stack ptr?
|
|
||||||
current->tss().esp = regs.esp + 12;
|
current->tss().esp = regs.esp + 12;
|
||||||
|
|
||||||
current->tss().ss = regs.ss;
|
current->tss().ss = regs.ss;
|
||||||
|
|
||||||
if ((current->tss().cs & 3) != 0) {
|
if ((current->tss().cs & 3) != 0) {
|
||||||
#if 0
|
|
||||||
dbgprintf("clock'ed across to ring0\n");
|
|
||||||
dbgprintf("code: %w:%x\n", current->tss().cs, current->tss().eip);
|
|
||||||
dbgprintf(" stk: %w:%x\n", current->tss().ss, current->tss().esp);
|
|
||||||
dbgprintf("astk: %w:%x\n", regs.ss_if_crossRing, regs.esp_if_crossRing);
|
|
||||||
//HANG;
|
|
||||||
#endif
|
|
||||||
current->tss().ss = regs.ss_if_crossRing;
|
current->tss().ss = regs.ss_if_crossRing;
|
||||||
current->tss().esp = regs.esp_if_crossRing;
|
current->tss().esp = regs.esp_if_crossRing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare a new task to run;
|
if (!scheduleNewProcess())
|
||||||
if (!scheduleNewTask())
|
|
||||||
return;
|
return;
|
||||||
Task::prepForIRETToNewTask();
|
Process::prepForIRETToNewProcess();
|
||||||
|
|
||||||
// Set the NT (nested task) flag.
|
// Set the NT (nested task) flag.
|
||||||
asm(
|
asm(
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "i386.h"
|
#include "i386.h"
|
||||||
#include "i8253.h"
|
#include "i8253.h"
|
||||||
#include "Keyboard.h"
|
#include "Keyboard.h"
|
||||||
#include "Task.h"
|
#include "Process.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "Disk.h"
|
#include "Disk.h"
|
||||||
#include "PIC.h"
|
#include "PIC.h"
|
||||||
|
@ -96,7 +96,7 @@ static void undertaker_main() NORETURN;
|
||||||
static void undertaker_main()
|
static void undertaker_main()
|
||||||
{
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Task::doHouseKeeping();
|
Process::doHouseKeeping();
|
||||||
sleep(300);
|
sleep(300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,9 +178,9 @@ static void init_stage2()
|
||||||
|
|
||||||
for (unsigned i = 0; i < 100; ++i) {
|
for (unsigned i = 0; i < 100; ++i) {
|
||||||
int error;
|
int error;
|
||||||
auto* shTask = Task::createUserTask("/bin/id", (uid_t)100, (gid_t)100, (pid_t)0, error);
|
auto* shProcess = Process::createUserProcess("/bin/id", (uid_t)100, (gid_t)100, (pid_t)0, error);
|
||||||
kprintf("malloc stats: alloc:%u free:%u\n", sum_alloc, sum_free);
|
kprintf("malloc stats: alloc:%u free:%u\n", sum_alloc, sum_free);
|
||||||
kprintf("sizeof(Task):%u\n", sizeof(Task));
|
kprintf("sizeof(Process):%u\n", sizeof(Process));
|
||||||
kprintf("delta:%u\n",sum_alloc - lastAlloc);
|
kprintf("delta:%u\n",sum_alloc - lastAlloc);
|
||||||
lastAlloc = sum_alloc;
|
lastAlloc = sum_alloc;
|
||||||
sleep(600);
|
sleep(600);
|
||||||
|
@ -188,11 +188,11 @@ static void init_stage2()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int error;
|
int error;
|
||||||
auto* sh0 = Task::createUserTask("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty0);
|
auto* sh0 = Process::createUserProcess("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty0);
|
||||||
#ifdef SPAWN_MULTIPLE_SHELLS
|
#ifdef SPAWN_MULTIPLE_SHELLS
|
||||||
auto* sh1 = Task::createUserTask("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty1);
|
auto* sh1 = Process::createUserProcess("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty1);
|
||||||
auto* sh2 = Task::createUserTask("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty2);
|
auto* sh2 = Process::createUserProcess("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty2);
|
||||||
auto* sh3 = Task::createUserTask("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty3);
|
auto* sh3 = Process::createUserProcess("/bin/sh", (uid_t)100, (gid_t)100, (pid_t)0, error, nullptr, tty3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -253,16 +253,16 @@ void init()
|
||||||
auto procfs = ProcFileSystem::create();
|
auto procfs = ProcFileSystem::create();
|
||||||
procfs->initialize();
|
procfs->initialize();
|
||||||
|
|
||||||
Task::initialize();
|
Process::initialize();
|
||||||
|
|
||||||
Task::createKernelTask(undertaker_main, "undertaker");
|
Process::createKernelProcess(undertaker_main, "undertaker");
|
||||||
Task::createKernelTask(init_stage2, "init");
|
Process::createKernelProcess(init_stage2, "init");
|
||||||
|
|
||||||
scheduleNewTask();
|
scheduleNewProcess();
|
||||||
|
|
||||||
sti();
|
sti();
|
||||||
|
|
||||||
// This now becomes the idle task :^)
|
// This now becomes the idle process :^)
|
||||||
for (;;) {
|
for (;;) {
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "UnixTypes.h"
|
#include "UnixTypes.h"
|
||||||
#include "TTY.h"
|
#include "TTY.h"
|
||||||
#include <AK/BufferStream.h>
|
#include <AK/BufferStream.h>
|
||||||
#include <Kernel/Task.h>
|
|
||||||
|
|
||||||
FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& vnode)
|
FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& vnode)
|
||||||
: m_vnode(move(vnode))
|
: m_vnode(move(vnode))
|
||||||
|
|
Loading…
Reference in a new issue