I am working on a school project (explains my restrictions in the question). My question is how to implement locks without semaphores in NACHOS. Although a NACHOS specific answer would be great, what I am looking for is a push in the right direction. So far, from my understanding, monitors use locks which use semaphores (mutexes really). Initially we thought to replace semaphores with monitors to implement locks, however, that didn't make sense.
Asked
Active
Viewed 1,519 times
2
-
Are you allowed to disable interrupts? – templatetypedef Feb 16 '12 at 00:53
3 Answers
0
Lock can be implemented by Thread:Sleep.
class Lock {
public:
Lock(char* debugName); // initialize lock to be FREE
~Lock(); // deallocate lock
char* getName() { return name; } // debugging assist
void Acquire(); // these are the only operations on a lock
void Release(); // they are both *atomic*
bool isHeldByCurrentThread() { return (thread == currentThread); } // true if the current thread
// holds this lock. Useful for
// checking in Release, and in
// Condition variable ops below.
private:
char* name; // for debugging
// plus some other stuff you'll need to define
Thread *thread; //the thread who holds this lock
enum value {FREE, BUSY};
List *queue;
};
Lock::Lock(char* debugName):name(debugName), thread(NULL), value(FREE), queue(new List())
{ }
Lock::~Lock()
{
delete queue;
}
void Lock::Acquire()
{
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
if (value == BUSY) {
queue->Append((void *)currentThread);
currentThread->Sleep();
}
value = BUSY;
thread = currentThread;
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
void Lock::Release()
{
Thread *nextThread;
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
nextThread = (Thread *)queue->Remove();
if (nextThread != NULL) // make thread ready, consuming the V immediately
scheduler->ReadyToRun(nextThread);
value = FREE;
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}

Liu Shuo
- 11
- 3
0
At first check whether the current holder of the lock is the current thread or not. Then use interrupt on-off and sleep to achieve lock. After a thread wakes from sleep, it should again check whether the lock is busy or free, because waking up a thread only passes it to the ready queue. Some other thread may meanwhile acquire the lock again before this thread can acquire the lock.
void Lock::Acquire() {
ASSERT(!isHeldByCurrentThread()); // cannot acquire a lock twice
IntStatus oldLevel = interrupt->SetLevel(IntOff); // disable interrupts
while (freeOrBusy == 'b') {
queue->Append((void *)currentThread);
currentThread->Sleep();
}
freeOrBusy = 'b';
currentHolder = currentThread;
(void) interrupt->SetLevel(oldLevel); // re-enable interrupts
}
void Lock::Release() {
ASSERT(isHeldByCurrentThread());
IntStatus oldLevel = interrupt->SetLevel(IntOff);
freeOrBusy = 'f';
currentHolder = NULL;
Thread *thread = (Thread *)queue->Remove(); // "queue" is the list of threads waiting
if (thread != NULL) // make thread ready
scheduler->ReadyToRun(thread);
(void) interrupt->SetLevel(oldLevel);
}

Preetom Saha Arko
- 2,588
- 4
- 21
- 37
0
You might want to think about spin-locks which do busy-waiting and do not require semaphore.However in a uniprocessor spin-locks are not used.

vjain27
- 3,514
- 9
- 41
- 60