Skip to content

Instantly share code, notes, and snippets.

@heimskr
Created December 15, 2021 00:17
Show Gist options
  • Save heimskr/9b701378d759e32d3af6630b5dc6721e to your computer and use it in GitHub Desktop.
Save heimskr/9b701378d759e32d3af6630b5dc6721e to your computer and use it in GitHub Desktop.
# 1 "../Kernel/src/Objects/Process.cpp"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 403 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Objects/Process.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/pid_t.h" 1 3
typedef int pid_t;
# 4 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/Arch/x86_64/CPU.h" 1
# 1 "../Kernel/include/Arch/x86_64/Compiler.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 39 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 3
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__config" 1 3
# 13 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__config" 3
# 1 "/home/kai/.local/share/lemon/bin/../include/x86_64-unknown-lemon/c++/v1/__config_site" 1 3
# 14 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__config" 2 3
# 23 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__config" 3
# 812 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__config" 3
namespace std { inline namespace __1 { } }
# 40 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 2 3
# 43 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 3
# 1 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 1 3 4
# 35 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 3 4
typedef long int ptrdiff_t;
# 46 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 60 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 3 4
typedef long unsigned int rsize_t;
# 102 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 3 4
# 1 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/__stddef_max_align_t.h" 1 3 4
# 19 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/__stddef_max_align_t.h" 3 4
typedef struct {
long long __clang_max_align_nonce1
__attribute__((__aligned__(__alignof__(long long))));
long double __clang_max_align_nonce2
__attribute__((__aligned__(__alignof__(long double))));
} max_align_t;
# 103 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 2 3 4
# 46 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 2 3
extern "C++" {
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__nullptr" 1 3
# 17 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__nullptr" 3
# 54 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/__nullptr" 3
namespace std
{
typedef decltype(nullptr) nullptr_t;
}
# 51 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 2 3
using std::nullptr_t;
}
# 6 "../Kernel/include/Arch/x86_64/Compiler.h" 2
__attribute__(( always_inline )) inline void* operator new(size_t, void* p){
return p;
}
# 4 "../Kernel/include/Arch/x86_64/CPU.h" 2
# 1 "../Kernel/include/Arch/x86_64/System.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stdint.h" 1 3
# 110 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stdint.h" 3
# 123 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stdint.h" 3
# 1 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 1 3 4
# 96 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 3 4
typedef long int int64_t;
typedef long unsigned int uint64_t;
# 110 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 3 4
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
typedef int64_t int_fast64_t;
typedef uint64_t uint_fast64_t;
# 167 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 3 4
typedef int int32_t;
typedef unsigned int uint32_t;
# 184 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 3 4
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
typedef int32_t int_fast32_t;
typedef uint32_t uint_fast32_t;
# 205 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 3 4
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int16_t int_fast16_t;
typedef uint16_t uint_fast16_t;
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef int8_t int_least8_t;
typedef uint8_t uint_least8_t;
typedef int8_t int_fast8_t;
typedef uint8_t uint_fast8_t;
# 249 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdint.h" 3 4
typedef long int intptr_t;
typedef long unsigned int uintptr_t;
typedef long int intmax_t;
typedef long unsigned int uintmax_t;
# 124 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stdint.h" 2 3
# 6 "../Kernel/include/Arch/x86_64/System.h" 2
extern "C" {
void outportb(uint16_t port, uint8_t value);
void outportw(uint16_t port, uint16_t value);
void outportd(uint16_t port, uint32_t value);
void outportl(uint16_t port, uint32_t value);
uint8_t inportb(uint16_t port);
uint16_t inportw(uint16_t port);
uint32_t inportd(uint16_t port);
uint32_t inportl(uint16_t port);
}
struct RegisterContext {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rbp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
};
typedef struct {
uint16_t fcw;
uint16_t fsw;
uint8_t ftw;
uint8_t zero;
uint16_t fop;
uint64_t rip;
uint64_t rdp;
uint32_t mxcsr;
uint32_t mxcsrMask;
uint8_t st[8][16];
uint8_t xmm[16][16];
} __attribute__((packed)) fx_state_t;
static inline int CheckInterrupts() {
unsigned long flags;
asm volatile("pushf;"
"pop %%rax;"
: "=a"(flags)::"cc");
return (flags & 0x200);
}
# 5 "../Kernel/include/Arch/x86_64/CPU.h" 2
# 1 "../Kernel/include/Arch/x86_64/TSS.h" 1
typedef struct {
uint32_t reserved __attribute__((aligned(16)));
uint64_t rsp0;
uint64_t rsp1;
uint64_t rsp2;
uint64_t reserved2;
uint64_t ist1;
uint64_t ist2;
uint64_t ist3;
uint64_t ist4;
uint64_t ist5;
uint64_t ist6;
uint64_t ist7;
uint64_t reserved3;
uint32_t reserved4;
uint32_t iopbOffset;
} __attribute__((packed)) tss_t;
namespace TSS
{
void InitializeTSS(tss_t* tss, void* gdt);
inline void SetKernelStack(tss_t* tss, uint64_t stack){
tss->rsp0 = stack;
}
}
# 6 "../Kernel/include/Arch/x86_64/CPU.h" 2
class Process;
struct Thread;
template <typename T> class FastList;
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) gdt_ptr_t;
struct CPU {
CPU* self;
uint64_t id;
void* gdt;
gdt_ptr_t gdtPtr;
Thread* currentThread = nullptr;
Thread* idleThread = nullptr;
Process* idleProcess;
volatile int runQueueLock = 0;
FastList<Thread*>* runQueue;
tss_t tss __attribute__((aligned(16)));
};
enum {
CPUID_ECX_SSE3 = 1 << 0,
CPUID_ECX_PCLMUL = 1 << 1,
CPUID_ECX_DTES64 = 1 << 2,
CPUID_ECX_MONITOR = 1 << 3,
CPUID_ECX_DS_CPL = 1 << 4,
CPUID_ECX_VMX = 1 << 5,
CPUID_ECX_SMX = 1 << 6,
CPUID_ECX_EST = 1 << 7,
CPUID_ECX_TM2 = 1 << 8,
CPUID_ECX_SSSE3 = 1 << 9,
CPUID_ECX_CID = 1 << 10,
CPUID_ECX_FMA = 1 << 12,
CPUID_ECX_CX16 = 1 << 13,
CPUID_ECX_ETPRD = 1 << 14,
CPUID_ECX_PDCM = 1 << 15,
CPUID_ECX_PCIDE = 1 << 17,
CPUID_ECX_DCA = 1 << 18,
CPUID_ECX_SSE4_1 = 1 << 19,
CPUID_ECX_SSE4_2 = 1 << 20,
CPUID_ECX_x2APIC = 1 << 21,
CPUID_ECX_MOVBE = 1 << 22,
CPUID_ECX_POPCNT = 1 << 23,
CPUID_ECX_AES = 1 << 25,
CPUID_ECX_XSAVE = 1 << 26,
CPUID_ECX_OSXSAVE = 1 << 27,
CPUID_ECX_AVX = 1 << 28,
CPUID_EDX_FPU = 1 << 0,
CPUID_EDX_VME = 1 << 1,
CPUID_EDX_DE = 1 << 2,
CPUID_EDX_PSE = 1 << 3,
CPUID_EDX_TSC = 1 << 4,
CPUID_EDX_MSR = 1 << 5,
CPUID_EDX_PAE = 1 << 6,
CPUID_EDX_MCE = 1 << 7,
CPUID_EDX_CX8 = 1 << 8,
CPUID_EDX_APIC = 1 << 9,
CPUID_EDX_SEP = 1 << 11,
CPUID_EDX_MTRR = 1 << 12,
CPUID_EDX_PGE = 1 << 13,
CPUID_EDX_MCA = 1 << 14,
CPUID_EDX_CMOV = 1 << 15,
CPUID_EDX_PAT = 1 << 16,
CPUID_EDX_PSE36 = 1 << 17,
CPUID_EDX_PSN = 1 << 18,
CPUID_EDX_CLF = 1 << 19,
CPUID_EDX_DTES = 1 << 21,
CPUID_EDX_ACPI = 1 << 22,
CPUID_EDX_MMX = 1 << 23,
CPUID_EDX_FXSR = 1 << 24,
CPUID_EDX_SSE = 1 << 25,
CPUID_EDX_SSE2 = 1 << 26,
CPUID_EDX_SS = 1 << 27,
CPUID_EDX_HTT = 1 << 28,
CPUID_EDX_TM1 = 1 << 29,
CPUID_EDX_IA64 = 1 << 30,
CPUID_EDX_PBE = 1 << 31
};
typedef struct {
char vendorString[12];
char nullTerminator = '\0';
uint32_t features_ecx;
uint32_t features_edx;
} __attribute__((packed)) cpuid_info_t;
cpuid_info_t CPUID();
__attribute__(( always_inline )) inline uintptr_t GetRBP() {
volatile uintptr_t val;
asm volatile("mov %%rbp, %0" : "=r"(val));
return val;
}
__attribute__(( always_inline )) inline uintptr_t GetCR3() {
volatile uintptr_t val;
asm volatile("mov %%cr3, %0" : "=r"(val));
return val;
}
static __attribute__(( always_inline )) inline void SetCPULocal(CPU* val) {
val->self = val;
asm volatile("wrmsr" ::"a"((uintptr_t)val & 0xFFFFFFFF) ,
"d"(((uintptr_t)val >> 32) & 0xFFFFFFFF) , "c"(0xC0000102) );
asm volatile("wrmsr" ::"a"((uintptr_t)val & 0xFFFFFFFF) ,
"d"(((uintptr_t)val >> 32) & 0xFFFFFFFF) , "c"(0xC0000101) );
}
static __attribute__(( always_inline )) inline CPU* GetCPULocal() {
CPU* ret;
int intEnable = CheckInterrupts();
asm("cli");
asm volatile("swapgs; movq %%gs:0, %0; swapgs;"
: "=r"(ret));
if (intEnable)
asm("sti");
return ret;
}
class InterruptDisabler {
public:
__attribute__(( always_inline )) inline InterruptDisabler() : m_intsWereEnabled(CheckInterrupts()) { asm volatile("cli"); }
__attribute__(( always_inline )) inline ~InterruptDisabler() {
if (m_intsWereEnabled) {
asm volatile("sti");
}
}
private:
bool m_intsWereEnabled = false;
};
# 6 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/Arch/x86_64/ELF.h" 1
typedef struct ELF64Header {
unsigned char id[16];
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entry;
uint64_t phOff;
uint64_t shOff;
uint32_t flags;
uint16_t hdrSize;
uint16_t phEntrySize;
uint16_t phNum;
uint16_t shEntrySize;
uint16_t shNum;
uint16_t shStrIndex;
} __attribute__((packed)) elf64_header_t;
typedef struct ELF64ProgramHeader {
uint32_t type;
uint32_t flags;
uint64_t offset;
uint64_t vaddr;
uint64_t paddr;
uint64_t fileSize;
uint64_t memSize;
uint64_t align;
} __attribute__((packed)) elf64_program_header_t;
typedef struct ELF64DynamicEntry {
int64_t tag;
union {
uint64_t val;
uint64_t ptr;
};
} __attribute__((packed)) elf64_dynamic_t;
typedef struct ELF64Symbol {
uint32_t name;
uint8_t info;
uint8_t other;
uint16_t shIndex;
uint64_t value;
uint64_t size;
} __attribute__((packed)) elf64_symbol_t;
typedef struct ELF64Section {
uint32_t name;
uint32_t type;
uint64_t flags;
uint64_t addr;
uint64_t off;
uint64_t size;
uint32_t link;
uint32_t info;
uint64_t align;
uint64_t entSize;
} __attribute__((packed)) elf64_section_t;
typedef struct ELF64Relocation {
uint64_t offset;
uint64_t info;
} __attribute__((packed)) elf64_rel_t;
typedef struct ELF64RelocationA {
uint64_t offset;
uint64_t info;
int64_t addend;
} __attribute__((packed)) elf64_rela_t;
typedef struct {
uint64_t entry;
uint64_t pHdrSegment;
uint64_t phEntrySize;
uint64_t phNum;
char* linkerPath;
} elf_info_t;
# 172 "../Kernel/include/Arch/x86_64/ELF.h"
using ELFHeader = ELF64Header;
using ELFProgramHeader = ELF64ProgramHeader;
using ELFDynamicEntry = ELF64DynamicEntry;
using ELFSymbol = ELF64Symbol;
using ELFSection = ELF64Section;
using ELFRelocation = ELF64Relocation;
using ELFRelocationA = ELF64RelocationA;
class Process;
int VerifyELF(void* elf);
elf_info_t LoadELFSegments(Process* proc, void* elf, uintptr_t base);
# 8 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/Errno.h" 1
# 9 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/Fs/Filesystem.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 4 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "../Kernel/include/List.h" 1
# 1 "../Kernel/include/Assert.h" 1
extern "C"
[[noreturn]]
void KernelAssertionFailed(const char* msg, const char* file, int line);
# 4 "../Kernel/include/List.h" 2
# 1 "../Kernel/include/CString.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 5 "../Kernel/include/CString.h" 2
# 1 "../Kernel/include/Arch/x86_64/Paging.h" 1
# 58 "../Kernel/include/Arch/x86_64/Paging.h"
typedef uint64_t page_t;
typedef uint64_t pd_entry_t;
typedef uint64_t pdpt_entry_t;
typedef uint64_t pml4_entry_t;
typedef struct {
uint64_t phys;
page_t* virt;
} __attribute__((packed)) page_table_t;
using page_dir_t = pd_entry_t[512];
using pdpt_t = pdpt_entry_t[512];
using pml4_t = pml4_entry_t[512];
typedef struct PageMap {
pdpt_entry_t* pdpt;
pd_entry_t** pageDirs;
uint64_t* pageDirsPhys;
page_t*** pageTables;
pml4_entry_t* pml4;
uint64_t pdptPhys;
uint64_t pml4Phys;
} __attribute__((packed)) page_map_t;
struct PageFaultTrap {
uintptr_t instructionPointer;
void(*handler)();
};
class AddressSpace;
namespace Memory {
extern pml4_t kernelPML4;
PageMap* CreatePageMap();
PageMap* ClonePageMap(PageMap* pageMap);
void DestroyPageMap(PageMap* pageMap);
void InitializeVirtualMemory();
void LateInitializeVirtualMemory();
void* KernelAllocate4KPages(uint64_t amount);
void Free4KPages(void* addr, uint64_t amount, page_map_t* addressSpace);
void KernelFree4KPages(void* addr, uint64_t amount);
void FreeVirtualMemory(void* pointer, uint64_t size);
# 115 "../Kernel/include/Arch/x86_64/Paging.h"
void KernelMapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount);
# 125 "../Kernel/include/Arch/x86_64/Paging.h"
void KernelMapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, uint64_t flags);
# 135 "../Kernel/include/Arch/x86_64/Paging.h"
void MapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, PageMap* pageMap);
# 146 "../Kernel/include/Arch/x86_64/Paging.h"
void MapVirtualMemory4K(uint64_t phys, uint64_t virt, uint64_t amount, uint64_t flags, PageMap* pageMap);
uintptr_t GetIOMapping(uintptr_t addr);
bool CheckKernelPointer(uintptr_t addr, uint64_t len);
bool CheckUsermodePointer(uintptr_t addr, uint64_t len, AddressSpace* addressSpace);
uint64_t VirtualToPhysicalAddress(uint64_t addr);
uint64_t VirtualToPhysicalAddress(uint64_t addr, page_map_t* addressSpace);
void SwitchPageDirectory(uint64_t phys);
void RegisterPageFaultTrap(PageFaultTrap trap);
void PageFaultHandler(void*, RegisterContext* regs);
inline void SetPageFrame(uint64_t* page, uint64_t addr) { *page = (*page & ~0xFFFFFFFFFF000ULL) | (addr & 0xFFFFFFFFFF000ULL); }
inline void SetPageFlags(uint64_t* page, uint64_t flags) { *page |= flags; }
inline uint32_t GetPageFrame(uint64_t p) { return (p & 0xFFFFFFFFFF000ULL) >> 12; }
inline void invlpg(uintptr_t addr) { asm volatile("invlpg (%0)" ::"r"(addr)); }
}
# 7 "../Kernel/include/CString.h" 2
long strlenSafe(const char* str, size_t& size, AddressSpace* aSpace);
char* itoa(unsigned long long num, char* str, int base);
int HexStringToPointer(const char* buffer, size_t bufferSize, uintptr_t& pointerValue);
extern "C" void* memset(void* src, int c, size_t count);
extern "C" void* memcpy(void* dest, const void* src, size_t count);
extern "C" int memcmp(const void* s1, const void* s2, size_t n);
void memcpy_optimized(void* dest, void* src, size_t count);
void strcpy(char* dest, const char* src);
void strncpy(char* dest, const char* src, size_t n);
int strcmp(const char* s1, const char* s2);
char* strtok_r(char* str, const char* delim, char** saveptr);
size_t strlen(const char* str);
char* strcat(char* dest, const char* src);
char* strncat(char* dest, const char* src, size_t n);
int strncmp(const char* s1, const char* s2, size_t n);
char* strupr(char* s);
char* strnupr(char* s, size_t n);
char* strchr(const char* s, int c);
char* strnchr(const char* s, int c, size_t n);
char* strrchr(const char* s, int c);
char* strdup(const char* s);
# 5 "../Kernel/include/List.h" 2
# 1 "../Kernel/include/MM/KMalloc.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 4 "../Kernel/include/MM/KMalloc.h" 2
void* kmalloc(size_t);
void kfree(void*);
void* krealloc(void*, size_t);
# 7 "../Kernel/include/List.h" 2
# 1 "../Kernel/include/Move.h" 1
namespace std {
template<typename T>
__attribute__(( always_inline )) inline constexpr T&& move(T& t) {
return static_cast<T&&>(t);
}
}
# 8 "../Kernel/include/List.h" 2
# 1 "../Kernel/include/Spinlock.h" 1
typedef volatile int lock_t;
# 51 "../Kernel/include/Spinlock.h"
template <bool disableInterrupts = false> class ScopedSpinLock final {
public:
__attribute__(( always_inline )) inline ScopedSpinLock(lock_t& lock) : m_lock(lock) {
if constexpr (disableInterrupts) {
(void)((CheckInterrupts()) || (KernelAssertionFailed("CheckInterrupts()", "../Kernel/include/Spinlock.h", 55), 0));
({ unsigned i = 0; (void)((CheckInterrupts()) || (KernelAssertionFailed("CheckInterrupts()", "../Kernel/include/Spinlock.h", 56), 0)); asm volatile("cli"); while (__sync_lock_test_and_set(&m_lock, 1) && ++i < 0xFFFFFFF) asm("sti; pause; cli"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Spinlock.h", 56), 0)); } });
} else {
({ unsigned i = 0; while (__sync_lock_test_and_set(&m_lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Spinlock.h", 58), 0)); } });
}
}
__attribute__(( always_inline )) inline ~ScopedSpinLock() {
({ __sync_lock_release(&m_lock); });;
if constexpr (disableInterrupts) {
asm volatile("sti");
}
}
private:
lock_t& m_lock;
};
# 9 "../Kernel/include/List.h" 2
template <typename T> struct ListNode {
ListNode* next = nullptr;
ListNode* prev = nullptr;
T obj;
};
template <typename T> class List;
template <typename T> class ListIterator {
friend class List<T>;
protected:
ListNode<T>* node = nullptr;
public:
ListIterator() = default;
ListIterator(const ListIterator<T>&) = default;
ListIterator& operator++() {
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 29), 0));
node = node->next;
return *this;
}
ListIterator operator++(int) {
ListIterator<T> v = ListIterator<T>(*this);
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 38), 0));
node = node->next;
return v;
}
ListIterator& operator=(const ListIterator& other) {
node = other.node;
return *this;
}
T& operator*() {
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 51), 0));
return node->obj;
}
T* operator->() {
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 57), 0));
return &node->obj;
}
friend bool operator==(const ListIterator& l, const ListIterator& r) {
if (l.node == r.node) {
return true;
} else {
return false;
}
}
friend bool operator!=(const ListIterator& l, const ListIterator& r) {
if (l.node != r.node) {
return true;
} else {
return false;
}
}
};
template <typename T> class FastList final {
public:
FastList() {
front = __null;
back = __null;
num = 0;
}
FastList(T&& other) {
front = other.front;
back = other.back;
num = other.num;
memset(&other, 0, sizeof(FastList<T>));
}
__attribute__(( always_inline )) inline FastList<T>& operator=(FastList<T>&& other) {
front = other.front;
back = other.back;
num = other.num;
memset(&other, 0, sizeof(FastList<T>));
return *this;
}
FastList(FastList& other) = delete;
__attribute__(( always_inline )) inline FastList<T>& operator=(const FastList<T>& other) = delete;
~FastList() {}
void clear() {
front = __null;
back = __null;
num = 0;
}
void add_back(const T& obj) {
obj->next = front;
if (!front) {
obj->prev = obj;
obj->next = obj;
front = obj;
} else {
(void)((back) || (KernelAssertionFailed("back", "../Kernel/include/List.h", 126), 0));
obj->prev = back;
back->next = obj;
front->prev = obj;
}
back = obj;
num++;
}
void add_front(const T& obj) {
if (!back) {
obj->prev = obj;
obj->next = obj;
back = obj;
} else {
(void)((front) || (KernelAssertionFailed("front", "../Kernel/include/List.h", 144), 0));
obj->next = front;
front->prev = obj;
back->next = obj;
}
front = obj;
obj->prev = back;
num++;
}
void insert(const T& obj, T& it) {
if (it == front) {
add_front(obj);
return;
}
(void)((it) || (KernelAssertionFailed("it", "../Kernel/include/List.h", 163), 0));
obj->prev = it->prev;
obj->next = it;
if (it->prev) {
it->prev->next = obj;
}
it->prev = obj;
num++;
}
T operator[](unsigned pos) { return get_at(pos); }
T get_at(unsigned pos) {
(void)((num > 0 && pos < num && front) || (KernelAssertionFailed("num > 0 && pos < num && front", "../Kernel/include/List.h", 179), 0));
T current = front;
for (unsigned int i = 0; i < pos && i < num && current->next; i++)
current = current->next;
return current;
}
__attribute__((always_inline)) inline unsigned get_length() const { return num; }
T remove_at(unsigned pos) {
(void)((num > 0) || (KernelAssertionFailed("num > 0", "../Kernel/include/List.h", 192), 0));
(void)((pos < num) || (KernelAssertionFailed("pos < num", "../Kernel/include/List.h", 193), 0));
(void)((front != nullptr) || (KernelAssertionFailed("front != nullptr", "../Kernel/include/List.h", 194), 0));
T current = front;
for (unsigned int i = 0; i < pos && current; i++)
current = current->next;
(void)((current) || (KernelAssertionFailed("current", "../Kernel/include/List.h", 201), 0));
if (current->next)
current->next->prev = current->prev;
if (current->prev)
current->prev->next = current->next;
if (front == current)
front = current->next;
if (back == current)
back = current->prev;
current->next = current->prev = nullptr;
if (!(--num))
front = back = nullptr;
return current;
}
void remove(T obj) {
if (!front || !num) {
(void)((front && num) || (KernelAssertionFailed("front && num", "../Kernel/include/List.h", 222), 0));
return;
}
if (obj->next && obj->next != obj) {
(void)((obj->next->prev == obj) || (KernelAssertionFailed("obj->next->prev == obj", "../Kernel/include/List.h", 227), 0));
obj->next->prev = obj->prev;
}
if (obj->prev && obj->prev != obj) {
(void)((obj->prev->next == obj) || (KernelAssertionFailed("obj->prev->next == obj", "../Kernel/include/List.h", 232), 0));
obj->prev->next = obj->next;
}
if (front == obj)
front = obj->next;
if (back == obj)
back = obj->prev;
obj->next = obj->prev = nullptr;
--num;
if (!num)
front = back = nullptr;
}
__attribute__((always_inline)) inline T next(const T& o) const {
if (o->next == front) {
return nullptr;
}
return o->next;
}
__attribute__((always_inline)) inline T get_front() const { return front; }
__attribute__((always_inline)) inline T get_back() const { return back; }
public:
T front;
T back;
unsigned num;
};
template <typename T> class List {
public:
List() {
front = __null;
back = __null;
num = 0;
lock = 0;
}
~List() {
({ __sync_lock_release(&lock); });;
clear();
while (cache.get_length()) {
kfree(cache.remove_at(0));
}
}
List& operator=(const List& l) {
clear();
for (auto& i : l) {
add_back(i);
}
return *this;
}
List& operator=(List&& l) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&l.lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 297), 0)); } });
front = l.front;
back = l.back;
num = l.num;
cache = std::move(l.cache);
l.front = nullptr;
l.back = nullptr;
l.num = 0;
({ __sync_lock_release(&l.lock); });;
return *this;
}
void clear() {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 314), 0)); } });
ListNode<T>* node = front;
while (node && node->next) {
ListNode<T>* n = node->next;
DestroyNode(node);
node = n;
}
front = __null;
back = __null;
num = 0;
({ __sync_lock_release(&lock); });;
}
T& add_back(T&& obj) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 331), 0)); } });
ListNode<T>* node = AllocateNode();
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 334), 0));
new (&node->obj) T(std::move(obj));
node->next = node->prev = nullptr;
if (!front) {
front = node;
} else if (back) {
back->next = node;
node->prev = back;
}
back = node;
num++;
({ __sync_lock_release(&lock); });;
return node->obj;
}
T& add_back(const T& obj) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 354), 0)); } });
ListNode<T>* node = AllocateNode();
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 357), 0));
new (&node->obj) T(obj);
node->next = node->prev = nullptr;
if (!front) {
front = node;
} else if (back) {
back->next = node;
node->prev = back;
}
back = node;
num++;
({ __sync_lock_release(&lock); });;
return node->obj;
}
void add_back_unlocked(const T& obj) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 377), 0)); } });
ListNode<T>* node = AllocateNode();
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 381), 0));
new (&node->obj) T(obj);
node->next = node->prev = nullptr;
if (!front) {
front = node;
} else if (back) {
back->next = node;
node->prev = back;
}
back = node;
num++;
({ __sync_lock_release(&lock); });;
}
T& add_front(const T& obj) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 399), 0)); } });
ListNode<T>* node = AllocateNode();
new (&node->obj) T(obj);
node->next = node->prev = nullptr;
if (!back) {
back = node;
} else if (front) {
front->prev = node;
node->next = front;
}
front = node;
num++;
({ __sync_lock_release(&lock); });;
return node->obj;
}
void insert(const T& obj, size_t pos) {
if (!num) {
add_back(obj);
return;
}
if (!pos) {
add_front(obj);
return;
}
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 432), 0)); } });
ListNode<T>* current = front;
for (unsigned int i = 0; i < pos && i < num && current->next; i++)
current = current->next;
ListNode<T>* node = AllocateNode();
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 440), 0));
new (&node->obj) T(obj);
InsertNodeAfter(current);
({ __sync_lock_release(&lock); });;
}
T& insert(const T& obj, ListIterator<T>& it) {
if (it.node == back) {
return add_back(obj);
}
(void)((it.node) || (KernelAssertionFailed("it.node", "../Kernel/include/List.h", 453), 0));
ListNode<T>* current = it.node;
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 456), 0)); } });
ListNode<T>* node = AllocateNode();
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 459), 0));
new (&node->obj) T(obj);
InsertNodeBefore(node, current);
({ __sync_lock_release(&lock); });;
return node->obj;
}
T& insert(T&& obj, ListIterator<T>& it) {
if (it.node == back) {
return add_back(obj);
}
(void)((it.node) || (KernelAssertionFailed("it.node", "../Kernel/include/List.h", 474), 0));
ListNode<T>* current = it.node;
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 477), 0)); } });
ListNode<T>* node = AllocateNode();
(void)((node) || (KernelAssertionFailed("node", "../Kernel/include/List.h", 480), 0));
new (&node->obj) T(std::move(obj));
InsertNodeBefore(node, current);
({ __sync_lock_release(&lock); });;
return node->obj;
}
__attribute__(( always_inline )) inline T& operator[](unsigned pos) { return get_at(pos); }
T& get_at(unsigned pos) {
(void)((num > 0 && pos < num && front != nullptr) || (KernelAssertionFailed("num > 0 && pos < num && front != nullptr", "../Kernel/include/List.h", 493), 0));
ListNode<T>* current = front;
for (unsigned int i = 0; i < pos && i < num && current->next; i++)
current = current->next;
return current->obj;
}
void replace_at(unsigned pos, const T& obj) {
(void)((num > 0 && pos < num) || (KernelAssertionFailed("num > 0 && pos < num", "../Kernel/include/List.h", 504), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 506), 0)); } });
ListNode<T>* current = front;
for (unsigned int i = 0; i < pos; i++)
current = current->next;
if (current) {
current->obj = obj;
}
({ __sync_lock_release(&lock); });;
}
void replace_at(unsigned pos, T&& obj) {
(void)((num > 0 && pos < num) || (KernelAssertionFailed("num > 0 && pos < num", "../Kernel/include/List.h", 521), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 523), 0)); } });
ListNode<T>* current = front;
for (unsigned int i = 0; i < pos; i++)
current = current->next;
if (current) {
current->obj = obj;
}
({ __sync_lock_release(&lock); });;
}
__attribute__(( always_inline )) inline unsigned get_length() const { return num; }
T remove_at(unsigned pos) {
(void)((num > 0) || (KernelAssertionFailed("num > 0", "../Kernel/include/List.h", 540), 0));
(void)((pos < num) || (KernelAssertionFailed("pos < num", "../Kernel/include/List.h", 541), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 543), 0)); } });
(void)((front != nullptr) || (KernelAssertionFailed("front != nullptr", "../Kernel/include/List.h", 544), 0));
ListNode<T>* current = front;
for (unsigned int i = 0; i < pos && current; i++)
current = current->next;
(void)((current) || (KernelAssertionFailed("current", "../Kernel/include/List.h", 551), 0));
T obj = std::move(current->obj);
num--;
if (front == current)
front = current->next;
if (back == current)
back = current->prev;
if (current->next)
current->next->prev = current->prev;
if (current->prev)
current->prev->next = current->next;
current->obj.~T();
if (cache.get_length() >= maxCache) {
kfree(current);
} else {
cache.add_back(current);
}
if (!num)
front = back = nullptr;
({ __sync_lock_release(&lock); });;
return obj;
}
T remove_at_force_cache(unsigned pos) {
(void)((num > 0) || (KernelAssertionFailed("num > 0", "../Kernel/include/List.h", 583), 0));
(void)((pos < num) || (KernelAssertionFailed("pos < num", "../Kernel/include/List.h", 584), 0));
(void)((front != nullptr) || (KernelAssertionFailed("front != nullptr", "../Kernel/include/List.h", 585), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 587), 0)); } });
ListNode<T>* current = front;
for (unsigned int i = 0; i < pos && current; i++)
current = current->next;
(void)((current) || (KernelAssertionFailed("current", "../Kernel/include/List.h", 594), 0));
T obj = std::move(current->obj);
num--;
if (front == current)
front = current->next;
if (back == current)
back = current->prev;
if (current->next)
current->next->prev = current->prev;
if (current->prev)
current->prev->next = current->next;
current->obj.~T();
cache.add_back(current);
if (!num)
front = back = nullptr;
({ __sync_lock_release(&lock); });;
return obj;
}
void remove(T val) {
if (num <= 0 || !front) {
return;
}
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 625), 0)); } });
ListNode<T>* current = front;
while (current && current != back && current->obj != val)
current = current->next;
if (current) {
if (current->prev)
current->prev->next = current->next;
if (current->next)
current->next->prev = current->prev;
if (front == current)
front = current->next;
if (back == current)
back = current->prev;
num--;
DestroyNode(current);
}
({ __sync_lock_release(&lock); });;
}
void remove(ListIterator<T>& it) {
(void)((it.node) || (KernelAssertionFailed("it.node", "../Kernel/include/List.h", 651), 0));
ListNode<T>* current = it.node;
if (current) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 655), 0)); } });
if (current->prev)
current->prev->next = current->next;
if (current->next)
current->next->prev = current->prev;
if (front == current)
front = current->next;
if (back == current)
back = current->prev;
it.node = current->prev;
num--;
DestroyNode(current);
({ __sync_lock_release(&lock); });;
}
}
void allocate(unsigned count) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/List.h", 677), 0)); } });
while (count--) {
cache.add_back((ListNode<T>*)kmalloc(sizeof(ListNode<T>)));
}
({ __sync_lock_release(&lock); });;
}
T& get_front() const {
(void)((front) || (KernelAssertionFailed("front", "../Kernel/include/List.h", 687), 0));
return front->obj;
}
T& get_back() const {
(void)((back) || (KernelAssertionFailed("back", "../Kernel/include/List.h", 692), 0));
return back->obj;
}
ListIterator<T> begin() const {
ListIterator<T> it;
if (!num || !front) {
it.node = nullptr;
} else {
it.node = front;
}
return it;
}
ListIterator<T> end() const {
ListIterator<T> it;
it.node = nullptr;
return it;
}
private:
__attribute__(( always_inline )) inline void InsertNodeBefore(ListNode<T>* node, ListNode<T>* existingNode) {
(void)((node && existingNode) || (KernelAssertionFailed("node && existingNode", "../Kernel/include/List.h", 716), 0));
node->prev = existingNode->prev;
node->next = existingNode;
if (existingNode->prev) {
existingNode->prev->next = node;
}
existingNode->prev = node;
if (existingNode == front) {
front = node;
}
num++;
}
__attribute__(( always_inline )) inline void InsertNodeAfter(ListNode<T>* node, ListNode<T>* existingNode) {
(void)((node && existingNode) || (KernelAssertionFailed("node && existingNode", "../Kernel/include/List.h", 734), 0));
node->prev = existingNode;
node->next = existingNode->next;
if (existingNode->next) {
existingNode->next->prev = node;
}
existingNode->next = node;
if (existingNode == back) {
back = node;
}
num++;
}
__attribute__(( always_inline )) inline ListNode<T>* AllocateNode() {
if (!cache.get_length()) {
return (ListNode<T>*)kmalloc(sizeof(ListNode<T>));
} else {
return cache.remove_at(0);
}
}
__attribute__(( always_inline )) inline void DestroyNode(ListNode<T>* node) {
node->obj.~T();
if (cache.get_length() >= maxCache) {
kfree(node);
} else {
cache.add_back(node);
}
}
ListNode<T>* front;
ListNode<T>* back;
unsigned num;
volatile int lock = 0;
const unsigned maxCache = 6;
FastList<ListNode<T>*> cache;
};
# 7 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "../Kernel/include/Lock.h" 1
# 1 "../Kernel/include/Arch/x86_64/Thread.h" 1
# 1 "../Kernel/include/MiscHdr.h" 1
enum {
VideoModeIndexed = 0,
VideoModeRGB = 1,
VideoModeText = 2,
};
typedef struct{
uint32_t width;
uint32_t height;
uint16_t bpp;
uint32_t pitch;
void* address;
uintptr_t physicalAddress;
int type;
} video_mode_t;
typedef struct {
uintptr_t totalMemory;
} memory_info_t;
typedef struct {
uintptr_t base;
uintptr_t size;
} boot_module_t;
# 6 "../Kernel/include/Arch/x86_64/Thread.h" 2
# 1 "../Kernel/include/Signal.h" 1
typedef void (*__sighandler) (int);
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/signal.h" 1 3
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/uid_t.h" 1 3
typedef unsigned int uid_t;
# 6 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/signal.h" 2 3
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/bits/size_t.h" 1 3
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 15 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 3
# 1 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 1 3 4
# 46 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 18 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 2 3
# 6 "/home/kai/.local/share/lemon/sysroot/system/include/bits/size_t.h" 2 3
# 7 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/signal.h" 2 3
union sigval {
int sival_int;
void *sival_ptr;
};
typedef struct {
int si_signo;
int si_code;
int si_errno;
pid_t si_pid;
uid_t si_uid;
void *si_addr;
int si_status;
union sigval si_value;
} siginfo_t;
extern "C" {
# 69 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/signal.h" 3
typedef long sigset_t;
# 91 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/signal.h" 3
typedef struct __stack {
void *ss_sp;
size_t ss_size;
int ss_flags;
} stack_t;
# 114 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/signal.h" 3
struct sigevent {
int sigev_notify;
int sigev_signo;
union sigval sigev_value;
void (*sigev_notify_function)(union sigval);
};
struct sigaction {
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flags;
void (*sa_sigaction)(int, siginfo_t *, void *);
};
typedef struct {
unsigned long oldmask;
unsigned long gregs[16];
unsigned long pc, pr, sr;
unsigned long gbr, mach, macl;
unsigned long fpregs[16];
unsigned long xfpregs[16];
unsigned int fpscr, fpul, ownedfp;
} mcontext_t;
}
# 7 "../Kernel/include/Signal.h" 2
enum class SignalAction : int {
Die = 0,
Ignore = 1,
UsermodeHandler = 2,
};
__attribute__(( always_inline )) inline SignalAction DefaultActionForSignal(int signum){
switch(signum){
case 11:
case 7:
case 4:
case 8:
case 6:
case 14:
case 1:
case 2:
case 29:
case 9:
case 13:
case 30:
case 3:
return SignalAction::Die;
default:
return SignalAction::Ignore;
}
}
struct SignalHandler {
enum class HandlerAction {
Default = 0,
Ignore = 1,
UsermodeHandler = 2,
};
enum {
FlagSignalInfo = (1 << 4),
FlagNoChildStop = (1 << 0),
FlagNoChildWait = (1 << 5),
FlagNoDefer = (1 << 6),
FlagOnStack = (1 << 1),
FlagResetHand = (1 << 2),
FlagRestart = (1 << 3),
};
static const int supportedFlags = (1 << 6);
HandlerAction action = HandlerAction::Default;
int flags = 0;
sigset_t mask = 0;
void* userHandler = nullptr;
__attribute__(( always_inline )) inline bool Ignore() const { return action == HandlerAction::Ignore; }
};
# 8 "../Kernel/include/Arch/x86_64/Thread.h" 2
# 1 "../Kernel/include/Arch/x86_64/Timer.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/bits/posix/timeval.h" 1 3
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/bits/ansi/time_t.h" 1 3
typedef long time_t;
# 5 "/home/kai/.local/share/lemon/sysroot/system/include/bits/posix/timeval.h" 2 3
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/bits/posix/suseconds_t.h" 1 3
typedef long suseconds_t;
# 6 "/home/kai/.local/share/lemon/sysroot/system/include/bits/posix/timeval.h" 2 3
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
# 6 "../Kernel/include/Arch/x86_64/Timer.h" 2
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/bits/ansi/timespec.h" 1 3
struct timespec {
time_t tv_sec;
long tv_nsec;
};
# 7 "../Kernel/include/Arch/x86_64/Timer.h" 2
typedef long time_t;
typedef struct timespec timespec_t;
static inline bool operator<(timeval l, timeval r){
return (l.tv_sec < r.tv_sec) || (l.tv_sec == r.tv_sec && l.tv_usec < r.tv_usec);
}
namespace Timer{
uint64_t GetSystemUptime();
uint32_t GetTicks();
uint32_t GetFrequency();
timeval GetSystemUptimeStruct();
long TimeDifference(const timeval& newTime, const timeval& oldTime);
void Wait(long ms);
void SleepCurrentThread(timeval& time);
void Initialize(uint32_t freq);
}
inline long operator-(const timeval& l, const timeval& r){
return Timer::TimeDifference(l, r);
}
# 9 "../Kernel/include/Arch/x86_64/Thread.h" 2
enum {
ThreadStateRunning,
ThreadStateBlocked,
ThreadStateZombie,
ThreadStateDying,
};
class Process;
struct Thread;
class ThreadBlocker{
friend struct Thread;
protected:
lock_t lock = 0;
Thread* thread = nullptr;
bool shouldBlock = true;
bool interrupted = false;
bool removed = false;
public:
virtual ~ThreadBlocker() = default;
virtual void Interrupt();
virtual void Unblock();
inline bool ShouldBlock() { return shouldBlock; }
inline bool WasInterrupted() { return interrupted; }
};
class GenericThreadBlocker : public ThreadBlocker{
public:
inline void Interrupt() {}
};
using FutexThreadBlocker = GenericThreadBlocker;
struct Thread {
lock_t lock = 0;
lock_t stateLock = 0;
Process* parent;
pid_t tid = 1;
void* stack = nullptr;
void* stackLimit = nullptr;
void* kernelStack = nullptr;
uint32_t timeSlice = 10;
uint32_t timeSliceDefault = 10;
RegisterContext registers;
RegisterContext lastSyscall;
void* fxState;
Thread* next = nullptr;
Thread* prev = nullptr;
uint8_t priority = 0;
uint8_t state = ThreadStateRunning;
uint64_t fsBase = 0;
bool blockTimedOut = false;
ThreadBlocker* blocker = nullptr;
uint64_t pendingSignals = 0;
uint64_t signalMask = 0;
Thread(class Process* _parent, pid_t _tid);
void Signal(int signal);
void HandlePendingSignal(RegisterContext* regs);
# 101 "../Kernel/include/Arch/x86_64/Thread.h"
[[nodiscard]] bool Block(ThreadBlocker* blocker);
# 113 "../Kernel/include/Arch/x86_64/Thread.h"
[[nodiscard]] bool Block(ThreadBlocker* blocker, long& usTimeout);
void Sleep(long us);
# 130 "../Kernel/include/Arch/x86_64/Thread.h"
void Unblock();
};
# 7 "../Kernel/include/Lock.h" 2
# 1 "../Kernel/include/Logging.h" 1
# 1 "../Kernel/include/Video/VideoConsole.h" 1
struct ConsoleCharacter
{
char c;
uint8_t r, g, b;
} __attribute__((packed));
class VideoConsole{
public:
int cursorX;
int cursorY;
int x;
int y;
int width;
int height;
int widthInCharacters;
int heightInCharacters;
ConsoleCharacter* characterBuffer;
VideoConsole(int x, int y, int width, int height);
void Update();
void Clear(uint8_t r, uint8_t g, uint8_t b);
void Print(char c, uint8_t r, uint8_t g, uint8_t b);
void Print(const char* str, uint8_t r, uint8_t g, uint8_t b);
void PrintN(const char* str, unsigned n, uint8_t r, uint8_t g, uint8_t b);
private:
void Scroll();
};
# 4 "../Kernel/include/Logging.h" 2
# 1 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdarg.h" 1 3 4
# 14 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdarg.h" 3 4
typedef __builtin_va_list va_list;
# 32 "/home/kai/.local/share/lemon/lib/clang/13.0.0/include/stdarg.h" 3 4
typedef __builtin_va_list __gnuc_va_list;
# 5 "../Kernel/include/Logging.h" 2
# 1 "../Kernel/include/Arch/x86_64/Debug.h" 1
enum{
DebugLevelQuiet = 0,
DebugLevelNormal = 1,
DebugLevelVerbose = 2,
};
# 17 "../Kernel/include/Arch/x86_64/Debug.h"
extern const int debugLevelHAL;
extern const int debugLevelScheduler;
extern const int debugLevelMisc;
extern const int debugLevelModules;
extern const int debugLevelSymbols;
extern const int debugLevelACPI;
extern const int debugLevelAHCI;
extern const int debugLevelATA;
extern const int debugLevelNVMe;
extern const int debugLevelPartitions;
extern const int debugLevelFilesystem;
extern const int debugLevelTmpFS;
extern const int debugLevelExt2;
extern const int debugLevelXHCI;
extern const int debugLevelInterrupts;
extern const int debugLevelMessageEndpoint;
extern const int debugLevelSyscalls;
extern const int debugLevelUsermodeMM;
extern const int debugLevelNetwork;
# 7 "../Kernel/include/Logging.h" 2
namespace Log{
extern VideoConsole* console;
void LateInitialize();
void SetVideoConsole(VideoConsole* con);
void DisableBuffer();
void EnableBuffer();
void WriteF(const char* __restrict format, va_list args);
void Write(const char* str, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255);
void Write(unsigned long long num, bool hex = true, uint8_t r = 255, uint8_t g = 255, uint8_t b = 255);
void Print(const char* __restrict fmt, ...);
void Warning(unsigned long long num);
void Warning(const char* __restrict fmt, ...);
void Error(unsigned long long num, bool hex = true);
void Error(const char* __restrict fmt, ...);
void Info(unsigned long long num, bool hex = true);
void Info(const char* __restrict fmt, ...);
__attribute__((always_inline)) inline static void Debug(const int& var, const int lvl, const char* __restrict fmt, ...){
if(var >= lvl){
Write("\r\n[INFO] ");
va_list args;
__builtin_va_start(args, fmt);
WriteF(fmt, args);
__builtin_va_end(args);
}
}
}
# 8 "../Kernel/include/Lock.h" 2
class Semaphore {
protected:
lock_t value = 0;
lock_t lock = 0;
class SemaphoreBlocker : public ThreadBlocker{
friend class Semaphore;
public:
SemaphoreBlocker* next = nullptr;
SemaphoreBlocker* prev = nullptr;
Semaphore* semaphore = nullptr;
inline SemaphoreBlocker(Semaphore* sema) : semaphore(sema) {
}
void Interrupt(){
interrupted = true;
shouldBlock = false;
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Lock.h", 30), 0)); } });
if(semaphore){
semaphore->blocked.remove(this);
semaphore = nullptr;
}
if(thread){
thread->Unblock();
}
thread = nullptr;
({ __sync_lock_release(&lock); });;
}
void Unblock(){
shouldBlock = false;
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Lock.h", 47), 0)); } });
if(semaphore){
semaphore->blocked.remove(this);
}
semaphore = nullptr;
if(thread){
thread->Unblock();
}
({ __sync_lock_release(&lock); });;
}
~SemaphoreBlocker(){
if(semaphore){
semaphore->blocked.remove(this);
}
}
};
FastList<SemaphoreBlocker*> blocked;
public:
Semaphore(int val) : value(val) {};
inline void SetValue(int val){
value = val;
}
inline lock_t GetValue(){
return value;
}
[[nodiscard]] bool Wait();
[[nodiscard]] bool WaitTimeout(long& timeout);
void Signal();
};
class ReadWriteLock {
unsigned activeReaders = 0;
lock_t fileLock = 0;
lock_t lock = 0;
bool writerAcquiredLock = false;
FastList<Thread*> readers;
FastList<Thread*> writers;
public:
__attribute__(( always_inline )) inline ReadWriteLock() {}
__attribute__(( always_inline )) inline void AcquireRead(){
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Lock.h", 98), 0)); } });
if(__atomic_add_fetch(&activeReaders, 1, 2) == 1){
({ unsigned i = 0; while (__sync_lock_test_and_set(&fileLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Lock.h", 101), 0)); } });
}
({ __sync_lock_release(&lock); });;
}
__attribute__(( always_inline )) inline void AcquireWrite(){
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Lock.h", 108), 0)); } });
({ unsigned i = 0; while (__sync_lock_test_and_set(&fileLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Lock.h", 109), 0)); } });
}
__attribute__(( always_inline )) inline bool TryAcquireWrite(){
if(!writerAcquiredLock && ({ int status; status = __sync_lock_test_and_set(&lock, 1); status; })){
return true;
}
writerAcquiredLock = true;
if(({ int status; status = __sync_lock_test_and_set(&fileLock, 1); status; })){
return true;
}
writerAcquiredLock = false;
return false;
}
__attribute__(( always_inline )) inline void ReleaseRead(){
if(__atomic_sub_fetch(&activeReaders, 1, 3) == 0){
({ __sync_lock_release(&fileLock); });;
}
}
__attribute__(( always_inline )) inline void ReleaseWrite(){
({ __sync_lock_release(&fileLock); });;
({ __sync_lock_release(&lock); });;
}
__attribute__(( always_inline )) inline bool IsWriteLocked() const { return lock && activeReaders == 0; }
};
using FilesystemLock = ReadWriteLock;
# 8 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "../Kernel/include/RefPtr.h" 1
# 1 "../Kernel/include/TTraits.h" 1
template <typename T> class TTraits {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return false; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "undefined"; }
};
template <> class TTraits<char> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "char"; }
};
template <> class TTraits<int8_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "int8_t"; }
};
template <> class TTraits<uint8_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "uint8_t"; }
};
template <> class TTraits<int16_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "int16_t"; }
};
template <> class TTraits<uint16_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "uint16_t"; }
};
template <> class TTraits<int32_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "int32_t"; }
};
template <> class TTraits<uint32_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "uint32_t"; }
};
template <> class TTraits<int64_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "int64_t"; }
};
template <> class TTraits<uint64_t> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "uint64_t"; }
};
template <typename T> class TTraits<T*> {
public:
__attribute__(( always_inline )) inline static constexpr bool is_trivial() { return true; }
__attribute__(( always_inline )) inline static constexpr const char* name() { return "T*"; }
};
# 5 "../Kernel/include/RefPtr.h" 2
# 1 "../subprojects/cxxshim/stage2/include/cstddef" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 5 "../subprojects/cxxshim/stage2/include/cstddef" 2
namespace std {
enum class [[gnu::may_alias]] byte : unsigned char { };
using nullptr_t = decltype(nullptr);
}
# 12 "../Kernel/include/RefPtr.h" 2
template <typename T> class FancyRefPtr {
public:
template <class U> FancyRefPtr(const FancyRefPtr<U>& s, T* p) : refCount(s.GetRefCount()), obj(p) {
__sync_fetch_and_add(refCount, 1);
}
FancyRefPtr() : refCount(nullptr), obj(nullptr) {}
FancyRefPtr(std::nullptr_t) : refCount(nullptr), obj(nullptr) {}
FancyRefPtr(T&& v) {
refCount = new unsigned(1);
obj = new T(v);
}
FancyRefPtr(T* p) : obj(p) {
if (obj) {
refCount = new unsigned(1);
} else {
refCount = nullptr;
}
}
FancyRefPtr(const FancyRefPtr<T>& ptr) {
obj = ptr.obj;
refCount = ptr.refCount;
if (obj && refCount) {
__sync_fetch_and_add(refCount, 1);
}
}
FancyRefPtr(FancyRefPtr<T>&& ptr) {
obj = ptr.obj;
refCount = ptr.refCount;
ptr.obj = nullptr;
ptr.refCount = nullptr;
}
virtual ~FancyRefPtr() { Dereference(); }
__attribute__(( always_inline )) inline T* get() const { return obj; }
__attribute__(( always_inline )) inline unsigned* GetRefCount() const { return refCount; }
FancyRefPtr<T>& operator=(const FancyRefPtr<T>& ptr) {
Dereference();
obj = ptr.obj;
refCount = ptr.refCount;
if (obj && refCount) {
__sync_fetch_and_add(refCount, 1);
}
return *this;
}
FancyRefPtr<T>& operator=(FancyRefPtr<T>&& ptr) {
Dereference();
obj = ptr.obj;
refCount = ptr.refCount;
ptr.obj = nullptr;
ptr.refCount = nullptr;
return *this;
}
__attribute__(( always_inline )) inline FancyRefPtr& operator=(std::nullptr_t) {
Dereference();
obj = nullptr;
refCount = nullptr;
return *this;
}
__attribute__(( always_inline )) inline bool operator==(const T* p) { return (obj == p); }
__attribute__(( always_inline )) inline bool operator!=(const T* p) { return (obj != p); }
__attribute__(( always_inline )) inline T& operator*() const {
(void)((obj) || (KernelAssertionFailed("obj", "../Kernel/include/RefPtr.h", 108), 0));
return *(obj);
}
__attribute__(( always_inline )) inline T* operator->() const {
(void)((obj) || (KernelAssertionFailed("obj", "../Kernel/include/RefPtr.h", 116), 0));
return obj;
}
__attribute__(( always_inline )) inline operator bool() { return obj; }
protected:
__attribute__(( always_inline )) inline void Dereference() {
if (refCount) {
__sync_fetch_and_sub(refCount, 1);
if (*refCount <= 0 && obj) {
delete obj;
delete refCount;
}
}
refCount = nullptr;
obj = nullptr;
}
unsigned* refCount = nullptr;
T* obj = nullptr;
};
template <class T, class U>
__attribute__(( always_inline )) inline static constexpr FancyRefPtr<T> static_pointer_cast(const FancyRefPtr<U>& src) {
return FancyRefPtr<T>(src, static_cast<T*>(src.get()));
}
# 9 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "../Kernel/include/String.h" 1
# 10 "../Kernel/include/String.h"
# 1 "../Kernel/include/Vector.h" 1
# 1 "../Kernel/include/Arch/x86_64/Memory.h" 1
# 1 "../Kernel/include/Arch/x86_64/PhysicalAllocator.h" 1
# 1 "../Kernel/include/Arch/x86_64/Serial.h" 1
namespace Serial {
void Initialize();
void Unlock();
void Write(const char c);
void Write(const char* s);
void Write(const char* s, unsigned n);
}
# 6 "../Kernel/include/Arch/x86_64/PhysicalAllocator.h" 2
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 7 "../Kernel/include/Arch/x86_64/PhysicalAllocator.h" 2
# 17 "../Kernel/include/Arch/x86_64/PhysicalAllocator.h"
extern void* kernel_end;
namespace Memory {
void InitializePhysicalAllocator(memory_info_t* mem_info);
uint64_t GetFirstFreeMemoryBlock();
void MarkMemoryRegionUsed(uint64_t base, size_t size);
void MarkMemoryRegionFree(uint64_t base, size_t size);
uint64_t AllocatePhysicalMemoryBlock();
uint64_t AllocateLargePhysicalMemoryBlock();
void FreePhysicalMemoryBlock(uint64_t addr);
extern uint64_t usedPhysicalBlocks;
extern uint64_t maxPhysicalBlocks;
}
# 7 "../Kernel/include/Arch/x86_64/Memory.h" 2
typedef struct {
uint64_t base;
uint64_t pageCount;
} mem_region_t;
# 5 "../Kernel/include/Vector.h" 2
template <typename T> class Vector {
class VectorIterator {
friend class Vector;
protected:
size_t pos = 0;
const Vector<T>& vector;
public:
VectorIterator(const Vector<T>& newVector) : vector(newVector){};
VectorIterator(const VectorIterator& it) : vector(it.vector) { pos = it.pos; };
VectorIterator& operator++() {
pos++;
return *this;
}
VectorIterator& operator++(int) {
auto it = *this;
pos++;
return it;
}
VectorIterator& operator=(const VectorIterator& other) {
VectorIterator(other.vector);
pos = other.pos;
return *this;
}
__attribute__(( always_inline )) inline T& operator*() const { return vector.data[pos]; }
__attribute__(( always_inline )) inline T* operator->() const { return &vector.data[pos]; }
__attribute__(( always_inline )) inline friend bool operator==(const VectorIterator& l, const VectorIterator& r) {
return l.pos == r.pos;
}
__attribute__(( always_inline )) inline friend bool operator!=(const VectorIterator& l, const VectorIterator& r) {
return l.pos != r.pos;
}
};
private:
T* data = nullptr;
size_t count = 0;
size_t capacity = 0;
lock_t lock = 0;
public:
Vector() = default;
Vector(const Vector<T>& x) {
EnsureCapacity(x.get_length());
for (unsigned i = 0; i < x.get_length(); i++) {
data[i] = x.data[i];
}
}
template <typename... D> Vector(D... data) { (add_back(data), ...); }
__attribute__(( always_inline )) inline T& at(size_t pos) {
(void)((pos < count) || (KernelAssertionFailed("pos < count", "../Kernel/include/Vector.h", 74), 0));
return data[pos];
}
__attribute__(( always_inline )) inline const T& at(size_t pos) const {
(void)((pos < count) || (KernelAssertionFailed("pos < count", "../Kernel/include/Vector.h", 79), 0));
return data[pos];
}
__attribute__(( always_inline )) inline const T& get_at(size_t pos) const { return at(pos); }
__attribute__(( always_inline )) inline T& operator[](size_t pos) { return at(pos); }
__attribute__(( always_inline )) inline const T& operator[](size_t pos) const { return at(pos); }
__attribute__(( always_inline )) inline size_t size() const { return count; }
__attribute__(( always_inline )) inline size_t get_length() const { return count; }
void erase(unsigned pos) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 94), 0)); } });
EraseUnlocked(pos);
({ __sync_lock_release(&lock); });;
}
void reserve(size_t allocatedSize) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 102), 0)); } });
EnsureCapacity(allocatedSize);
({ __sync_lock_release(&lock); });;
}
void resize(size_t newSize) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 110), 0)); } });
EnsureCapacity(newSize);
size_t oldCount = count;
count = newSize;
if (count > oldCount) {
for (unsigned i = oldCount; i < count; i++) {
new (&data[i]) T();
}
} else if (count < oldCount) {
if constexpr (!TTraits<T>::is_trivial()) {
for (unsigned i = count; i < oldCount; i++) {
data[i].~T();
}
}
}
({ __sync_lock_release(&lock); });;
}
T& add_back(const T& val) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 132), 0)); } });
EnsureCapacity(count + 1);
T& ref = data[count];
count++;
new (&ref) T(val);
({ __sync_lock_release(&lock); });;
return ref;
}
T& add_back(T&& val) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 146), 0)); } });
EnsureCapacity(count + 1);
T& ref = data[count];
count++;
new (&ref) T(static_cast<T&&>(val));
({ __sync_lock_release(&lock); });;
return ref;
}
T& pop_back() {
(void)((count) || (KernelAssertionFailed("count", "../Kernel/include/Vector.h", 160), 0));
return data[--count];
}
__attribute__(( always_inline )) inline T* Data() { return data; }
void remove(const T& val) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 168), 0)); } });
for (unsigned i = 0; i < count; i++) {
if (data[i] == val) {
EraseUnlocked(i);
return;
}
}
({ __sync_lock_release(&lock); });;
}
~Vector() {
if (data) {
kfree(data);
}
data = nullptr;
}
VectorIterator begin() const {
VectorIterator it = VectorIterator(*this);
it.pos = 0;
return it;
}
VectorIterator end() const {
VectorIterator it = VectorIterator(*this);
it.pos = count;
return it;
}
void clear() {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Vector.h", 204), 0)); } });
if (data) {
kfree(data);
}
count = capacity = 0;
data = nullptr;
({ __sync_lock_release(&lock); });;
}
private:
__attribute__(( always_inline )) inline void EnsureCapacity(unsigned size) {
if (size >= capacity) {
size_t newCapacity = capacity + (size << 1) + 1;
if (data) {
T* oldData = data;
data = reinterpret_cast<T*>(kmalloc(newCapacity * sizeof(T)));
if constexpr (TTraits<T>::is_trivial()) {
memcpy(data, oldData, capacity * sizeof(T));
memset(data + capacity, 0, sizeof(T) * (size - capacity));
} else {
for (unsigned i = 0; i < count && i < capacity; i++) {
new (&data[i]) T(std::move(oldData[i]));
oldData[i].~T();
}
for (unsigned i = capacity; i < size; i++) {
new (&data[i]) T();
}
}
kfree(oldData);
} else {
data = reinterpret_cast<T*>(kmalloc(newCapacity * sizeof(T)));
}
capacity = newCapacity;
}
}
__attribute__(( always_inline )) inline void EraseUnlocked(unsigned pos) {
(void)((pos < count) || (KernelAssertionFailed("pos < count", "../Kernel/include/Vector.h", 247), 0));
if constexpr (TTraits<T>::is_trivial()) {
memcpy(&data[pos], &data[pos + 1], (count - pos - 1) * sizeof(T));
} else {
for (unsigned i = pos; i < count - 1; i++) {
data[i] = std::move(data[i + 1]);
}
}
count--;
}
};
# 11 "../Kernel/include/String.h" 2
template <typename T> class BasicString {
private:
const unsigned c_bufferRound = 32;
static_assert(TTraits<T>::is_trivial());
public:
BasicString() {
m_buffer = nullptr;
m_bufferSize = 0;
m_len = 0;
(void)((Empty()) || (KernelAssertionFailed("Empty()", "../Kernel/include/String.h", 23), 0));
}
BasicString(const T* data) {
m_buffer = nullptr;
CopyFromNullTerminatedBuffer(data);
}
BasicString(const T* data, size_t len) {
m_buffer = nullptr;
CopyFromBuffer(data, len);
}
BasicString(const BasicString& other) {
Resize(other.m_len);
memcpy(m_buffer, other.m_buffer, m_len * sizeof(T));
m_buffer[m_len] = 0;
}
BasicString(BasicString&& other) {
ScopedSpinLock acq(other.m_lock);
m_len = other.m_len;
m_bufferSize = other.m_bufferSize;
m_buffer = other.m_buffer;
other.m_len = 0;
other.m_buffer = 0;
other.m_bufferSize = 0;
}
~BasicString() {
ScopedSpinLock acq(m_lock);
if (m_buffer) {
delete[] m_buffer;
m_buffer = nullptr;
}
m_len = 0;
m_bufferSize = 0;
}
BasicString& operator=(const BasicString& other) {
ScopedSpinLock acq(m_lock);
Resize(other.m_len);
memcpy(m_buffer, other.m_buffer, m_len * sizeof(T));
m_buffer[m_len] = 0;
return *this;
}
BasicString& operator=(BasicString&& other) {
ScopedSpinLock acq(m_lock);
ScopedSpinLock acqOther(other.m_lock);
m_len = other.m_len;
m_bufferSize = other.m_bufferSize;
m_buffer = other.m_buffer;
other.m_len = 0;
other.m_buffer = 0;
return *this;
}
BasicString& operator+=(const BasicString& other) {
ScopedSpinLock acq(m_lock);
unsigned oldLen = m_len;
Resize(oldLen + other.m_len);
memcpy((m_buffer + oldLen), other.m_buffer, other.m_len * sizeof(T));
return *this;
}
BasicString& operator+=(const T* data) {
ScopedSpinLock acq(m_lock);
unsigned oldLen = m_len;
unsigned dataLen = 0;
while (data[dataLen])
dataLen++;
Resize(oldLen + dataLen);
memcpy((m_buffer + oldLen), data, dataLen);
return *this;
}
T& operator[](unsigned pos) { return m_buffer[pos]; }
const T& operator[](unsigned pos) const { return m_buffer[pos]; }
Vector<BasicString<T>> Split(T delim) const {
Vector<BasicString<T>> result;
int start = 0;
unsigned i = 0;
for (; i < m_len; i++) {
if (m_buffer[i] == delim) {
if ((i - start) > 0) {
result.add_back(BasicString<T>((m_buffer + start), (i - start)));
}
start = i + 1;
}
}
if ((i - start) > 0) {
result.add_back(BasicString<T>((m_buffer + start), (i - start)));
}
return result;
}
int Compare(const T* data) const {
const T* s1 = m_buffer;
while (*s1 == *data) {
if (!(*s1)) {
return 0;
}
s1++;
data++;
}
return (*s1) - (*data);
};
__attribute__(( always_inline )) inline int Compare(const BasicString& other) const { return Compare(other.Data()); };
__attribute__(( always_inline )) inline unsigned Length() const { return m_len; }
__attribute__(( always_inline )) inline const T* Data() const { return m_buffer; }
__attribute__(( always_inline )) inline const T* c_str() const { (void)((m_buffer) || (KernelAssertionFailed("m_buffer", "../Kernel/include/String.h", 167), 0)); return m_buffer; }
__attribute__(( always_inline )) inline bool Empty() const { return (!m_buffer) || (m_len == 0); }
protected:
lock_t m_lock = 0;
unsigned m_len = 0;
unsigned m_bufferSize = 0;
T* m_buffer = nullptr;
__attribute__(( always_inline )) inline void CopyFromNullTerminatedBuffer(const T* data) {
unsigned len = 0;
while (data[len])
len++;
CopyFromBuffer(data, len);
}
__attribute__(( always_inline )) inline void CopyFromBuffer(const T* data, size_t len) {
Resize(len);
memcpy(m_buffer, data, m_len * sizeof(T));
m_buffer[m_len] = 0;
}
__attribute__(( always_inline )) inline void Resize(unsigned newLen) {
if (m_buffer && newLen < m_bufferSize) {
m_len = newLen;
m_buffer[m_len] = 0;
return;
}
m_bufferSize = (newLen + 1 + c_bufferRound - 1) & ~(c_bufferRound - 1);
T* newBuffer = new T[m_bufferSize];
if (m_buffer) {
memcpy(newBuffer, m_buffer, m_len * sizeof(T));
delete[] m_buffer;
}
m_buffer = newBuffer;
m_len = newLen;
m_buffer[m_len] = 0;
}
};
template <typename T> BasicString<T> operator+(const BasicString<T>& l, const T* r) {
BasicString<T> str(l);
str += r;
return str;
}
template <typename T, typename U> BasicString<T> operator+(const BasicString<T>& l, const U& r) {
BasicString<T> str(l);
str += r;
return str;
}
using String = BasicString<char>;
__attribute__(( always_inline )) inline String to_string(int num, int base = 10) {
char buf[128];
buf[127] = 0;
int i = 127;
if (num == 0) {
buf[--i] = '0';
}
while (num != 0 && i) {
int rem = num % base;
buf[--i] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
return String(buf + i);
}
__attribute__(( always_inline )) inline String to_string(long num, int base = 10) {
char buf[128];
buf[127] = 0;
int i = 127;
if (num == 0) {
buf[--i] = '0';
}
while (num != 0 && i) {
int rem = num % base;
buf[--i] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
return String(buf + i);
}
__attribute__(( always_inline )) inline String to_string(unsigned num, int base = 10) {
char buf[128];
buf[127] = 0;
int i = 127;
if (num == 0) {
buf[--i] = '0';
}
while (num != 0 && i) {
int rem = num % base;
buf[--i] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
num = num / base;
}
return String(buf + i);
}
String to_string(const struct IPv4Address& addr);
String to_string(const struct MACAddress& addr);
# 10 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "../Kernel/include/Arch/x86_64/Types.h" 1
typedef long long ssize_t;
# 11 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/abi.h" 1 3
# 13 "../Kernel/include/Fs/Filesystem.h" 2
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/abi-bits/fcntl.h" 1 3
# 14 "../Kernel/include/Fs/Filesystem.h" 2
# 95 "../Kernel/include/Fs/Filesystem.h"
typedef int64_t ino_t;
typedef uint64_t dev_t;
typedef int64_t off_t;
typedef int32_t mode_t;
typedef int32_t nlink_t;
typedef int64_t volume_id_t;
typedef struct {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
uid_t st_uid;
uid_t st_gid;
dev_t st_rdev;
off_t st_size;
int64_t st_blksize;
int64_t st_blocks;
} stat_t;
class FsNode;
struct UNIXFileDescriptor;
struct pollfd {
int fd;
short events;
short revents;
};
typedef struct {
char fds_bits[128];
} fd_set_t;
static inline void FD_CLR(int fd, fd_set_t* fds) {
(void)((fd < 1024) || (KernelAssertionFailed("fd < FD_SETSIZE", "../Kernel/include/Fs/Filesystem.h", 129), 0));
fds->fds_bits[fd / 8] &= ~(1 << (fd % 8));
}
static inline int FD_ISSET(int fd, fd_set_t* fds) {
(void)((fd < 1024) || (KernelAssertionFailed("fd < FD_SETSIZE", "../Kernel/include/Fs/Filesystem.h", 134), 0));
return fds->fds_bits[fd / 8] & (1 << (fd % 8));
}
static inline void FD_SET(int fd, fd_set_t* fds) {
(void)((fd < 1024) || (KernelAssertionFailed("fd < FD_SETSIZE", "../Kernel/include/Fs/Filesystem.h", 139), 0));
fds->fds_bits[fd / 8] |= 1 << (fd % 8);
}
class FilesystemWatcher;
class DirectoryEntry;
class FsNode {
friend class FilesystemBlocker;
public:
lock_t blockedLock = 0;
FastList<class FilesystemBlocker*> blocked;
uint32_t flags = 0;
uint32_t pmask = 0;
uid_t uid = 0;
ino_t inode = 0;
size_t size = 0;
int nlink = 0;
unsigned handleCount = 0;
volume_id_t volumeID;
int error = 0;
virtual ~FsNode();
# 176 "../Kernel/include/Fs/Filesystem.h"
virtual ssize_t Read(size_t off, size_t size, uint8_t* buffer);
# 188 "../Kernel/include/Fs/Filesystem.h"
virtual ssize_t Write(size_t off, size_t size, uint8_t* buffer);
virtual UNIXFileDescriptor* Open(size_t flags);
virtual void Close();
virtual int ReadDir(DirectoryEntry*, uint32_t);
virtual FsNode* FindDir(const char* name);
virtual int Create(DirectoryEntry* ent, uint32_t mode);
virtual int CreateDirectory(DirectoryEntry* ent, uint32_t mode);
virtual ssize_t ReadLink(char* pathBuffer, size_t bufSize);
virtual int Link(FsNode*, DirectoryEntry*);
virtual int Unlink(DirectoryEntry*, bool unlinkDirectories = false);
virtual int Truncate(off_t length);
virtual int Ioctl(uint64_t cmd, uint64_t arg);
virtual void Sync();
virtual bool CanRead() { return true; }
virtual bool CanWrite() { return true; }
virtual void Watch(FilesystemWatcher& watcher, int events);
virtual void Unwatch(FilesystemWatcher& watcher);
virtual inline bool IsFile() { return (flags & 0xF000) == 0x8000; }
virtual inline bool IsDirectory() { return (flags & 0xF000) == 0x4000; }
virtual inline bool IsBlockDevice() { return (flags & 0xF000) == 0x6000; }
virtual inline bool IsSymlink() { return (flags & 0xF000) == 0xA000; }
virtual inline bool IsCharDevice() { return (flags & 0xF000) == 0x2000; }
virtual inline bool IsSocket() { return (flags & 0xF000) == 0xC000; }
virtual inline bool IsEPoll() const { return false; }
void UnblockAll();
FsNode* link;
FsNode* parent;
FilesystemLock nodeLock;
};
typedef struct UNIXFileDescriptor {
FsNode* node = nullptr;
off_t pos = 0;
mode_t mode = 0;
~UNIXFileDescriptor();
} fs_fd_t;
class DirectoryEntry {
public:
char name[255];
FsNode* node = nullptr;
uint32_t inode = 0;
DirectoryEntry* parent = nullptr;
mode_t flags = 0;
DirectoryEntry(FsNode* node, const char* name);
DirectoryEntry() {}
static mode_t FileToDirentFlags(mode_t flags) {
switch (flags & 0xF000) {
case 0x8000:
flags = 8;
break;
case 0x4000:
flags = 4;
break;
case 0x2000:
flags = 2;
break;
case 0x6000:
flags = 6;
break;
case 0xC000:
flags = 12;
break;
case 0xA000:
flags = 10;
break;
default:
(void)((!"Invalid file flags!") || (KernelAssertionFailed("!\"Invalid file flags!\"", "../Kernel/include/Fs/Filesystem.h", 273), 0));
}
return flags;
}
};
class FilesystemWatcher : public Semaphore {
List<UNIXFileDescriptor*> watching;
public:
FilesystemWatcher() : Semaphore(0) {}
inline void WatchNode(FsNode* node, int events) {
UNIXFileDescriptor* desc = node->Open(0);
(void)((desc) || (KernelAssertionFailed("desc", "../Kernel/include/Fs/Filesystem.h", 290), 0));
desc->node->Watch(*this, events);
watching.add_back(desc);
}
~FilesystemWatcher() {
for (auto& fd : watching) {
fd->node->Unwatch(*this);
delete fd;
}
}
};
class FilesystemBlocker : public ThreadBlocker {
friend FsNode;
friend FastList<FilesystemBlocker*>;
public:
enum BlockType {
BlockRead,
BlockWrite,
};
protected:
FsNode* node = nullptr;
FilesystemBlocker* next;
FilesystemBlocker* prev;
int blockType = BlockType::BlockRead;
size_t requestedLength = 1;
public:
FilesystemBlocker(FsNode* _node) : node(_node) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Fs/Filesystem.h", 327), 0)); } });
({ unsigned i = 0; while (__sync_lock_test_and_set(&node->blockedLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Fs/Filesystem.h", 329), 0)); } });
node->blocked.add_back(this);
({ __sync_lock_release(&node->blockedLock); });;
({ __sync_lock_release(&lock); });;
}
FilesystemBlocker(FsNode* _node, size_t len) : node(_node), requestedLength(len) {
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Fs/Filesystem.h", 337), 0)); } });
({ unsigned i = 0; while (__sync_lock_test_and_set(&node->blockedLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Fs/Filesystem.h", 339), 0)); } });
node->blocked.add_back(this);
({ __sync_lock_release(&node->blockedLock); });;
({ __sync_lock_release(&lock); });;
}
void Interrupt();
inline void Unblock() {
shouldBlock = false;
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Fs/Filesystem.h", 351), 0)); } });
if (node && !removed) {
node->blocked.remove(this);
removed = true;
}
node = nullptr;
if (thread) {
thread->Unblock();
}
({ __sync_lock_release(&lock); });;
}
inline size_t RequestedLength() { return requestedLength; }
~FilesystemBlocker();
};
typedef struct fs_dirent {
uint32_t inode;
uint32_t type;
char name[255];
} fs_dirent_t;
namespace fs {
class FsVolume;
class FsDriver {
public:
virtual ~FsDriver() = default;
virtual FsVolume* Mount(FsNode* device, const char* name) = 0;
virtual FsVolume* Unmount(FsVolume* volume) = 0;
virtual int Identify(FsNode* device) = 0;
virtual const char* ID() const = 0;
};
extern List<FsDriver*> drivers;
void Initialize();
FsNode* GetRoot();
# 405 "../Kernel/include/Fs/Filesystem.h"
void RegisterDriver(FsDriver* driver);
void UnregisterDriver(FsDriver* driver);
FsDriver* IdentifyFilesystem(FsNode* node);
# 418 "../Kernel/include/Fs/Filesystem.h"
FsNode* FollowLink(FsNode* link, FsNode* workingDir);
# 428 "../Kernel/include/Fs/Filesystem.h"
FsNode* ResolvePath(const String& path, const char* workingDir = nullptr, bool followSymlinks = true);
# 438 "../Kernel/include/Fs/Filesystem.h"
FsNode* ResolvePath(const String& path, FsNode* workingDir, bool followSymlinks = true);
# 448 "../Kernel/include/Fs/Filesystem.h"
FsNode* ResolveParent(const char* path, const char* workingDir = nullptr);
char* CanonicalizePath(const char* path, char* workingDir);
char* BaseName(const char* path);
# 464 "../Kernel/include/Fs/Filesystem.h"
ssize_t Read(FsNode* node, size_t offset, size_t size, void* buffer);
# 478 "../Kernel/include/Fs/Filesystem.h"
ssize_t Write(FsNode* node, size_t offset, size_t size, void* buffer);
UNIXFileDescriptor* Open(FsNode* node, uint32_t flags = 0);
void Close(FsNode* node);
void Close(UNIXFileDescriptor* handle);
int ReadDir(FsNode* node, DirectoryEntry* dirent, uint32_t index);
FsNode* FindDir(FsNode* node, const char* name);
ssize_t Read(const FancyRefPtr<UNIXFileDescriptor>& handle, size_t size, uint8_t* buffer);
ssize_t Write(const FancyRefPtr<UNIXFileDescriptor>& handle, size_t size, uint8_t* buffer);
int ReadDir(const FancyRefPtr<UNIXFileDescriptor>& handle, DirectoryEntry* dirent, uint32_t index);
FsNode* FindDir(const FancyRefPtr<UNIXFileDescriptor>& handle, const char* name);
int Link(FsNode*, FsNode*, DirectoryEntry*);
int Unlink(FsNode*, DirectoryEntry*, bool unlinkDirectories = false);
int Ioctl(const FancyRefPtr<UNIXFileDescriptor>& handle, uint64_t cmd, uint64_t arg);
int Rename(FsNode* olddir, char* oldpath, FsNode* newdir, char* newpath);
}
__attribute__(( always_inline )) inline UNIXFileDescriptor::~UNIXFileDescriptor() { fs::Close(this); }
# 10 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/Hash.h" 1
static inline unsigned HashU(unsigned value){
unsigned hash = value;
hash = ((hash >> 5) ^ hash) * 47499631;
hash = ((hash >> 5) ^ hash) * 47499631;
hash = (hash >> 5) ^ hash;
return hash;
}
template<typename T>
unsigned Hash(const T& value);
template<typename K, typename T>
class HashMap{
public:
class KeyValuePair{
friend class HashMap;
friend class HashMapIterator;
protected:
T value;
K key;
KeyValuePair(K key, T value) : value(value), key(key){}
};
class HashMapIterator {
friend class HashMap<K, T>;
protected:
HashMap<K, T>* map;
unsigned bucketIndex = 0;
List<KeyValuePair>* bucket;
ListIterator<KeyValuePair> listIt;
public:
HashMapIterator() = default;
HashMapIterator(const HashMapIterator&) = default;
HashMapIterator& operator++(){
(void)((listIt != bucket->end()) || (KernelAssertionFailed("listIt != bucket->end()", "../Kernel/include/Hash.h", 47), 0));
listIt++;
if(listIt == bucket->end() && bucketIndex < map->bucketCount - 1){
bucket = map->buckets[++bucketIndex];
listIt = bucket->begin();
}
return *this;
}
HashMapIterator& operator++(int){
ListIterator<KeyValuePair> v = ListIterator<KeyValuePair>(*this);
(void)((listIt != bucket->end()) || (KernelAssertionFailed("listIt != bucket->end()", "../Kernel/include/Hash.h", 62), 0));
listIt++;
if(listIt == bucket->end() && bucketIndex < map->bucketCount - 1){
bucket = map->buckets[++bucketIndex];
listIt = bucket->begin();
}
return v;
}
T& operator*(){
return listIt.operator*().value;
}
T* operator->(){
return &listIt.operator->()->value;
}
friend bool operator==(const HashMapIterator& l, const HashMapIterator& r){
if(l.listIt == r.listIt){
return true;
} else {
return false;
}
}
friend bool operator!=(const HashMapIterator& l, const HashMapIterator& r){
if(l.listIt != r.listIt){
return true;
} else {
return false;
}
}
};
HashMap(){
buckets = new List<KeyValuePair>[bucketCount];
lock = 0;
}
HashMap(unsigned bCount){
bucketCount = bCount;
buckets = new List<KeyValuePair>[bucketCount];
lock = 0;
}
void insert(K key, const T& value){
auto& bucket = buckets[Hash(key) % bucketCount];
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Hash.h", 114), 0)); } });
for(KeyValuePair& v : bucket){
if(v.key == key){
v.value = value;
itemCount++;
({ __sync_lock_release(&lock); });;
return;
}
}
bucket.add_back(KeyValuePair(key, value));
({ __sync_lock_release(&lock); });;
}
T remove(K key){
auto& bucket = buckets[Hash(key) % bucketCount];
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Hash.h", 133), 0)); } });
for(unsigned i = 0; i < bucket.get_length(); i++){
if(bucket[i].key == key){
auto pair = bucket.remove_at(i);
itemCount--;
({ __sync_lock_release(&lock); });;
return pair.value;
}
}
({ __sync_lock_release(&lock); });;
return T();
}
void removeValue(T value){
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Hash.h", 150), 0)); } });
for(unsigned b = 0; b < bucketCount; b++){
auto& bucket = buckets[b];
for(unsigned i = 0; i < bucket.get_length(); i++){
if(bucket[i].value == value){
bucket.remove_at(i);
itemCount--;
({ __sync_lock_release(&lock); });;
return;
}
}
}
({ __sync_lock_release(&lock); });;
return;
}
int get(const K& key, T& value){
auto& bucket = buckets[Hash(key) % bucketCount];
({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Hash.h", 173), 0)); } });
for(KeyValuePair& val : bucket){
if(val.key == key){
({ __sync_lock_release(&lock); });;
value = val.value;
return 1;
}
}
({ __sync_lock_release(&lock); });;
return 0;
}
int find(K key){
auto& bucket = buckets[Hash(key) % bucketCount];
for(KeyValuePair& val : bucket){
if(val.key == key){
return 1;
}
}
return 0;
}
unsigned get_length(){
return itemCount;
}
HashMapIterator begin(){
HashMapIterator it;
it.bucket = buckets[0];
it.bucketIndex = 0;
it.map = this;
it.listIt = it.bucket->begin();
return it;
}
HashMapIterator end(){
HashMapIterator it;
it.bucket = buckets[bucketCount - 1];
it.bucketIndex = bucketCount - 1;
it.map = this;
it.listIt = it.bucket->end();
return it;
}
~HashMap(){
delete[](buckets);
}
private:
List<KeyValuePair>* buckets;
unsigned bucketCount = 512;
unsigned itemCount = 0;
lock_t lock = 0;
};
# 11 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/MM/AddressSpace.h" 1
# 1 "../Kernel/include/Pair.h" 1
template <typename T1, typename T2>
class Pair{
public:
T1 item1;
T2 item2;
Pair(const T1 one, const T2 two){
item1 = one;
item2 = two;
}
Pair(){
}
};
# 6 "../Kernel/include/MM/AddressSpace.h" 2
# 1 "../Kernel/include/MM/VMObject.h" 1
# 1 "/home/kai/.local/share/lemon/sysroot/system/include/c++/v1/stddef.h" 1 3
# 5 "../Kernel/include/MM/VMObject.h" 2
class VMObject {
friend class AddressSpace;
friend void ::Memory::PageFaultHandler(void*, struct RegisterContext*);
public:
VMObject(size_t size, bool anonymous, bool shared);
virtual ~VMObject() = default;
virtual int Hit(uintptr_t base, uintptr_t offset, PageMap* pMap);
virtual void MapAllocatedBlocks(uintptr_t base, PageMap* pMap) = 0;
virtual VMObject* Clone() = 0;
virtual VMObject* Split(uintptr_t offset);
__attribute__(( always_inline )) inline size_t Size() const { return size; }
virtual size_t UsedPhysicalMemory() const { return 0; }
__attribute__(( always_inline )) inline bool IsAnonymous() const { return anonymous; }
__attribute__(( always_inline )) inline bool IsShared() const { return shared; }
__attribute__(( always_inline )) inline bool IsCopyOnWrite() const { return copyOnWrite; }
__attribute__(( always_inline )) inline bool IsReclaimable() const { return reclaimable; }
__attribute__(( always_inline )) inline virtual bool CanMunmap() const { return false; }
__attribute__(( always_inline )) inline size_t ReferenceCount() const { return refCount; }
protected:
size_t size;
size_t refCount = 0;
bool anonymous : 1 = true;
bool shared : 1 = false;
bool copyOnWrite : 1 = false;
bool reclaimable : 1 = false;
};
class PhysicalVMObject : public VMObject {
public:
PhysicalVMObject(size_t size, bool anonymous, bool shared);
virtual ~PhysicalVMObject();
int Hit(uintptr_t base, uintptr_t offset, PageMap* pMap) final;
void ForceAllocate();
virtual void MapAllocatedBlocks(uintptr_t base, PageMap* pMap);
virtual VMObject* Clone();
virtual size_t UsedPhysicalMemory() const;
protected:
uint32_t* physicalBlocks = nullptr;
};
class ProcessImageVMObject final : public PhysicalVMObject {
public:
ProcessImageVMObject(uintptr_t base, size_t size, bool write);
void MapAllocatedBlocks(uintptr_t base, PageMap* pMap);
protected:
bool write : 1 = true;
uintptr_t base;
};
class AnonymousVMObject : public PhysicalVMObject{
AnonymousVMObject(size_t size);
VMObject* Split(uintptr_t offset) override;
__attribute__(( always_inline )) inline bool CanMunmap() const override { return true; }
};
struct MappedRegion {
uintptr_t base;
size_t size;
FancyRefPtr<VMObject> vmObject;
ReadWriteLock lock;
__attribute__(( always_inline )) inline uintptr_t Base() const { return base; }
__attribute__(( always_inline )) inline uintptr_t Size() const { return size; }
__attribute__(( always_inline )) inline uintptr_t End() const { return base + size; }
MappedRegion() = delete;
__attribute__(( always_inline )) inline MappedRegion(uintptr_t base, size_t size)
: base(base), size(size), vmObject(nullptr) {
}
__attribute__(( always_inline )) inline MappedRegion(uintptr_t base, size_t size, FancyRefPtr<VMObject> vmObject)
: base(base), size(size), vmObject(vmObject) {
}
__attribute__(( always_inline )) inline MappedRegion(const MappedRegion& region){
base = region.base;
size = region.size;
vmObject = region.vmObject;
lock = ReadWriteLock();
}
__attribute__(( always_inline )) inline MappedRegion& operator=(const MappedRegion& region){
base = region.base;
size = region.size;
vmObject = region.vmObject;
lock = ReadWriteLock();
return *this;
}
__attribute__(( always_inline )) inline MappedRegion(MappedRegion&& region){
base = region.base;
size = region.size;
vmObject = std::move(region.vmObject);
region.base = region.size = 0;
}
__attribute__(( always_inline )) inline MappedRegion& operator=(MappedRegion&& region){
base = region.base;
size = region.size;
vmObject = std::move(region.vmObject);
region.base = region.size = 0;
return *this;
}
};
# 10 "../Kernel/include/MM/AddressSpace.h" 2
class AddressSpace final {
public:
AddressSpace(PageMap* pm);
~AddressSpace();
__attribute__(( always_inline )) inline AddressSpace* Kernel();
# 30 "../Kernel/include/MM/AddressSpace.h"
MappedRegion* AddressToRegionReadLock(uintptr_t address);
# 41 "../Kernel/include/MM/AddressSpace.h"
MappedRegion* AddressToRegionWriteLock(uintptr_t address);
# 51 "../Kernel/include/MM/AddressSpace.h"
bool RangeInRegion(uintptr_t base, size_t size);
# 60 "../Kernel/include/MM/AddressSpace.h"
long UnmapRegion(MappedRegion* region);
MappedRegion* MapVMO(FancyRefPtr<VMObject> obj, uintptr_t base, bool fixed);
MappedRegion* AllocateAnonymousVMObject(size_t size, uintptr_t base, bool fixed);
AddressSpace* Fork();
long UnmapMemory(uintptr_t base, size_t size);
void UnmapAll();
size_t UsedPhysicalMemory() const;
void DumpRegions();
__attribute__((always_inline)) inline PageMap* GetPageMap() { return m_pageMap; }
protected:
MappedRegion* FindAvailableRegion(size_t size);
MappedRegion* AllocateRegionAt(uintptr_t base, size_t size);
__attribute__(( always_inline )) inline bool IsKernel() const { return this == m_kernel; }
AddressSpace* m_kernel;
uintptr_t m_startRegion = 0;
uintptr_t m_endRegion = 0xFFFFFFFF80000000ULL;
lock_t m_lock = 0;
PageMap* m_pageMap = nullptr;
List<MappedRegion> m_regions;
AddressSpace* m_parent = nullptr;
};
# 13 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/Objects/Handle.h" 1
# 1 "../Kernel/include/Objects/KObject.h" 1
# 13 "../Kernel/include/Objects/KObject.h"
typedef long kobject_id_t;
class KernelObjectWatcher;
class KernelObject {
protected:
int64_t oid = -1;
static int64_t nextOID;
public:
KernelObject() { oid = nextOID++; }
inline int64_t ObjectID() { return oid; }
virtual kobject_id_t InstanceTypeID() const = 0;
inline bool IsType(kobject_id_t id) { return InstanceTypeID() == id; }
virtual void Watch(KernelObjectWatcher& watcher, int events);
virtual void Unwatch(KernelObjectWatcher& watcher);
virtual void Destroy() = 0;
virtual ~KernelObject() = default;
};
class KernelObjectWatcher : public Semaphore {
List<FancyRefPtr<KernelObject>> watching;
public:
KernelObjectWatcher() : Semaphore(0) {}
inline void WatchObject(FancyRefPtr<KernelObject> node, int events) {
node->Watch(*this, events);
watching.add_back(node);
}
~KernelObjectWatcher() {
for (auto& node : watching) {
node->Unwatch(*this);
}
watching.clear();
}
};
# 4 "../Kernel/include/Objects/Handle.h" 2
typedef long long handle_id_t;
struct Handle {
handle_id_t id = 0;
FancyRefPtr<KernelObject> ko;
__attribute__(( always_inline )) inline operator bool(){
return id && ko.get();
}
};
# 14 "../Kernel/include/Objects/Process.h" 2
# 1 "../Kernel/include/TimerEvent.h" 1
struct RegisterContext;
namespace Timer{
using TimerCallback = void(*)(void*);
void Handler(void*, RegisterContext* r);
class TimerEvent final {
friend void Timer::Handler(void*, RegisterContext* r);
friend class ::FastList<TimerEvent*>;
protected:
long ticks = 0;
bool dispatched = false;
lock_t lock = 0;
TimerEvent* next = nullptr;
TimerEvent* prev = nullptr;
TimerCallback callback;
void* data = nullptr;
void Dispatch();
public:
TimerEvent(long _us, TimerCallback _callback, void* data);
~TimerEvent();
inline long GetTicks() const { return ticks; }
__attribute__((always_inline)) inline void Lock() { ({ unsigned i = 0; while (__sync_lock_test_and_set(&lock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/TimerEvent.h", 34), 0)); } }); }
__attribute__((always_inline)) inline void Unlock() { ({ __sync_lock_release(&lock); });; }
};
}
# 19 "../Kernel/include/Objects/Process.h" 2
class Process : public KernelObject {
friend struct Thread;
friend void KernelProcess();
friend long SysExecve(RegisterContext* r);
public:
enum {
Process_Running = 0,
Process_Dying = 1,
Process_Dead = 3,
};
static FancyRefPtr<Process> CreateIdleProcess(const char* name);
static FancyRefPtr<Process> CreateKernelProcess(void* entry, const char* name, Process* parent);
static FancyRefPtr<Process> CreateELFProcess(void* elf, const Vector<String>& argv, const Vector<String>& envp,
const char* execPath, Process* parent);
__attribute__(( always_inline )) inline static Process* Current() {
CPU* cpu = GetCPULocal();
Process* ret = nullptr;
if (cpu->currentThread)
ret = cpu->currentThread->parent;
return ret;
}
~Process();
void Destroy() override;
# 68 "../Kernel/include/Objects/Process.h"
void Die();
void Start();
kobject_id_t InstanceTypeID() const override { return 5; }
# 85 "../Kernel/include/Objects/Process.h"
void Watch(KernelObjectWatcher& watcher, int events) override;
void Unwatch(KernelObjectWatcher& watcher) override;
# 96 "../Kernel/include/Objects/Process.h"
FancyRefPtr<Process> Fork();
# 107 "../Kernel/include/Objects/Process.h"
uintptr_t LoadELF(uintptr_t* stackPointer, elf_info_t elfInfo, const Vector<String>& argv,
const Vector<String>& envp, const char* execPath);
__attribute__(( always_inline )) inline pid_t PID() const { return m_pid; }
__attribute__(( always_inline )) inline int State() const { return m_state; }
__attribute__(( always_inline )) inline int IsDead() const { return m_state == Process_Dead; }
__attribute__(( always_inline )) inline int IsCPUIdleProcess() const { return m_isIdleProcess; }
__attribute__(( always_inline )) inline const Process* Parent() const { return m_parent; }
# 138 "../Kernel/include/Objects/Process.h"
__attribute__(( always_inline )) inline FancyRefPtr<Thread> GetMainThread() { return m_mainThread; }
# 149 "../Kernel/include/Objects/Process.h"
__attribute__(( always_inline )) inline FancyRefPtr<Thread> GetThreadFromTID(pid_t tid) {
ScopedSpinLock acq(m_processLock);
return GetThreadFromTID_Unlocked(tid);
}
pid_t CreateChildThread(uintptr_t entry, uintptr_t stack, uint64_t cs, uint64_t ss);
const List<FancyRefPtr<Thread>>& Threads() { return m_threads; }
__attribute__(( always_inline )) inline PageMap* GetPageMap() { return addressSpace->GetPageMap(); }
int AllocateFileDescriptor(FancyRefPtr<UNIXFileDescriptor> fd);
__attribute__(( always_inline )) inline FancyRefPtr<UNIXFileDescriptor> GetFileDescriptor(int fd) {
ScopedSpinLock lockFds(m_fileDescriptorLock);
if (fd >= m_fileDescriptors.size()) {
return nullptr;
}
return m_fileDescriptors[fd];
}
# 188 "../Kernel/include/Objects/Process.h"
__attribute__(( always_inline )) inline int DestroyFileDescriptor(int fd) {
ScopedSpinLock lockFds(m_fileDescriptorLock);
if (fd >= m_fileDescriptors.size()) {
return 1008;
}
m_fileDescriptors[fd] = nullptr;
return 0;
}
# 206 "../Kernel/include/Objects/Process.h"
__attribute__(( always_inline )) inline int ReplaceFileDescriptor(int fd, FancyRefPtr<UNIXFileDescriptor> newFd) {
ScopedSpinLock lockFds(m_fileDescriptorLock);
(void)((fd < m_fileDescriptors.size()) || (KernelAssertionFailed("fd < m_fileDescriptors.size()", "../Kernel/include/Objects/Process.h", 208), 0));
m_fileDescriptors.at(fd) = newFd;
return 0;
}
__attribute__(( always_inline )) inline unsigned FileDescriptorCount() const { return m_fileDescriptors.size(); }
__attribute__(( always_inline )) inline Handle AllocateHandle(FancyRefPtr<KernelObject> ko) {
ScopedSpinLock lockHandles(m_handleLock);
Handle h;
h.ko = std::move(ko);
h.id = m_handles.get_length() + 1;
m_handles.add_back(h);
return h;
}
__attribute__(( always_inline )) inline Handle FindHandle(handle_id_t id) {
ScopedSpinLock lockFds(m_handleLock);
if (id < 1 || id > m_handles.size()) {
return {0, nullptr};
}
return m_handles[id - 1];
}
__attribute__(( always_inline )) inline int DestroyHandle(handle_id_t id) {
ScopedSpinLock lockFds(m_handleLock);
if (id > m_handles.size()) {
return 1008;
}
m_handles[id - 1] = {0, nullptr};
return 0;
}
__attribute__(( always_inline )) inline FancyRefPtr<UNIXFileDescriptor> stdin() { return m_fileDescriptors[0]; };
__attribute__(( always_inline )) inline FancyRefPtr<UNIXFileDescriptor> stdout() { return m_fileDescriptors[1]; };
__attribute__(( always_inline )) inline FancyRefPtr<UNIXFileDescriptor> stderr() { return m_fileDescriptors[2]; };
__attribute__(( always_inline )) inline void RegisterChildProcess(const FancyRefPtr<Process>& child) {
ScopedSpinLock lock(m_processLock);
m_children.add_back(child);
}
__attribute__(( always_inline )) inline FancyRefPtr<Process> FindChildByPID(pid_t pid) {
ScopedSpinLock lock(m_processLock);
for (auto& child : m_children) {
if (child->PID() == pid) {
return child;
}
}
return nullptr;
}
__attribute__(( always_inline )) inline FancyRefPtr<Process> RemoveDeadChild() {
ScopedSpinLock lock(m_processLock);
FancyRefPtr<Process> proc;
for (auto it = m_children.begin(); it != m_children.end(); it++) {
if ((*it)->State() == Process_Dead) {
proc = std::move(*it);
m_children.remove(it);
break;
}
}
if (proc.get()) {
ScopedSpinLock lockChild(proc->m_processLock);
proc->m_parent = nullptr;
return proc;
}
return nullptr;
}
__attribute__(( always_inline )) inline FancyRefPtr<Process> RemoveDeadChild(pid_t pid) {
ScopedSpinLock lock(m_processLock);
for (auto it = m_children.begin(); it != m_children.end(); it++) {
if ((*it)->PID() == pid) {
(void)(((*it)->IsDead()) || (KernelAssertionFailed("(*it)->IsDead()", "../Kernel/include/Objects/Process.h", 305), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&(*it)->m_processLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Objects/Process.h", 307), 0)); } });
FancyRefPtr<Process> proc = std::move(*it);
proc->m_parent = nullptr;
m_children.remove(it);
({ __sync_lock_release(&proc->m_processLock); });;
return proc;
}
}
(void)((!"Could not find process!") || (KernelAssertionFailed("!\"Could not find process!\"", "../Kernel/include/Objects/Process.h", 315), 0));
}
__attribute__(( always_inline )) inline int WaitForChildToDie(FancyRefPtr<Process>& ptr) {
auto child = RemoveDeadChild();
if (child.get()) {
ptr = std::move(child);
return 0;
}
retry:
({ unsigned i = 0; while (__sync_lock_test_and_set(&m_processLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/include/Objects/Process.h", 331), 0)); } });
if (!m_children.get_length()) {
({ __sync_lock_release(&m_processLock); });;
return -1012;
}
KernelObjectWatcher watcher;
for (auto& child : m_children) {
watcher.WatchObject(static_pointer_cast<KernelObject>(child), 0);
}
({ __sync_lock_release(&m_processLock); });;
bool wasInterrupted = watcher.Wait();
child = RemoveDeadChild();
if (child.get()) {
ptr = std::move(child);
return 0;
} else if (wasInterrupted) {
return -1025;
}
goto retry;
}
__attribute__(( always_inline )) inline void SetAlarm(unsigned int seconds) {
ScopedSpinLock lockProcess(m_processLock);
if (seconds == 0) {
m_alarmEvent = nullptr;
return;
}
m_alarmEvent = new Timer::TimerEvent(
seconds * 1000000,
[](void* thread) {
Thread* t = reinterpret_cast<Thread*>(thread);
t->Signal(14);
},
m_mainThread.get());
}
char name[255 + 1];
char workingDir[4096 + 1];
int32_t euid = 0;
int32_t uid = 0;
int32_t egid = 0;
int32_t gid = 0;
SignalHandler signalHandlers[34];
uint64_t usedMemoryBlocks = 0;
timeval creationTime;
uint64_t activeTicks = 0;
AddressSpace* addressSpace = nullptr;
HashMap<uintptr_t, List<FutexThreadBlocker*>*> futexWaitQueue = HashMap<uintptr_t, List<FutexThreadBlocker*>*>(8);
int exitCode = 0;
private:
Process(pid_t pid, const char* name, const char* workingDir, Process* parent);
FancyRefPtr<Thread> GetThreadFromTID_Unlocked(pid_t tid);
void MapSignalTrampoline();
lock_t m_processLock = 0;
lock_t m_watchingLock = 0;
lock_t m_fileDescriptorLock = 0;
lock_t m_handleLock = 0;
pid_t m_pid;
bool m_started = false;
MappedRegion* m_signalTrampoline = nullptr;
int m_state = Process_Running;
bool m_isIdleProcess = false;
int64_t m_nextThreadID = 1;
FancyRefPtr<Thread> m_mainThread;
List<FancyRefPtr<Thread>> m_threads;
List<FancyRefPtr<Process>> m_children;
# 436 "../Kernel/include/Objects/Process.h"
Vector<Handle> m_handles;
Vector<FancyRefPtr<UNIXFileDescriptor>> m_fileDescriptors;
List<KernelObjectWatcher*> m_watching;
FancyRefPtr<Timer::TimerEvent> m_alarmEvent = nullptr;
Process* m_parent = nullptr;
};
# 2 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Arch/x86_64/ABI.h" 1
typedef struct{
uint64_t a_type;
uint64_t a_val;
} auxv_t;
# 4 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Arch/x86_64/APIC.h" 1
# 59 "../Kernel/include/Arch/x86_64/APIC.h"
namespace APIC{
namespace Local{
int Initialize();
void Enable();
uint32_t Read(uint32_t off);
void Write(uint32_t off, uint32_t val);
void SendIPI(uint8_t apicID, uint32_t dsh, uint32_t type, uint8_t vector);
}
namespace IO{
int Initialize();
void SetBase(uintptr_t newBase);
void MapLegacyIRQ(uint8_t irq);
}
int Initialize();
}
extern "C" void LocalAPICEOI();
# 5 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Arch/x86_64/IDT.h" 1
# 11 "../Kernel/include/Arch/x86_64/IDT.h"
typedef struct {
uint16_t base_low;
uint16_t sel;
uint8_t ist;
uint8_t flags;
uint16_t base_med;
uint32_t base_high;
uint32_t null;
} __attribute__((packed)) idt_entry_t;
typedef struct {
uint16_t limit;
uint64_t base;
} __attribute__((packed)) idt_ptr_t;
typedef void(*isr_t)(void*, RegisterContext*);
extern "C" void idt_flush();
namespace IDT{
void Initialize();
void RegisterInterruptHandler(uint8_t interrupt, isr_t handler, void* data = nullptr);
void DisablePIC();
uint8_t ReserveUnusedInterrupt();
int GetErrCode();
}
# 9 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Arch/x86_64/SMP.h" 1
namespace SMP{
extern CPU* cpus[];
extern unsigned processorCount;
void InitializeCPU(uint16_t id);
void Initialize();
}
# 10 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Arch/x86_64/Scheduler.h" 1
# 25 "../Kernel/include/Arch/x86_64/Scheduler.h"
namespace Scheduler {
class ProcessStateThreadBlocker;
}
namespace Scheduler {
extern lock_t destroyedProcessesLock;
extern List<FancyRefPtr<Process>>* destroyedProcesses;
void RegisterProcess(FancyRefPtr<Process> proc);
void MarkProcessForDestruction(Process* proc);
__attribute__(( always_inline )) inline static Process* GetCurrentProcess() {
CPU* cpu = GetCPULocal();
Process* ret = nullptr;
if (cpu->currentThread)
ret = cpu->currentThread->parent;
return ret;
}
__attribute__(( always_inline )) inline static Thread* GetCurrentThread() { return GetCPULocal()->currentThread; }
template <typename T>
__attribute__(( always_inline )) inline bool CheckUsermodePointer(T* ptr, AddressSpace* addressSpace = GetCurrentProcess()->addressSpace) {
return addressSpace->RangeInRegion(reinterpret_cast<uintptr_t>(ptr), sizeof(T));
}
void Yield();
void Schedule(void* data, RegisterContext* r);
pid_t GetNextPID();
FancyRefPtr<Process> FindProcessByPID(pid_t pid);
pid_t GetNextProcessPID(pid_t pid);
void InsertNewThreadIntoQueue(Thread* thread);
void Initialize();
void Tick(RegisterContext* r);
}
# 11 "../Kernel/src/Objects/Process.cpp" 2
# 1 "../Kernel/include/Panic.h" 1
[[noreturn]] void KernelPanic(const char** reasons, int reasonCount);
template<typename... T>
[[noreturn]] void KernelPanic(T*... reasons){
const char* list[] { reasons... };
KernelPanic(list, sizeof...(reasons));
}
# 13 "../Kernel/src/Objects/Process.cpp" 2
extern uint8_t signalTrampolineStart[];
extern uint8_t signalTrampolineEnd[];
void IdleProcess();
FancyRefPtr<Process> Process::CreateIdleProcess(const char* name){
FancyRefPtr<Process> proc = new Process(Scheduler::GetNextPID(), name, "/", nullptr);
proc->m_mainThread->registers.rip = reinterpret_cast<uintptr_t>(IdleProcess);
proc->m_mainThread->timeSlice = 0;
proc->m_mainThread->timeSliceDefault = 0;
proc->m_mainThread->registers.rsp = reinterpret_cast<uintptr_t>(proc->m_mainThread->kernelStack);
proc->m_mainThread->registers.rbp = reinterpret_cast<uintptr_t>(proc->m_mainThread->kernelStack);
proc->m_isIdleProcess = true;
Scheduler::RegisterProcess(proc);
return proc;
}
FancyRefPtr<Process> Process::CreateKernelProcess(void* entry, const char* name, Process* parent){
FancyRefPtr<Process> proc = new Process(Scheduler::GetNextPID(), name, "/", parent);
proc->m_mainThread->registers.rip = reinterpret_cast<uintptr_t>(entry);
proc->m_mainThread->registers.rsp = reinterpret_cast<uintptr_t>(proc->m_mainThread->kernelStack);
proc->m_mainThread->registers.rbp = reinterpret_cast<uintptr_t>(proc->m_mainThread->kernelStack);
Scheduler::RegisterProcess(proc);
return proc;
}
FancyRefPtr<Process> Process::CreateELFProcess(void* elf, const Vector<String>& argv, const Vector<String>& envp, const char* execPath, Process* parent){
if (!VerifyELF(elf)) {
return nullptr;
}
const char* name = "unknown";
if(argv.size() >= 1){
name = argv[0].c_str();
}
FancyRefPtr<Process> proc = new Process(Scheduler::GetNextPID(), name, "/", parent);
Thread* thread = proc->m_mainThread.get();
thread->registers.cs = 0x1B;
thread->registers.ss = 0x23;
thread->timeSliceDefault = 10;
thread->timeSlice = thread->timeSliceDefault;
thread->priority = 4;
elf_info_t elfInfo = LoadELFSegments(proc.get(), elf, 0);
MappedRegion* stackRegion = proc->addressSpace->AllocateAnonymousVMObject(0x400000, 0, false);
thread->stack = reinterpret_cast<void*>(stackRegion->base);
thread->registers.rsp = (uintptr_t)thread->stack + 0x400000;
thread->registers.rbp = (uintptr_t)thread->stack + 0x400000;
stackRegion->vmObject->Hit(stackRegion->base, 0x400000 - 0x1000, proc->GetPageMap());
stackRegion->vmObject->Hit(stackRegion->base, 0x400000 - 0x2000, proc->GetPageMap());
stackRegion->vmObject->Hit(stackRegion->base, 0x400000 - 0x3000, proc->GetPageMap());
thread->registers.rip = proc->LoadELF(&thread->registers.rsp, elfInfo, argv, envp, execPath);
if (!thread->registers.rip) {
proc->Die();
delete proc->addressSpace;
proc->addressSpace = nullptr;
return nullptr;
}
(void)((!(thread->registers.rsp & 0xF)) || (KernelAssertionFailed("!(thread->registers.rsp & 0xF)", "../Kernel/src/Objects/Process.cpp", 86), 0));
FsNode* nullDev = fs::ResolvePath("/dev/null");
FsNode* logDev = fs::ResolvePath("/dev/kernellog");
if (nullDev) {
proc->m_fileDescriptors[0] = (fs::Open(nullDev));
} else {
Log::Warning("Failed to find /dev/null");
}
if (logDev) {
proc->m_fileDescriptors[1] = (fs::Open(logDev));
proc->m_fileDescriptors[2] = (fs::Open(logDev));
} else {
Log::Warning("Failed to find /dev/kernellog");
}
proc->MapSignalTrampoline();
Scheduler::RegisterProcess(proc);
return proc;
}
Process::Process(pid_t pid, const char* _name, const char* _workingDir, Process* parent)
: m_pid(pid), m_parent(parent) {
if(_workingDir){
strncpy(workingDir, _workingDir, 4096);
} else {
strcpy(workingDir, "/");
}
strncpy(name, _name, 255);
addressSpace = new AddressSpace(Memory::CreatePageMap());
for (unsigned i = 0; i < 34; i++) {
signalHandlers[i] = {
.action = SignalHandler::HandlerAction::Default,
.flags = 0,
.mask = 0,
.userHandler = nullptr,
};
}
creationTime = Timer::GetSystemUptimeStruct();
m_mainThread = new Thread(this, m_nextThreadID++);
m_threads.add_back(m_mainThread);
(void)((m_mainThread->parent == this) || (KernelAssertionFailed("m_mainThread->parent == this", "../Kernel/src/Objects/Process.cpp", 137), 0));
m_fileDescriptors.add_back(nullptr);
m_fileDescriptors.add_back(nullptr);
m_fileDescriptors.add_back(nullptr);
}
uintptr_t Process::LoadELF(uintptr_t* stackPointer, elf_info_t elfInfo, const Vector<String>& argv, const Vector<String>& envp, const char* execPath) {
uintptr_t rip = elfInfo.entry;
if (elfInfo.linkerPath) {
uintptr_t linkerBaseAddress = 0x7FC0000000;
FsNode* node = fs::ResolvePath("/lib/ld.so");
if (!node) {
KernelPanic("Failed to load dynamic linker!");
}
void* linkerElf = kmalloc(node->size);
fs::Read(node, 0, node->size, (uint8_t*)linkerElf);
if (!VerifyELF(linkerElf)) {
Log::Warning("Invalid Dynamic Linker ELF");
return 0;
}
elf_info_t linkerELFInfo = LoadELFSegments(this, linkerElf, linkerBaseAddress);
rip = linkerELFInfo.entry;
kfree(linkerElf);
}
char* tempArgv[argv.size()];
char* tempEnvp[envp.size()];
asm("cli");
asm volatile("mov %%rax, %%cr3" ::"a"(this->GetPageMap()->pml4Phys));
uint64_t* stack = (uint64_t*)(*stackPointer);
char* stackStr = (char*)stack;
for (int i = 0; i < argv.size(); i++) {
stackStr -= argv[i].Length() + 1;
tempArgv[i] = stackStr;
strcpy((char*)stackStr, argv[i].c_str());
}
for (int i = 0; i < envp.size(); i++) {
stackStr -= envp[i].Length() + 1;
tempEnvp[i] = stackStr;
strcpy((char*)stackStr, envp[i].c_str());
}
char* execPathValue = nullptr;
if (execPath) {
stackStr -= strlen(execPath) + 1;
strcpy((char*)stackStr, execPath);
execPathValue = stackStr;
}
stackStr -= (uintptr_t)stackStr & 0xf;
stack = (uint64_t*)stackStr;
stack -= ((argv.size() + envp.size()) % 2);
stack--;
*stack = 0;
stack -= sizeof(auxv_t) / sizeof(*stack);
*((auxv_t*)stack) = {.a_type = 3, .a_val = elfInfo.pHdrSegment};
stack -= sizeof(auxv_t) / sizeof(*stack);
*((auxv_t*)stack) = {.a_type = 4, .a_val = elfInfo.phEntrySize};
stack -= sizeof(auxv_t) / sizeof(*stack);
*((auxv_t*)stack) = {.a_type = 5, .a_val = elfInfo.phNum};
stack -= sizeof(auxv_t) / sizeof(*stack);
*((auxv_t*)stack) = {.a_type = 9, .a_val = elfInfo.entry};
if (execPath && execPathValue) {
stack -= sizeof(auxv_t) / sizeof(*stack);
*((auxv_t*)stack) = {.a_type = 15, .a_val = (uint64_t)execPathValue};
}
stack--;
*stack = 0;
stack -= envp.size();
for (int i = 0; i < envp.size(); i++) {
*(stack + i) = (uint64_t)tempEnvp[i];
}
stack--;
*stack = 0;
stack -= argv.size();
for (int i = 0; i < argv.size(); i++) {
*(stack + i) = (uint64_t)tempArgv[i];
}
stack--;
*stack = argv.size();
asm volatile("mov %%rax, %%cr3" ::"a"(Scheduler::GetCurrentProcess()->GetPageMap()->pml4Phys));
asm("sti");
*stackPointer = (uintptr_t)stack;
return rip;
}
Process::~Process() {
ScopedSpinLock lock(m_processLock);
(void)((m_state == Process_Dead) || (KernelAssertionFailed("m_state == Process_Dead", "../Kernel/src/Objects/Process.cpp", 255), 0));
(void)((!m_parent) || (KernelAssertionFailed("!m_parent", "../Kernel/src/Objects/Process.cpp", 256), 0));
if (addressSpace) {
delete addressSpace;
addressSpace = nullptr;
}
}
void Process::Destroy() {
if (m_state != Process_Dead) {
KernelObjectWatcher watcher;
Watch(watcher, 0);
m_mainThread->Signal(9);
bool interrupted = watcher.Wait();
(void)((!interrupted) || (KernelAssertionFailed("!interrupted", "../Kernel/src/Objects/Process.cpp", 273), 0));
(void)((m_state == Process_Dead) || (KernelAssertionFailed("m_state == Process_Dead", "../Kernel/src/Objects/Process.cpp", 274), 0));
}
if (m_parent) {
ScopedSpinLock acq(m_parent->m_processLock);
for (auto it = m_parent->m_children.begin(); it != m_parent->m_children.end(); it++) {
if (it->get() == this) {
m_parent->m_children.remove(it);
break;
}
}
m_parent = nullptr;
}
}
void Process::Die() {
asm volatile("sti");
CPU* cpu = GetCPULocal();
m_state = Process_Dying;
Log::Debug(debugLevelScheduler, DebugLevelNormal, "Killing Process %s (PID %d)", name, m_pid);
(void)((({ int status; status = __sync_lock_test_and_set(&Scheduler::GetCurrentThread()->lock, 1); status; })) || (KernelAssertionFailed("acquireTestLock(&Scheduler::GetCurrentThread()->lock)", "../Kernel/src/Objects/Process.cpp", 299), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&m_processLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/src/Objects/Process.cpp", 301), 0)); } });
List<FancyRefPtr<Thread>> runningThreads;
for (auto& thread : m_threads) {
asm("cli");
if (thread != cpu->currentThread && thread) {
if (thread->blocker && thread->state == ThreadStateBlocked) {
thread->blocker->Interrupt();
}
thread->state = ThreadStateZombie;
if (({ int status; status = __sync_lock_test_and_set(&thread->lock, 1); status; })) {
asm("sti");
runningThreads.add_back(thread);
asm("cli");
} else {
thread->state =
ThreadStateBlocked;
thread->timeSlice = thread->timeSliceDefault = 0;
}
}
}
asm("sti");
while (m_children.get_length()) {
FancyRefPtr<Process> child = m_children.get_front();
if (child->State() == Process_Running) {
child->GetMainThread()->Signal(9);
while(child->State() != Process_Dead);
} else if (child->State() == Process_Dying) {
KernelObjectWatcher w;
child->Watch(w, 0);
bool wasInterrupted = w.Wait();
(void)((!wasInterrupted) || (KernelAssertionFailed("!wasInterrupted", "../Kernel/src/Objects/Process.cpp", 336), 0));
}
child->m_parent = nullptr;
m_children.remove(child);
}
({ __sync_lock_release(&m_processLock); });;
asm("sti");
while (runningThreads.get_length()) {
auto it = runningThreads.begin();
while (it != runningThreads.end()) {
FancyRefPtr<Thread> thread = *it;
if (!({ int status; status = __sync_lock_test_and_set(&thread->lock, 1); status; })) {
runningThreads.remove(*(it++));
thread->state = ThreadStateBlocked;
thread->timeSlice = thread->timeSliceDefault = 0;
} else {
it++;
}
}
Scheduler::GetCurrentThread()->Sleep(50000);
}
(void)((!runningThreads.get_length()) || (KernelAssertionFailed("!runningThreads.get_length()", "../Kernel/src/Objects/Process.cpp", 364), 0));
({ unsigned i = 0; while (__sync_lock_test_and_set(&m_processLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/src/Objects/Process.cpp", 366), 0)); } });
({ unsigned i = 0; while (__sync_lock_test_and_set(&cpu->runQueueLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/src/Objects/Process.cpp", 367), 0)); } });
asm("cli");
for (unsigned j = 0; j < cpu->runQueue->get_length(); j++) {
if (Thread* thread = cpu->runQueue->get_at(j); thread != cpu->currentThread && thread->parent == this) {
cpu->runQueue->remove_at(j);
}
}
({ __sync_lock_release(&cpu->runQueueLock); });;
asm("sti");
for (unsigned i = 0; i < SMP::processorCount; i++) {
if (i == cpu->id)
continue;
CPU* other = SMP::cpus[i];
asm("sti");
({ unsigned i = 0; while (__sync_lock_test_and_set(&other->runQueueLock, 1) && ++i < 0xFFFFFFF) asm("pause"); if (i >= 0xFFFFFFF) { (void)((!"Deadlock!") || (KernelAssertionFailed("!\"Deadlock!\"", "../Kernel/src/Objects/Process.cpp", 385), 0)); } });
asm("cli");
(void)((!(other->currentThread && other->currentThread->parent == this)) || (KernelAssertionFailed("!(other->currentThread && other->currentThread->parent == this)", "../Kernel/src/Objects/Process.cpp", 388), 0));
for (unsigned j = 0; j < other->runQueue->get_length(); j++) {
Thread* thread = other->runQueue->get_at(j);
(void)((thread) || (KernelAssertionFailed("thread", "../Kernel/src/Objects/Process.cpp", 393), 0));
if (thread->parent == this) {
other->runQueue->remove(thread);
}
}
({ __sync_lock_release(&other->runQueueLock); });;
asm("sti");
if (other->currentThread == nullptr) {
APIC::Local::SendIPI(i, (1 << 18), 0, 0xFD);
}
}
asm("sti");
Log::Debug(debugLevelScheduler, DebugLevelVerbose, "[%d] Closing fds...", m_pid);
for (auto& fd : m_fileDescriptors) {
fd = nullptr;
}
m_fileDescriptors.clear();
Log::Debug(debugLevelScheduler, DebugLevelVerbose, "[%d] Closing handles...", m_pid);
for (auto& handle : m_handles) {
if(handle.ko.get()){
handle.ko->Destroy();
}
handle.ko = nullptr;
}
m_handles.clear();
Log::Debug(debugLevelScheduler, DebugLevelVerbose, "[%d] Signaling watchers...", m_pid);
for(auto* watcher : m_watching){
watcher->Signal();
}
m_watching.clear();
m_state = Process_Dead;
if(m_parent && (m_parent->State() == Process_Running)){
Log::Debug(debugLevelScheduler, DebugLevelVerbose, "[%d] Sending SIGCHILD to %s...", m_pid, m_parent->name);
m_parent->GetMainThread()->Signal(17);
}
Log::Debug(debugLevelScheduler, DebugLevelVerbose, "[%d] Marking process for destruction...", m_pid);
Scheduler::MarkProcessForDestruction(this);
bool isDyingProcess = (cpu->currentThread->parent == this);
if(isDyingProcess){
Log::Debug(debugLevelScheduler, DebugLevelVerbose, "[%d] Rescheduling...", m_pid);
asm("cli");
asm volatile("mov %%rax, %%cr3" ::"a"(((uint64_t)Memory::kernelPML4) - 0xFFFFFFFF80000000ULL));
cpu->currentThread->state = ThreadStateDying;
cpu->currentThread->timeSlice = 0;
({ __sync_lock_release(&m_processLock); });;
asm volatile("sti; int $0xFD");
(void)((!"We should not be here") || (KernelAssertionFailed("!\"We should not be here\"", "../Kernel/src/Objects/Process.cpp", 459), 0));
} else {
({ __sync_lock_release(&m_processLock); });;
}
}
void Process::Start(){
ScopedSpinLock acq(m_processLock);
(void)((!m_started) || (KernelAssertionFailed("!m_started", "../Kernel/src/Objects/Process.cpp", 467), 0));
Scheduler::InsertNewThreadIntoQueue(m_mainThread.get());
m_started = true;
}
void Process::Watch(KernelObjectWatcher& watcher, int events) {
ScopedSpinLock acq(m_watchingLock);
if (m_state == Process_Dead) {
watcher.Signal();
return;
}
m_watching.add_back(&watcher);
}
void Process::Unwatch(KernelObjectWatcher& watcher) {
ScopedSpinLock acq(m_watchingLock);
if (m_state == Process_Dead) {
return;
}
m_watching.remove(&watcher);
}
FancyRefPtr<Process> Process::Fork() {
ScopedSpinLock lock(m_processLock);
FancyRefPtr<Process> newProcess = new Process(Scheduler::GetNextPID(), name, workingDir, this);
delete newProcess->addressSpace;
newProcess->addressSpace = addressSpace->Fork();
newProcess->euid = euid;
newProcess->uid = uid;
newProcess->euid = egid;
newProcess->gid = gid;
newProcess->m_fileDescriptors.resize(m_fileDescriptors.size());
for(unsigned i = 0; i < m_fileDescriptors.size(); i++){
UNIXFileDescriptor* source = m_fileDescriptors[i].get();
if(!source || !source->node){
continue;
}
UNIXFileDescriptor* dest = fs::Open(source->node);
dest->mode = source->mode;
dest->pos = source->pos;
newProcess->m_fileDescriptors[i] = dest;
}
m_children.add_back(newProcess);
Scheduler::RegisterProcess(newProcess);
return newProcess;
}
pid_t Process::CreateChildThread(uintptr_t entry, uintptr_t stack, uint64_t cs, uint64_t ss){
pid_t threadID = m_nextThreadID++;
Thread& thread = *m_threads.add_back(new Thread(this, threadID));
thread.registers.rip = entry;
thread.registers.rsp = stack;
thread.registers.rbp = stack;
thread.state = ThreadStateRunning;
thread.stack = thread.stackLimit = reinterpret_cast<void*>(stack);
RegisterContext* registers = &thread.registers;
registers->rflags = 0x202;
thread.registers.cs = cs;
thread.registers.ss = ss;
thread.timeSliceDefault = 10;
thread.timeSlice = thread.timeSliceDefault;
thread.priority = 4;
Scheduler::InsertNewThreadIntoQueue(&thread);
return threadID;
}
int Process::AllocateFileDescriptor(FancyRefPtr<UNIXFileDescriptor> fd){
ScopedSpinLock lockFDs(m_fileDescriptorLock);
int i = 0;
for(; i < static_cast<int>(m_fileDescriptors.get_length()); i++){
if(m_fileDescriptors[i] == nullptr){
m_fileDescriptors[i] = std::move(fd);
return i;
}
}
m_fileDescriptors.add_back(std::move(fd));
return i;
}
FancyRefPtr<Thread> Process::GetThreadFromTID_Unlocked(pid_t tid) {
for (const FancyRefPtr<Thread>& t : m_threads) {
if (t->tid == tid) {
return t;
}
}
return nullptr;
}
void Process::MapSignalTrampoline(){
m_signalTrampoline = addressSpace->AllocateAnonymousVMObject(
((signalTrampolineEnd - signalTrampolineStart) + 4096U - 1) &
~static_cast<unsigned>(4096U - 1),
0, false);
reinterpret_cast<PhysicalVMObject*>(m_signalTrampoline->vmObject.get())
->ForceAllocate();
m_signalTrampoline->vmObject->MapAllocatedBlocks(m_signalTrampoline->Base(), GetPageMap());
asm volatile("cli; mov %%rax, %%cr3" ::"a"(GetPageMap()->pml4Phys));
memcpy(reinterpret_cast<void*>(m_signalTrampoline->Base()), signalTrampolineStart,
signalTrampolineEnd - signalTrampolineStart);
asm volatile("mov %%rax, %%cr3; sti" ::"a"(Scheduler::GetCurrentProcess()->GetPageMap()->pml4Phys));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment