📄 synch-sleep.cc
字号:
// synch.cc
// Routines for synchronizing threads. Three kinds of
// synchronization routines are defined here: semaphores, locks
// and condition variables (the implementation of the last two
// are left to the reader).
//
// Any implementation of a synchronization routine needs some
// primitive atomic operation. We assume Nachos is running on
// a uniprocessor, and thus atomicity can be provided by
// turning off interrupts. While interrupts are disabled, no
// context switch can occur, and thus the current thread is guaranteed
// to hold the CPU throughout, until interrupts are reenabled.
//
// Because some of these routines might be called with interrupts
// already disabled (Semaphore::V for one), instead of turning
// on interrupts at the end of the atomic operation, we always simply
// re-set the interrupt state back to its original value (whether
// that be disabled or enabled).
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved. See copyright.h for copyright notice and limitation
// of liability and disclaimer of warranty provisions.
#include "copyright.h"
#include "synch-sleep.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); // disable interrupts
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); // re-enable interrupts
}
//----------------------------------------------------------------------
// 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);
}
// Dummy functions -- so we can compile our later assignments
// Note -- without a correct implementation of Condition::Wait(),
// the test case in the network assignment won't work!
//构造函数,初始化变量
Lock::Lock(char* debugName)
{
name = debugName;
lock_flag = FREE;
waitlock_queue = new List();
haslock_thread = NULL;
}
//析构函数
Lock::~Lock()
{
delete waitlock_queue;
}
//当前线程获得锁的函数
void Lock::Acquire()
{
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
while(lock_flag == BUSY) //wait until the lock is FREE
{
waitlock_queue->Append( (void *)currentThread );//将当前线程插入到等待队列中
currentThread->Sleep(); //当前线程进入睡眠
}
lock_flag = BUSY; //then set it to BUSY
haslock_thread = currentThread;//当前线程拥有锁
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
//释放锁
void Lock::Release()
{
Thread *ready_thread;
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
ASSERT(isHeldByCurrentThread() );//检查当前线程是否拥有锁
lock_flag = FREE; //set lock to be FREE
haslock_thread = NULL;
ready_thread = (Thread *)waitlock_queue->Remove(); //waking up a thread waiting in Acquire
if(ready_thread != NULL)
scheduler->ReadyToRun(ready_thread);
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
//检查当前线程是否拥有锁
bool Lock::isHeldByCurrentThread()
{
if( lock_flag == BUSY && haslock_thread == currentThread )
return true;
else
return false;
}
//构造函数,初始化变量
Condition::Condition(char* debugName)
{
name = debugName;
waitcondition_queue = new List();
}
Condition::~Condition()
{
delete waitcondition_queue;
}
//线程等待条件变量
void Condition::Wait(Lock* conditionLock)
{
Thread *thread;
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
thread = currentThread;
ASSERT(conditionLock->isHeldByCurrentThread() );
conditionLock->Release(); //release the lock
waitcondition_queue->Append((void *)thread);
thread->Sleep(); //进入睡眠状态,relinquish the CPU
conditionLock->Acquire(); //re-acquire the lock
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
//唤醒一个等待该条件变量的线程
void Condition::Signal(Lock* conditionLock)
{
Thread* thread_ready;
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
thread_ready = (Thread *)waitcondition_queue->Remove();
ASSERT(conditionLock->isHeldByCurrentThread() );
if(thread_ready != NULL)
scheduler->ReadyToRun(thread_ready);
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
//唤醒所有等待该条件的线程
void Condition::Broadcast(Lock* conditionLock)
{
Thread *thread;
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
while( (thread = (Thread *)waitcondition_queue->Remove() ) != NULL)
scheduler->ReadyToRun(thread);
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -