30
EECS 482 Introduction to Operating Systems Winter 2018 Harsha V. Madhyastha

EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

  • Upload
    others

  • View
    3

  • Download
    0

Embed Size (px)

Citation preview

Page 1: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

EECS 482Introduction to Operating

Systems

Winter 2018

Harsha V. Madhyastha

Page 2: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Recap: Synchronization

January 17, 2018 EECS 482 – Lecture 4 2

Code

Stack (T1)

Heap

Stack (T2)

Stack (T3)

Avoid race conditions via mutual exclusion

Criticalsections

Page 3: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

“Too much milk” Takeaways● Feasible to synchronize via loads/stores, but …

◆ Complex◆ Busy waiting

3

Bobleave noteBobwhile (noteAlice) {

do nothing}if (noMilk) {

buy milk}remove noteBob

Aliceleave noteAlice

if (no noteBob) {if (noMilk) {

buy milk}

}remove noteAlice

EECS 482 – Lecture 4January 17, 2018

Want simple to use and efficientsolutions that are broadly applicable

Page 4: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

“Too much milk” Takeaways● Locks simplify mutual exclusion

◆ Acquire lock at start of critical section◆ Release lock at end of critical section

● No busy waiting in user-level code

4EECS 482 – Lecture 4January 17, 2018

Bobmilk.lock()if (noMilk) {

buy milk}milk.unlock()

Alicemilk.lock()if (noMilk) {

buy milk}milk.unlock()

Page 5: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

“Too much milk” Takeaways● For efficiency, minimize size of critical section

5EECS 482 – Lecture 4January 17, 2018

note.lock()if (noNote) {

leave notenote.unlock()if (noMilk) {

buy milk}note.lock()remove notenote.unlock()

}else {

note.unlock()}

Page 6: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Shared queuestruct node {

int data

struct node *next

}

struct queue {

struct node *head

}

● Empty list

● List with one node

January 17, 2018 EECS 482 – Lecture 4 6

head

NULL

head

NULL

Page 7: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Shared queueenqueue(new_element) {

// find tail of queuefor (ptr = head; ptr->next != NULL; ptr = ptr->next) {}

// add new element to tail of queueptr->next = new_element;new_element->next = NULL;

}

dequeue() {element = NULL;// if something on queue, then remove itif (head->next != NULL) {

element = head->next;head->next = head->next->next;

}return(element);

}

Problems if two threads manipulate queue at same time?

7EECS 482 – Lecture 4January 17, 2018

head

NULL

T1’s ptr

T2’s ptr

Page 8: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Shared queue with locksenqueue(new_element) {

qmutex.lock();// find tail of queuefor (ptr=head; ptr->next != NULL; ptr = ptr->next) {}

// add new element to tail of queueptr->next = new_element;new_element->next = NULL;qmutex.unlock();

}dequeue() {

qmutex.lock();element = NULL;// if something on queue, then remove itif (head->next != NULL) {

element = head->next;head->next = head->next->next;

}qmutex.unlock();return(element);

} 8EECS 482 – Lecture 4January 17, 2018

Page 9: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Thread-safety invariants● When can enqueue() unlock?

◆ Must restore queue to a stable state● Stable state is called an invariant

◆ Condition that is “always” true for the linked list◆ Example: each node appears exactly once

● Is invariant ever allowed to be false?◆ Hold lock whenever you’re manipulating shared data,

i.e., whenever you’re breaking the invariant● What if you’re only reading the data?

9EECS 482 – Lecture 4January 17, 2018

Page 10: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Don’t break assumptionsenqueue(new_element) {

lock// find tail of queue

for (ptr=head; ptr->next != NULL; ptr = ptr->next) {}

unlocklock// add new element to tail of queue

ptr->next = new_element;

new_element->next = NULL;unlock

}

Does this work?

10EECS 482 – Lecture 4January 17, 2018

Page 11: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Fine-grained locking● Instead of one lock for entire queue, use one lock per node

◆ Why would you want to do this?

● Lock each node as the queue is traversed, then release as soon as it’s safe, so other threads can also access the queue

1. lock A2. get pointer to B3. unlock A4. lock B5. read B6. unlock B

What problems could occur?How to fix?

11

A B C NULL

EECS 482 – Lecture 4January 17, 2018

Another thread could lock A anddequeue all nodes

Page 12: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

How to fix?● lock A● get pointer to B● lock B● unlock A● read B● unlock B

● Hand-over-hand locking◆ Lock next node before releasing last node◆ Used in Project 4

12EECS 482 – Lecture 4January 17, 2018

Page 13: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Announcements

● Attempt homework questions before discussion section on Friday

● Group declaration due on Monday (Jan 22)

● Read handout for Project 1 and tried autograder?◆ After today’s lecture, we’ll have covered all material to

do the project

January 17, 2018 EECS 482 – Lecture 4 13

Page 14: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Ordering constraints● What if you wanted dequeue() to wait if the

queue is empty?dequeue() {

qmutex.lock();

// wait for queue to be non-empty

qmutex.unlock();while(head->next == NULL);qmutex.lock();// remove element

element = head->next;

head->next = head->next->next;

qmutex.unlock();

return(element);

}14EECS 482 – Lecture 4January 17, 2018

Does this work?

Page 15: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Ordering constraintsdequeue() {

qmutex.lock();

// wait for queue to be non-empty

while(head->next == NULL) {qmutex.unlock(); qmutex.lock();

}// remove element

element = head->next;

head->next = head->next->next;

qmutex.unlock();

return(element);

}

15EECS 482 – Lecture 4January 17, 2018

Does this work?

Page 16: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Avoiding busy waiting● Have waiting dequeuer “go to sleep”

◆ Put dequeuer onto a waiting list, then go to sleep

if (queue is empty) {

add myself to waiting list

go to sleep

}

◆ enqueuer wakes up sleeping dequeuer

16EECS 482 – Lecture 4January 17, 2018

Page 17: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Avoiding busy waitingenqueue()

lock

add new item to tail of queue

if (dequeuer is waiting) {take waiting dequeuer off waiting listwake up dequeuer

}unlock

dequeue()lock

if (queue is empty) {add myself to waiting listsleep

}remove item from queue

unlock17EECS 482 – Lecture 4January 17, 2018

Does this work?

Page 18: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Two types of synchronization● Mutual exclusion

◆ Ensures that only one thread is in critical section◆ “Not at the same time”◆ lock/unlock

● Ordering constraints◆ One thread waits for another to do something◆ “Before after”◆ E.g., dequeuer must wait for enqueuer to add

something to queue

18EECS 482 – Lecture 4January 17, 2018

Locks

Condition variables

Page 19: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Condition variables● Enable thread to sleep inside a critical section, by

◆ Releasing lock◆ Putting thread onto waiting list◆ Going to sleep◆ After being woken, call lock()

● Each condition variable has a list of waiting threads◆ These threads are “waiting on that condition”

● Each condition variable is associated with a lock

19

atomic

EECS 482 – Lecture 4January 17, 2018

Page 20: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Condition variables interface● wait(mutex)

◆ Atomically release lock, add thread to waiting list, sleep◆ Thread must hold the lock when calling wait()◆ Should thread re-establish invariant before calling wait()?

● signal()◆ Wake up one thread waiting on this condition variable

● broadcast()◆ Wake up all threads waiting on this condition variable

● If no thread is waiting, signal/broadcast does nothing

January 17, 2018 EECS 482 – Lecture 4 20

Page 21: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Thread-safe queue with no busy waiting

enqueue()lock

add new element to tail of queue

if (dequeuer is waiting) {take waiting dequeuer off waiting listwake up deqeuer

}unlock

dequeue()lock

if (queue is empty) {add myself to waiting listsleep

}remove item from queue

unlock

return removed item21EECS 482 – Lecture 4January 17, 2018

Page 22: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Thread-safe queue with condition variables

cv queueCV;enqueue() {

queueMutex.lock()

add new element to tail of queue

queueCV.signal()queueMutex.unlock()

}

dequeue() {

queueMutex.lock()

if (queue is empty) {queueCV.wait();

}remove item from queue

queueMutex.unlock()

return removed item

}

22EECS 482 – Lecture 4January 17, 2018

This is broken!

unlockput thread on wait queuego to sleepre-acquire lock

atomic

Page 23: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Thread-safe queue with condition variables

cv queueCV;enqueue() {

queueMutex.lock()

find tail of queue

add new element to tail of queue

queueCV.signal()queueMutex.unlock()

}

dequeue() {queueMutex.lock()

while (queue is empty) {queueCV.wait();

}remove item from queue

queueMutex.unlock()

return removed item

}23EECS 482 – Lecture 4January 17, 2018

Always use while!

Page 24: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Conditional variables eliminate busy waiting

lock

. . .

while (queue is empty) {

unlocklock

}

. . .

unlock

lock

. . .

while (queue is empty) {

cv.wait}

. . .

unlock

January 17, 2018 EECS 482 – Lecture 4 24

Page 25: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Monitors● Combine two types of synchronization

◆ Locks for mutual exclusion◆ Condition variables for ordering constraints

● A monitor = a lock + the condition variables associated with that lock

25EECS 482 – Lecture 4January 17, 2018

Page 26: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Mesa vs. Hoare monitors● Mesa monitors

◆ When waiter is woken, it must contend for the lock◆ So it must re-check the condition it was waiting for

● What would be required to ensure condition is met when waiter starts running again?

● Hoare monitors◆ Special priority to woken-up waiter◆ Signaling thread immediately gives up lock◆ Signaling thread reacquires lock after waiter unlocks

26EECS 482 – Lecture 4January 17, 2018

Page 27: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Mesa vs. Hoare monitors● Mesa monitors

◆ When waiter is woken, it must contend for the lock◆ So it must re-check the condition it was waiting for

● What would be required to ensure condition is met when waiter starts running again?

● Hoare monitors◆ Special priority to woken-up waiter◆ Signaling thread immediately gives up lock◆ Signaling thread reacquires lock after waiter unlocks

27EECS 482 – Lecture 4January 17, 2018

We (and most OSes) use Mesa monitors

Waiter is solely responsible for ensuring condition is met

Page 28: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Programming with monitors1. List the shared data needed for the problem2. Assign locks to each group of shared data

» Tradeoff between complexity and concurrency3. List the before-after conditions for the problem4. Assign condition variable to each condition

» Associate with lock protecting data used for condition5. Add lock/unlock around all accesses to shared data

» Remember invariant6. Add while (!cond) { wait } where condition must hold7. Add signal/broadcast after possibly making cond true

January 17, 2018 EECS 482 – Lecture 4 28

Page 29: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Typical monitor code

lock

while (!condition) {

wait

}

do stuff

signal about the stuff you did

unlock

January 17, 2018 EECS 482 – Lecture 4 29

Page 30: EECS 482 Introduction to Operating Systems€¦ · Harsha V. Madhyastha. Recap: Synchronization January 17, 2018 EECS 482 –Lecture 4 2 Code Stack (T1) Heap Stack (T2) Stack (T3)

Project 1

● Now, you should know everything you need to know to do project 1

● Due in 12 days (on Jan 29th)

January 17, 2018 EECS 482 – Lecture 4 30