28 februarie 2015

Nachos: Acquire & Release implementation for Lock

Adaptata la solutia de aici & aici.

#define FREE false
#define BUSY true

Lock::Lock(char* debugName)  {
    name=debugName;
    value=FREE;
    queue=new List;
}

void Lock::Acquire() {
    IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
    // if lock not available...
    if (value == BUSY) {
queue->Append (currentThread); // add to queue & go to sleep
currentThread->Sleep();
    }
    // here thread is waken up, the real acquire begins
    value=BUSY;
held=currentThread;  // save the thread which got the lock
    interrupt->SetLevel(oldLevel); // re-enable interrupts
}

void Lock::Release() {
    IntStatus oldLevel = interrupt->SetLevel(IntOff);
    Thread* thread = (Thread *) queue->Remove();
    if (held==currentThread) { // this is necessary to avoid a crazy thread releasing others
        if (thread!=NULL) {
            scheduler->ReadyToRun(thread);    // add it to ready queue
}
        else { // if queue is empty
           value=FREE;
        }
    }
    interrupt->SetLevel(oldLevel);
}


Meanings:
FREE : there is no other thread inside the Lock
BUSY: there is at least one thread either in the queue or in the process of acquiring


// there is a slightly equivalent solution
// however I think the previous one is more meaningful
// variable held is kind of useless here

void Lock::Acquire() {
    IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
    // if lock not available...
    while (value == BUSY) {
queue->Append (currentThread); // add to queue & go to sleep
currentThread->Sleep();
    }
    // here thread is waken up, the real acquire begins
    value=BUSY; 
    held=currentThread;
    interrupt->SetLevel(oldLevel); // re-enable interrupts
}

void Lock::Release() {
    IntStatus oldLevel = interrupt->SetLevel(IntOff);
    if (held==currentThread) {
    Thread* thread = (Thread *) queue->Remove();
        if (thread!=NULL) {
            scheduler->ReadyToRun(thread);    // add it to ready queue
}
        value=FREE;
    }
    interrupt->SetLevel(oldLevel);
}

-------------------------

Some differences Lock vs. Semaphore
* Semaphore has a counter of resources whereas Lock is either busy or free. Lock is used for Mutual Exclusion only, i.e, only one thread can access the shared resources at any time.
* Lock has owner whereas Semaphore does not have any owner.
* Lock does not track number of resources/ number of waiting tasks, whereas Semaphore does.
* Only the thread which is the owner of the Lock can Release the lock on resource. Semaphore can be accessed by any thread.
* Semaphore is a shared object while Lock is not.

Niciun comentariu: