📄 osutils.cxx
字号:
sleepTimer = time;
if (time == PMaxTimeInterval)
sleepTimer.Pause();
switch (status) {
case Running : // Suspending itself, yield to next thread
status = Sleeping;
Yield();
break;
case Waiting :
case Suspended :
status = Sleeping;
break;
default :
break;
}
}
void PThread::BeginThread()
{
if (IsSuspended()) { // Begins suspended
status = Suspended;
Yield();
}
else
status = Running;
Main();
status = Terminating;
Yield(); // Never returns from here
}
void PThread::Yield()
{
PThread * current = PProcessInstance->currentThread;
if (current == PProcessInstance) {
PProcessInstance->GetTimerList()->Process();
if (current->link == current)
return;
}
else {
char stackUsed;
if (&stackUsed < current->stackBase) {
char * buf = (char *)malloc(1000);
sprintf(buf, "Stack overflow!\n"
"\n"
"Thread: 0x%08x - %s\n"
"Stack top : 0x%08x\n"
"Stack base : 0x%08x\n"
"Stack frame: 0x%08x\n"
"\n",
(int)current, current->GetClass(),
(int)current->stackTop,
(int)current->stackBase,
(int)&stackUsed);
PAssertAlways(buf);
PError << "Aborting." << endl;
#if defined(P_VXWORKS)
exit(1);
#else
_exit(1);
#endif
}
}
if (current->status == Running && current->basePriority == HighestPriority)
return;
do {
if (current->status == Running)
current->status = Waiting;
static const int dynamicLevel[NumPriorities] = { -1, 3, 1, 0, 0 };
current->dynamicPriority = dynamicLevel[current->basePriority];
PThread * next = NULL; // Next thread to be scheduled
PThread * prev = current; // Need the thread in the previous link
PThread * start = current; // Need thread in list that is the "start"
PThread * thread = current->link;
BOOL pass = 0;
BOOL canUseLowest = TRUE;
for (;;) {
if (PProcessTerminating) {
next = PProcessInstance;
next->status = Running;
break;
}
switch (thread->status) {
case Waiting :
if (thread->dynamicPriority == 0) {
next = thread;
next->status = Running;
}
else if (thread->dynamicPriority > 0) {
thread->dynamicPriority--;
canUseLowest = FALSE;
}
else if (pass > 1 && canUseLowest)
thread->dynamicPriority++;
break;
case Sleeping :
if (thread->sleepTimer == 0) {
if (thread->IsSuspended())
thread->status = Suspended;
else {
thread->status = Running;
next = thread;
}
}
break;
case BlockedIO :
if (thread->IsNoLongerBlocked()) {
if (PProcessTerminating)
next = PProcessInstance;
else {
thread->ClearBlock();
next = thread;
}
next->status = Running;
}
break;
case BlockedSem :
case SuspendedBlockSem :
if (thread->blockingSemaphore->timeout == 0) {
thread->blockingSemaphore->PSemaphore::Signal();
thread->blockingSemaphore->timeout = 0;
if (thread->status == Waiting) {
next = thread;
next->status = Running;
}
}
break;
case Starting :
if (!thread->IsSuspended())
next = thread;
break;
case Terminating :
if (thread == current) // Cannot self terminate
next = PProcessInstance; // So switch to process thread first
else {
prev->link = thread->link; // Unlink it from the list
if (thread == start) // If unlinking the "start" thread
start = prev; // then we better make it still in list
thread->status = Terminated; // Flag thread as terminated
if (thread->autoDelete)
delete thread; // Destroy if auto-delete
thread = prev;
}
break;
default :
break;
}
if (next != NULL) // Have a thread to run
break;
// Need to have previous thread so can unlink a terminating thread
prev = thread;
thread = thread->link;
if (thread == start) {
pass++;
if (pass > 3) // Everything is blocked
PProcessInstance->OperatingSystemYield();
}
}
PProcessInstance->currentThread = next;
next->SwitchContext(current);
// Could get here with a self terminating thread, so go around again if all
// we did was switch stacks, and do not actually have a running thread.
} while (PProcessInstance->currentThread->status != Running);
if (PProcessTerminating) {
PProcessTerminating = FALSE;
if (PProcessInstance->IsDescendant(PServiceProcess::Class()))
((PServiceProcess *)PProcessInstance)->OnStop();
exit(PProcessInstance->terminationValue);
}
}
#endif
///////////////////////////////////////////////////////////////////////////////
// PSemaphore
#ifndef P_PLATFORM_HAS_THREADS
PSemaphore::PSemaphore(unsigned initial, unsigned maxCount)
{
PAssert(maxCount > 0, "Invalid semaphore maximum.");
if (initial > maxCount)
initial = maxCount;
currentCount = initial;
maximumCount = maxCount;
}
PSemaphore::~PSemaphore()
{
PAssert(blockedThreads.IsEmpty(),
"Semaphore destroyed while still has blocked threads");
}
void PSemaphore::Wait()
{
Wait(PMaxTimeInterval);
}
BOOL PSemaphore::Wait(const PTimeInterval & time)
{
if (currentCount > 0)
currentCount--;
else {
PThread * thread = PThread::Current();
blockedThreads.Enqueue(thread);
thread->blockingSemaphore = this;
thread->status = PThread::BlockedSem;
timeout = time;
if (time == PMaxTimeInterval)
timeout.Pause();
PThread::Yield();
if (timeout == 0)
return FALSE;
}
return TRUE;
}
void PSemaphore::Signal()
{
if (blockedThreads.GetSize() > 0) {
PThread * thread = blockedThreads.Dequeue();
switch (thread->status) {
case PThread::BlockedSem :
thread->status = PThread::Waiting;
break;
case PThread::SuspendedBlockSem :
thread->status = PThread::Suspended;
break;
default:
PAssertAlways("Semaphore unblock of thread that is not blocked");
}
thread->sleepTimer = 0;
timeout = PMaxTimeInterval;
timeout.Pause();
}
else if (currentCount < maximumCount)
currentCount++;
}
BOOL PSemaphore::WillBlock() const
{
return currentCount == 0;
}
PMutex::PMutex()
: PSemaphore(1, 1)
{
}
PSyncPoint::PSyncPoint()
: PSemaphore(0, 1)
{
}
#endif
void PSyncPointAck::Signal()
{
PSyncPoint::Signal();
ack.Wait();
}
void PSyncPointAck::Signal(const PTimeInterval & wait)
{
PSyncPoint::Signal();
ack.Wait(wait);
}
void PSyncPointAck::Acknowledge()
{
ack.Signal();
}
void PCondMutex::WaitCondition()
{
for (;;) {
Wait();
if (Condition())
return;
PMutex::Signal();
OnWait();
syncPoint.Wait();
}
}
void PCondMutex::Signal()
{
if (Condition())
syncPoint.Signal();
PMutex::Signal();
}
void PCondMutex::OnWait()
{
// Do nothing
}
PIntCondMutex::PIntCondMutex(int val, int targ, Operation op)
{
value = val;
target = targ;
operation = op;
}
void PIntCondMutex::PrintOn(ostream & strm) const
{
strm << '(' << value;
switch (operation) {
case LT :
strm << " < ";
case LE :
strm << " <= ";
case GE :
strm << " >= ";
case GT :
strm << " > ";
default:
strm << " == ";
}
strm << target << ')';
}
BOOL PIntCondMutex::Condition()
{
switch (operation) {
case LT :
return value < target;
case LE :
return value <= target;
case GE :
return value >= target;
case GT :
return value > target;
default :
break;
}
return value == target;
}
PIntCondMutex & PIntCondMutex::operator=(int newval)
{
Wait();
value = newval;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator++()
{
Wait();
value++;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator+=(int inc)
{
Wait();
value += inc;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator--()
{
Wait();
value--;
Signal();
return *this;
}
PIntCondMutex & PIntCondMutex::operator-=(int dec)
{
Wait();
value -= dec;
Signal();
return *this;
}
void PReadWriteMutex::StartRead()
{
starvationPreventer.Wait();
starvationPreventer.Signal();
++readers;
}
void PReadWriteMutex::EndRead()
{
--readers;
}
void PReadWriteMutex::StartWrite()
{
starvationPreventer.Wait();
readers.WaitCondition();
}
void PReadWriteMutex::EndWrite()
{
starvationPreventer.Signal();
readers.Signal();
}
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -