22 #include "pedigree/kernel/process/Thread.h" 23 #include "pedigree/kernel/LockGuard.h" 24 #include "pedigree/kernel/Log.h" 25 #include "pedigree/kernel/machine/InputManager.h" 26 #include "pedigree/kernel/process/Mutex.h" 27 #include "pedigree/kernel/process/PerProcessorScheduler.h" 28 #include "pedigree/kernel/process/Process.h" 29 #include "pedigree/kernel/process/ProcessorThreadAllocator.h" 30 #include "pedigree/kernel/process/Scheduler.h" 31 #include "pedigree/kernel/processor/NMFaultHandler.h" 32 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 33 #include "pedigree/kernel/processor/Processor.h" 34 #include "pedigree/kernel/processor/ProcessorInformation.h" 35 #include "pedigree/kernel/processor/state.h" 36 #include "pedigree/kernel/utilities/ExtensibleBitmap.h" 37 #include "pedigree/kernel/utilities/Iterator.h" 38 #include "pedigree/kernel/utilities/MemoryAllocator.h" 39 #include "pedigree/kernel/utilities/Vector.h" 40 #include "pedigree/kernel/utilities/utility.h" 43 Process *pParent, ThreadStartFunc pStartFunction,
void *pParam,
44 void *pStack,
bool semiUser,
bool bDontPickCore,
bool delayedStart)
49 FATAL(
"Thread::Thread(): Parent process was NULL!");
60 bool bUserMode =
true;
61 void *requestedStack = pStack;
72 pStack = kernelStack->getTop();
104 ProcessorThreadAllocator::instance().
addThread(
105 this, pStartFunction, pParam, bUserMode, pStack);
112 this, pStartFunction, pParam, bUserMode, pStack);
121 FATAL(
"Thread::Thread(): Parent process was NULL!");
140 FATAL(
"Thread::Thread(): Parent process was NULL!");
172 ProcessorThreadAllocator::instance().
addThread(
this, state);
179 WARNING(
"A thread is being removed, but it never removed itself from " 182 "This warning indicates an application or kernel module is buggy!");
192 for (
size_t i = 0; i < MAX_NESTED_EVENTS; i++)
203 physical_uintptr_t phys = 0;
211 uintptr_t base =
reinterpret_cast<uintptr_t
>(
m_pTlsBase);
221 ERROR(
"Thread: no parent, but a TLS base exists.");
251 ERROR(
"Thread::shutdown: request in pending requests list has " 276 if (pReq->bCompleted)
280 if (pReq->refcnt <= 1)
288 if (pReq->pThread ==
this)
298 if (pReq->refcnt > 1)
301 if (pReq->pThread ==
this)
307 pReq->bReject =
true;
342 void Thread::forceToStartupProcessor()
353 ERROR(
"Thread::forceToStartupProcessor must be run as the desired " 368 if (s != Thread::Zombie)
370 WARNING(
"Error condition in Thread::setStatus, more info below...");
372 FATAL(
"Thread::setStatus called with non-zombie status, when the " 373 "thread is a zombie!");
383 if (s == Thread::Zombie)
408 if (
m_Status == Thread::Ready && previousStatus != Thread::Running)
411 reportWakeupUnlocked(Unknown);
416 m_pScheduler->threadStatusChanged(
this);
429 ERROR(
"Thread: Max nested events!");
431 return *(m_StateLevels[MAX_NESTED_EVENTS - 1].
m_State);
450 ERROR(
"Thread: Potential error: popStack() called with state level 0!");
451 ERROR(
"Thread: (ignore this if longjmp has been called)");
486 if (stateLevel >= MAX_NESTED_EVENTS)
487 stateLevel = MAX_NESTED_EVENTS - 1;
488 if (m_StateLevels[stateLevel].m_pKernelStack == 0)
511 uintptr_t stack =
reinterpret_cast<uintptr_t
>(
519 if (stateLevel >= MAX_NESTED_EVENTS)
522 "Thread::pokeState(): stateLevel `" << stateLevel
523 <<
"' is over the maximum.");
526 *(m_StateLevels[stateLevel].
m_State) = state;
534 WARNING(
"Thread: dropping event as we are a zombie");
563 WARNING(
"Thread: not immediately waking up from event as we're not " 582 bool bDelete =
false;
591 if ((*it)->isDeletable())
623 if ((*it)->getNumber() == eventNumber)
635 for (
auto it : deregisterEvents)
637 it->deregisterThread(
this);
638 if (it->isDeletable())
645 Event *pResult =
nullptr;
661 ERROR(
"A null event was in a thread's event queue!");
691 bool Thread::hasEvents()
721 if ((*it)->getNumber() == eventNumber)
760 if (!m_StateLevels[0].m_pKernelStack)
773 THREAD_TLS_SIZE, base);
782 <<
"]: failed to allocate TLS area.");
787 physical_uintptr_t phys =
795 uint32_t *tlsBase =
reinterpret_cast<uint32_t *
>(
m_pTlsBase);
797 *tlsBase =
static_cast<uint32_t
>(
m_Id);
802 #ifdef VERBOSE_KERNEL 805 <<
"]: allocated TLS area at " <<
m_pTlsBase <<
".");
808 return reinterpret_cast<uintptr_t
>(
m_pTlsBase);
832 uintptr_t *pBase =
reinterpret_cast<uintptr_t *
>(base);
862 Joining, reinterpret_cast<uintptr_t>(__builtin_return_address(0)));
889 WARNING(
"Thread::detach() called on a thread that has already exited.");
898 ERROR(
"Thread::detach() called while other threads are joining.");
907 Thread::StateLevel::StateLevel()
908 : m_State(), m_pKernelStack(0), m_pUserStack(0), m_pAuxillaryStack(0),
909 m_InhibitMask(), m_pBlockingThread(0)
911 m_State =
new SchedulerState;
912 ByteSet(m_State, 0,
sizeof(SchedulerState));
916 Thread::StateLevel::~StateLevel()
922 : m_State(), m_pKernelStack(s.
m_pKernelStack), m_pUserStack(s.m_pUserStack),
924 m_pBlockingThread(s.m_pBlockingThread)
926 m_State =
new SchedulerState(*(s.
m_State));
933 m_State =
new SchedulerState(*(s.
m_State));
953 m_pScheduler = pScheduler;
963 if (m_StateLevels[level].m_pKernelStack)
966 m_StateLevels[level].m_pKernelStack);
969 else if (m_StateLevels[level].m_pAuxillaryStack)
972 m_StateLevels[level].m_pAuxillaryStack);
976 if (m_StateLevels[level].m_pUserStack &&
m_pParent)
981 m_StateLevels[level].m_pUserStack);
982 m_StateLevels[level].m_pUserStack = 0;
1001 if ((*it) == watcher)
1016 reportWakeupUnlocked(reason);
1019 void Thread::reportWakeupUnlocked(
WakeReason reason)
void cullEvent(Event *pEvent)
void removeWakeupWatcher(WakeReason *watcher)
void allocateStackAtLevel(size_t stateLevel)
void addWakeupWatcher(WakeReason *watcher)
void pushBack(const T &value)
void pushBack(const T &value)
void inhibitEvent(size_t eventNumber, bool bInhibit)
virtual void unmap(void *virtualAddress)=0
SharedPointer< ExtensibleBitmap > m_InhibitMask
void setScheduler(class PerProcessorScheduler *pScheduler)
static void threadExited() NORETURN
static PhysicalMemoryManager & instance()
void popState(bool clean=true)
Iterator erase(Iterator &Iter)
SchedulerState & pushState()
virtual void getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
A vector / dynamic array.
List< RequestQueue::Request * > m_PendingRequests
static void setTlsBase(uintptr_t newBase)
void setDebugState(DebugState state, uintptr_t address)
bool isRequestValid(const Request *r)
List< Event * > m_EventQueue
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
virtual bool isMapped(void *virtualAddress)=0
void setTlsBase(uintptr_t base)
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
size_t getStateLevel() const
virtual Stack * allocateStack()=0
size_t getSpecificNestingLevel()
bool acquire(bool recurse=false, bool safe=true)
Spinlock m_ConcurrencyLock
void free(T address, T length, bool merge=true)
VirtualAddressSpace::Stack * m_pKernelStack
static ProcessorInformation & information()
virtual void freeStack(Stack *pStack)=0
bool allocate(T length, T &address)
bool hasEvent(Event *pEvent)
static const size_t Write
bool sendEvent(Event *pEvent)
VirtualAddressSpace::Stack * m_pAuxillaryStack
void reportWakeup(WakeReason reason)
void cleanStateLevel(size_t level)
MemoryAllocator & getDynamicSpaceAllocator()
Thread(Process *pParent, ThreadStartFunc pStartFunction, void *pParam, void *pStack=0, bool semiUser=false, bool bDontPickCore=false, bool delayedStart=false)
void removeThread(Thread *pThread)
static NMFaultHandler & instance()
void pokeState(size_t stateLevel, SchedulerState &state)
void addThread(Thread *pThread, Thread::ThreadStartFunc pStartFunction, void *pParam, bool bUsermode, void *pStack)
static Scheduler & instance()
The exception was caused by a hardware task switch.
void addRequest(RequestQueue::Request *req)
virtual uintptr_t getDynamicStart() const
void removeRequest(RequestQueue::Request *req)
No unwind necessary, carry on as normal.
VirtualAddressSpace * getAddressSpace()
virtual bool isDeletable()
virtual void freePage(physical_uintptr_t page)=0
void setInterruptible(bool state)
void removeThread(Thread *pThread)
void addThread(Thread *pThread, PerProcessorScheduler &PPSched)
List< WakeReason * > m_WakeWatchers
void registerThread(Thread *thread)
UnwindType getUnwindState()
virtual size_t getNumber()=0
class PerProcessorScheduler * getScheduler() const
size_t addThread(Thread *pThread)
MemoryAllocator & getSpaceAllocator()
void deregisterThread(Thread *thread)
static SharedPointer< T > allocate(Args...)