26 #include "pedigree/kernel/process/Semaphore.h" 27 #include "pedigree/kernel/Log.h" 28 #include "pedigree/kernel/machine/Machine.h" 29 #include "pedigree/kernel/machine/Timer.h" 30 #include "pedigree/kernel/process/PerProcessorScheduler.h" 31 #include "pedigree/kernel/process/Scheduler.h" 32 #include "pedigree/kernel/process/Thread.h" 33 #include "pedigree/kernel/process/eventNumbers.h" 34 #include "pedigree/kernel/processor/Processor.h" 35 #include "pedigree/kernel/processor/ProcessorInformation.h" 36 #include "pedigree/kernel/utilities/Iterator.h" 37 #include "pedigree/kernel/utilities/assert.h" 38 #include "pedigree/kernel/utilities/utility.h" 40 static void interruptSemaphore(uint8_t *pBuffer)
45 Semaphore::SemaphoreEvent::SemaphoreEvent()
47 reinterpret_cast<uintptr_t>(&interruptSemaphore),
52 Semaphore::SemaphoreEvent::~SemaphoreEvent() =
default;
59 bool Semaphore::SemaphoreEvent::unserialize(
67 return EventNumbers::Interrupt;
71 : magic(0xdeadbaba), m_Counter(nInitialValue), m_BeingModified(false),
72 m_Queue(), m_bCanInterrupt(canInterrupt)
74 assert(magic == 0xdeadbaba);
79 assert(magic == 0xdeadbaba);
101 if (magic != 0xdeadbaba)
110 #ifdef MULTIPROCESSOR 111 for (
int i = 0; i < 10; i++)
114 return SemaphoreResult::withValue(
true);
118 if (timeoutSecs || timeoutUsecs)
122 pEvent, timeoutSecs, timeoutUsecs);
142 bool bWasInterrupts = m_BeingModified.interrupts();
168 reinterpret_cast<uintptr_t>(__builtin_return_address(0)));
180 if (m_bCanInterrupt && wakeReason != Thread::NotWoken)
183 if (wakeReason != Thread::Unknown)
188 result = SemaphoreResult::withError(TimedOut);
193 result = SemaphoreResult::withError(Interrupted);
225 ssize_t value = m_Counter;
227 if ((value - static_cast<ssize_t>(n)) < 0)
229 if (m_Counter.compareAndSwap(value, value - n))
231 #ifdef STRICT_LOCK_ORDERING 241 assert(magic == 0xdeadbaba);
255 while (m_Queue.
count() != 0)
260 WARNING(
"Null thread in a Semaphore thread queue");
265 WARNING(
"A thread that was to be woken by a Semaphore is no " 266 "longer in the scheduler");
269 else if (pThread->
getStatus() != Thread::Sleeping)
273 if (pThread->
getStatus() == Thread::Zombie)
275 "Semaphore has a zombie thread in its thread queue");
277 stillPendingThreads.
pushBack(pThread);
284 if (stillPendingThreads.
count())
287 it != stillPendingThreads.
end(); ++it)
296 if (wakeupThreads.
count())
299 it != wakeupThreads.
end(); ++it)
313 #ifdef STRICT_LOCK_ORDERING 320 return static_cast<ssize_t
>(m_Counter);
void removeWakeupWatcher(WakeReason *watcher)
void addWakeupWatcher(WakeReason *watcher)
void pushBack(const T &value)
virtual void removeAlarm(class Event *pEvent)=0
Iterator erase(Iterator &Iter)
virtual Timer * getTimer()=0
void setDebugState(DebugState state, uintptr_t address)
void removeThread(class Thread *pThread)
void setUnwindState(UnwindType ut)
bool acquire(bool recurse=false, bool safe=true)
static ProcessorInformation & information()
virtual size_t serialize(uint8_t *pBuffer)
Semaphore(size_t nInitialValue, bool canInterrupt=true)
static Scheduler & instance()
static void setInterrupts(bool bEnable)
SemaphoreResult acquireWithResult(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
No unwind necessary, carry on as normal.
void setInterrupted(bool b)
bool tryAcquire(size_t n=1)
virtual void addAlarm(class Event *pEvent, size_t alarmSecs, size_t alarmUsecs=0)=0
virtual size_t getNumber()