/******************************************************************************* Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014. This file is part of Sortix. Sortix is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Sortix is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Sortix. If not, see . sortix/kernel/thread.h Describes a thread belonging to a process. *******************************************************************************/ #ifndef INCLUDE_SORTIX_KERNEL_THREAD_H #define INCLUDE_SORTIX_KERNEL_THREAD_H #include #include #include #include #include #include #include typedef struct multiboot_info multiboot_info_t; namespace Sortix { class Process; class Thread; extern "C" void KernelInit(unsigned long magic, multiboot_info_t* bootinfo); typedef void (*ThreadEntry)(void* user); // Simply exits the kernel thread. __attribute__((noreturn)) void KernelThreadExit(); // Internally used as a kernel thread entry point that exits the thread // upon the actual thread entry returning. extern "C" __attribute__((noreturn)) void BootstrapKernelThread(void* user, ThreadEntry entry); // These functions create a new kernel process but doesn't start it. Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs, unsigned long fsbase, unsigned long gsbase); Thread* CreateKernelThread(Process* process, ThreadEntry entry, void* user, size_t stacksize = 0); Thread* CreateKernelThread(ThreadEntry entry, void* user, size_t stacksize = 0); // This function can be used to start a thread from the above functions. void StartKernelThread(Thread* thread); // Alternatively, these functions both create and start the thread. Thread* RunKernelThread(Process* process, CPU::InterruptRegisters* regs); Thread* RunKernelThread(Process* process, ThreadEntry entry, void* user, size_t stacksize = 0); Thread* RunKernelThread(ThreadEntry entry, void* user, size_t stacksize = 0); void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry, void* user, addr_t stack, size_t stacksize); class Thread { friend Thread* CreateKernelThread(Process* process, CPU::InterruptRegisters* regs, unsigned long fsbase, unsigned long gsbase); friend void KernelInit(unsigned long magic, multiboot_info_t* bootinfo); friend void UpdatePendingSignals(Thread* thread); public: static void Init(); private: Thread(); public: ~Thread(); public: size_t id; Process* process; Thread* prevsibling; Thread* nextsibling; public: Thread* scheduler_list_prev; Thread* scheduler_list_next; volatile ThreadState state; uint8_t fpuenv[512UL + 16UL]; uint8_t* fpuenvaligned; bool fpuinitialized; public: sigset_t signal_pending; sigset_t signal_mask; stack_t signal_stack; addr_t addrspace; addr_t kernelstackpos; size_t kernelstacksize; bool kernelstackmalloced; bool pledged_destruction; #if defined(__i386__) || defined(__x86_64__) public: unsigned long fsbase; unsigned long gsbase; #endif private: CPU::InterruptRegisters registers; public: void SaveRegisters(const CPU::InterruptRegisters* src); void LoadRegisters(CPU::InterruptRegisters* dest); void HandleSignal(CPU::InterruptRegisters* regs); void HandleSigreturn(CPU::InterruptRegisters* regs); bool DeliverSignal(int signum); bool DeliverSignalUnlocked(int signum); addr_t SwitchAddressSpace(addr_t newaddrspace); }; Thread* CurrentThread(); } // namespace Sortix #endif