When multiple threads are trying to access the same data it is important to enforce mutual exclusion. If we didn’t we would get some really funky outcomes that we really don’t want. One way to force that only one thread can access this data or data structure is a structure called a lock. For example:


Thread A {
int x = remove_from_front_of_queue (someQueue);}
Thread B {int y = put_in_queue (someQueue,item);}

By not forcing mutual exclusion we can get some messy results. I will be doing an implementation of locks in os161

Our Structure of the lock, we keep track of the name and the current thread that owns the lock


struct lock {

char *name;

volatile struct thread *owner; //thread currently owning the lock

};

/*lock_create will create the lock and return it when finished*/struct lock * lock_create(const char*name) {

struct lock *lock;

lock = kmalloc(sizeof(struct lock));

if (lock == NULL) {

return NULL;

}

lock->name = kstrdup(name);

if (lock->name == NULL) {

kfree(lock);

return NULL;

}

lock->owner=NULL;

return lock;

}

/* just freeing our memory we have allocated and destroying the lock */void lock_destroy(struct lock *lock) {

assert(lock != NULL);

kfree(lock->name);

kfree(lock);

}

/* when a thread wants to acquire the lock */void lock_acquire(structlock *lock) {

/* we must make sure interupts are turned off and the lock exists */

int spl; assert(lock !=NULL);

spl splhigh();

/* when a lock is already acquired we cannot proceed so the thread must sleep on the lock until the owner is

finished when the thread is woken up it will continue to call the while loop to check again if the lock is acquired

we could have multiple threads all trying to acquire the lock this is why we have a while loop we can then turn interrupts on again*/

while(lock->owner !=NULL) thread_sleep(lock); // in thread_sleep keep track of this lock and the address its sleeping on

lock->owner=curthread; // curthread is a global variable in os161 which holds the current thread running

splx(spl);

}

/* when a thread is finished with a lock it will call lock_release the thread calling this must be the owner of the lock */void lock_release(struct lock *lock) {

int spl=splhigh();

assert(lock !=NULL);

assert(curthread==lock->owner);//check that we own lock

lock->owner=NULL;

thread_wakeup_single(lock);// must implement – loop through the sleeping threads and check if a thread is sleeping on this lock if so wake it up. 

splx(spl);

}