⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 synch-sleep.cc

📁 本次实验的目的在于将nachos中的锁机制和条件变量的实现补充完整
💻 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 + -