📄 synch-sem.cc
字号:
#include "copyright.h"
#include "synch.h"
#include "system.h"
//----------------------------------------------------------------------
// Semaphore::Semaphore
// Initialize a semaphore, so that it can be used for synchronization.
//
// "debugName" is an arbitrary name, useful for debugging.
// "initialValue" is the initial value of the semaphore.
//----------------------------------------------------------------------
Semaphore::Semaphore(char* debugName, int initialValue)
{
name = debugName;
value = initialValue;
queue = new List;
}
//----------------------------------------------------------------------
// Semaphore::Semaphore
// De-allocate semaphore, when no longer needed. Assume no one
// is still waiting on the semaphore!
//----------------------------------------------------------------------
Semaphore::~Semaphore()
{
delete queue;
}
//----------------------------------------------------------------------
// Semaphore::P
// Wait until semaphore value > 0, then decrement. Checking the
// value and decrementing must be done atomically, so we
// need to disable interrupts before checking the value.
//
// Note that Thread::Sleep assumes that interrupts are disabled
// when it is called.
//----------------------------------------------------------------------
void
Semaphore::P()
{
IntStatus oldLevel = interrupt->SetLevel(IntOff); //禁用中断
while (value == 0) { // semaphore not available
queue->Append((void *)currentThread); // so go to sleep
currentThread->Sleep();
}
value--; // semaphore available,
// consume its value
(void) interrupt->SetLevel(oldLevel); //恢复中断
}
//----------------------------------------------------------------------
// Semaphore::V
// Increment semaphore value, waking up a waiter if necessary.
// As with P(), this operation must be atomic, so we need to disable
// interrupts. Scheduler::ReadyToRun() assumes that threads
// are disabled when it is called.
//----------------------------------------------------------------------
void
Semaphore::V()
{
Thread *thread;
IntStatus oldLevel = interrupt->SetLevel(IntOff); //禁用中断
thread = (Thread *)queue->Remove();
if (thread != NULL) // make thread ready, consuming the V immediately
scheduler->ReadyToRun(thread);
value++;
(void) interrupt->SetLevel(oldLevel); //恢复中断
}
Lock::Lock(char* debugName) //initialize lock to be FREE
{
name = debugName;
HoldThread = new Thread("HoldThread");
Hold = 0;
threadnum = 0;
semaphore = new Semaphore("locksem",0);
}
Lock::~Lock() //析构函数
{
delete HoldThreak;
delete semaphore;
}
void
Lock::Acquire() //wait until the lock is FREE, then set it to BUSY
{
ASSERT( !isHeldByCurrentThread ); //check the lock if FREE
IntStatus oldL = interrupt->SetLevel(IntOff); //禁用中断
while ( Hold )
semaphore->P();
HoldThread = currentThread;
Hold = 1;
(void) interrupt->SetLevel(oldL); //恢复中断
}
void
Lock::Release() //set lock to be FREE, waking up a thread waiting
{
ASSERT( isHeldByCurrentThread()); //check the lock if BUSY
IntStatus oldL = interrupt->SetLevel(IntOff); //禁用中断
HoldThread = NULL;
Hold = 0;
semaphore->V();
(void) interrupt->SetLevel(oldL); //恢复中断
}
bool
isHeldByCurrentThread()
{
if ( HoldThread == currentThread && Hold )
return true;
else
return false;
}
Condition::Condition(char* debugName) //initialize condition to "no one waiting"
{
name = debugName;
semaphore = new Semaphore("Conditionsem",0);
}
Condition::~Condition()
{
delete semaphore;
}
void
Condition::Wait(Lock* conditionLock)
//release the lock, relinquish the CPU until signaled,then re-acquire the lock
{
ASSERT( conditionLock->isHeldByCurrentThread()); //check the lock if held
IntStatus oldL = interrupt->SetLevel(IntOff); //禁用中断
conditionLock->Release();
semaphore->P();
threadnum++;
conditionLock->Acquire();
(void) interrupt->SetLever(oldL); //恢复中断
}
void
Condition::Signal() //wake up a thread,if there are any waiting on the condition
{
ASSERT( conditionLock->isHeldByCurrentThread());
IntStatus oldLeve = interrupt->SetLevel(IntOff);
if ( threadnum > 0 )
{
semaphore->V();
threadnum--;
}
(void) interrupt->SetLevel(oldLeve);
}
void
Condition::Broadcast() //wake up all threads waiting on the condition
{
ASSERT( conditionLock->isHeldByCurrentThread());
IntStatus odlLeve = interrupt->SetLevel(IntOff);
while ( threadnum > 0 )
{
semaphore->V();
threadnum--;
}
(void) interrupt->SetLevel(oldLeve);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -