/******************************************************************************* Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013. 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 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); extern "C" void Thread__OnSigKill(Thread* thread); typedef void (*sighandler_t)(int); 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 Thread__OnSigKill(Thread* thread); public: static void Init(); private: Thread(); public: ~Thread(); public: size_t id; Process* process; bool terminated; Thread* prevsibling; Thread* nextsibling; // These are some things used internally by the scheduler and should not be // touched by anything but it. Consider it private. public: Thread* schedulerlistprev; Thread* schedulerlistnext; volatile ThreadState state; uint8_t fpuenv[512UL + 16UL]; uint8_t* fpuenvaligned; bool fpuinitialized; public: addr_t addrspace; sighandler_t sighandler; addr_t kernelstackpos; size_t kernelstacksize; bool kernelstackmalloced; #if defined(__i386__) || defined(__x86_64__) public: unsigned long fsbase; unsigned long gsbase; #endif private: CPU::InterruptRegisters registers; Signal::Queue signalqueue; int currentsignal; int siglevel; int signums[SIG_NUM_LEVELS]; CPU::InterruptRegisters sigregs[SIG_NUM_LEVELS]; 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); addr_t SwitchAddressSpace(addr_t newaddrspace); private: void GotoOnSigKill(CPU::InterruptRegisters* regs); __attribute__((noreturn)) void OnSigKill(); void LastPrayer(); void SetHavePendingSignals(); void HandleSignalFixupRegsCPU(CPU::InterruptRegisters* regs); void HandleSignalCPU(CPU::InterruptRegisters* regs); }; Thread* CurrentThread(); } // namespace Sortix #endif