Lecture 15 - Midterm Review
Some tips:
- Explain what you're doing
- Use context clues
- etc.
What will be covered:
- Introduction/History of OS's
- What is an OS? Resource Management (Asgn1) and Priviledge
- Independent Threads of Control (Asgn2) and Concurrency
- More on Synchronization Mechanisms (critical section, scheduling, etc.), Deadlock (Asgn3)
- Architecture of IO Systems
Reviewed Topics
Timesharing is when you share time between threads, specifically:
- when one blocks
- when your turn is up (you've been working for too much)
Because of context switching, it can't improve your efficiency (you're adding more instructions), but it does improve your response time (you can interact with each program eventually). Your quantum of time should be long enough such that you can wait that long for another process to return to this one (and more if there's many threads).
Also looking at question 35 on the MT, we found that making lwp_fork
is impossible to make since if you just copied the stacks, the pointers (memory addresses) would point to the original stack, which isn't the intended idea.
For question 36, you can do:
typedef int Semaphore;
Semaphore s = 1;
void DOWN(Semaphore *s)
{
while(*s == 0) lwp_yield(); // wait for your turn
*(s)--; // decrement
}
void UP(Semaphore *s)
{
*(s)++; // increment. Ensures its non-zero.
}
- Is it safe (does it work)? Yes since it's round robin because no thread can go on until it's safe for it to go on (and only one thread can).
- Is there starvation/deadlock? Possibly if the user doesn't use the calls correctly.
The better way would be to Queue
up your thread id, then to only yield while it is not your turn. Change UP
to be:
//...
void DOWN(Semaphore *s)
{
enqueue(lwp_gettid(), *q); // stick yourself on the queue
while(*s != 0 || head(*q) != lwp_gettid()) lwp_yield(); // wait for the semaphore OR it's not your turn.
*(s)--; // decrement
}
//...