cs 423 operating system design: synchronization · synchronization roadmap 14 shared objects...

of 37/37
CS423: Operating Systems Design Professor Adam Bates Fall 2018 CS 423 Operating System Design: Synchronization

Post on 20-Jul-2020

1 views

Category:

Documents

0 download

Embed Size (px)

TRANSCRIPT

  • CS423: Operating Systems Design

    Professor Adam BatesFall 2018

    CS 423 
Operating System Design:

    Synchronization

  • CS 423: Operating Systems Design 2

    • Learning Objectives: • Understand different primitives for synchronization at

    the operating system layer • Announcements:

    • C4 weekly summaries! Due Friday (any time zone) • MP1 is out! Due Feb 20 (any time zone)• CS Instructional Cloud is back online

    Goals for Today

    Reminder: Please put away devices at the start of class

  • CS423: Operating Systems Design

    MP1: Error check copy_*_user?

    3

    https://elixir.bootlin.com/linux/latest/source/include/linux/uaccess.h#L152

  • CS423: Operating Systems Design

    Synchronization Motivation

    4

    •  Whenthreadsconcurrentlyread/writesharedmemory,programbehaviorisundefined– Twothreadswritetothesamevariable;whichoneshouldwin?

    •  Threadscheduleisnon-determinis>c– Behaviorchangeswhenre-runprogram

    •  Compiler/hardwareinstruc>onreordering•  Mul>-wordopera>onsarenotatomic

  • CS423: Operating Systems Design

    Can this panic?

    5

    Thread1p=someComputa1on();pIni1alized=true;

    Thread2while(!pIni1alized);q=someFunc1on(p);if(q!=someFunc1on(p))panic

  • CS423: Operating Systems Design

    Why Reordering?

    6

    •  Whydocompilersreorderinstruc2ons?–  Efficientcodegenera2onrequiresanalyzingcontrol/datadependency

    –  Ifvariablescanspontaneouslychange,mostcompilerop2miza2onsbecomeimpossible

    •  WhydoCPUsreorderinstruc2ons?– Writebuffering:allownextinstruc2ontoexecutewhilewriteisbeingcompleted

    Fix:memorybarrier–  Instruc2ontocompiler/CPU– Allopsbeforebarriercompletebeforebarrierreturns– NoopaJerbarrierstartsun2lbarrierreturns

  • CS423: Operating Systems Design

    Too Much Milk!

    7

    PersonA PersonB

    12:30 Lookinfridge.Outofmilk.

    12:35 Leaveforstore.

    12:40 Arriveatstore. Lookinfridge.Outofmilk.

    12:45 Buymilk. Leaveforstore.

    12:50 Arrivehome,putmilkaway. Arriveatstore.

    12:55 Buymilk.

    1:00 Arrivehome,putmilkaway.Ohno!

  • CS423: Operating Systems Design

    Too Much Milk!

    8

    SOLUTION

    Make your own oat milk at home

    srsly tho — https://minimalistbaker.com/make-oat-milk/

  • CS423: Operating Systems Design

    Definitions

    9

    Racecondi*on:outputofaconcurrentprogramdependsontheorderofopera1onsbetweenthreads

    Mutualexclusion:onlyonethreaddoesapar1cularthingata1me–  Cri*calsec*on:pieceofcodethatonlyonethreadcanexecuteatonce

    Lock:preventsomeonefromdoingsomething–  Lockbeforeenteringcri1calsec1on,beforeaccessingshareddata

    –  Unlockwhenleaving,a=erdoneaccessingshareddata–  Waitiflocked(allsynchroniza1oninvolveswai1ng!)

  • CS423: Operating Systems Design

    Too Much Milk, Try #1

    10

    •  Correctnessproperty– Someonebuysifneeded(liveness)– Atmostonepersonbuys(safety)

    •  Try#1:leaveanoteif(!note)if(!milk){

    leavenotebuymilkremovenote}

  • CS423: Operating Systems Design 11

    ThreadAleavenoteAif(!noteB){if(!milk)buymilk}removenoteA

    ThreadBleavenoteBif(!noteA){if(!milk)buymilk}removenoteB

    Too Much Milk, Try #2

  • CS423: Operating Systems Design

    Too Much Milk, Try #3

    12

    ThreadAleavenoteAwhile(noteB)//Xdonothing;if(!milk)buymilk;removenoteA

    ThreadBleavenoteBif(!noteA){//Yif(!milk)buymilk}removenoteB

    CanguaranteeatXandYthateither:(i)  Safeformetobuy(ii) Otherwillbuy,oktoquit

  • CS423: Operating Systems Design

    Takeaways

    13

    •  Solu%oniscomplicated– “obvious”codeo5enhasbugs

    •  Moderncompilers/architecturesreorderinstruc%ons– Makingreasoningevenmoredifficult

    •  Generalizingtomanythreads/processors– Evenmorecomplex:seePeterson’salgorithm

  • CS423: Operating Systems Design

    Synchronization Roadmap

    14

    Shared Objects

    Synchronization Variables

    Atomic Instructions

    Hardware

    Interrupt Disable

    Bounded Buffer

    Multiple Processors

    Semaphores Locks

    Test-and-Set

    Barrier

    Hardware Interrupts

    Condition Variables

    Concurrent Applications

  • CS423: Operating Systems Design

    Locks

    15

    •  Lock::acquire– waitun0llockisfree,thentakeit

    •  Lock::release–  releaselock,wakingupanyonewai0ngforit

    1.  Atmostonelockholderata0me(safety)2.  Ifnooneholding,acquiregetslock(progress)3.  Ifalllockholdersfinishandnohigherpriority

    waiters,waitereventuallygetslock(progress)

  • CS423: Operating Systems Design

    Why only Acquire/Release?

    16

    Why can’t we have an “Ask if Lock is Free” function?

  • CS423: Operating Systems Design 17

    Too Much Milk, Try #4

    Locksallowconcurrentcodetobemuchsimpler:lock.acquire();if(!milk)buymilklock.release();

  • CS423: Operating Systems Design

    Ex: Lock Malloc/Free

    18

    char*malloc(n){heaplock.acquire();p=allocatememoryheaplock.release();returnp;}

    voidfree(char*p){heaplock.acquire();putpbackonfreelistheaplock.release();}

  • CS423: Operating Systems Design

    Rules for Using Locks

    19

    •  Lockisini)allyfree•  Alwaysacquirebeforeaccessingshareddatastructure–  Beginningofprocedure!

    •  Alwaysreleasea

  • CS423: Operating Systems Design

    Will this Code Work?

    20

    if(p==NULL){lock.acquire();if(p==NULL){p=newP();}lock.release();}usep->field1

    newP(){p=malloc(sizeof(p));p->field1=…p->field2=…returnp;}

  • CS423: Operating Systems Design

    Ex: Thread-Safe Bounded Queue

    21

    tryget(){item=NULL;lock.acquire();if(front<tail){item=buf[front%MAX];front++;}lock.release();returnitem;}

    tryput(item){lock.acquire();if((tail–front)<size){buf[tail%MAX]=item;tail++;}lock.release();}

    IniJally:front=tail=0;lock=FREE;MAXisbuffercapacity

  • CS423: Operating Systems Design

    Question(s)

    22

    •  IftrygetreturnsNULL,doweknowthebufferisempty?

    •  Ifwepolltrygetinaloop,whathappenstoathreadcallingtryput?

  • CS423: Operating Systems Design

    Condition Variables• Waiting inside a critical section

    • Called only when holding a lock

    • CV::Wait — atomically release lock and relinquish processor

    • Reacquire the lock when wakened

    • CV::Signal — wake up a waiter, if any

    • CV::Broadcast — wake up all waiters, if any

    23

  • CS423: Operating Systems Design

    Condition Variables

    24

    methodThatWaits() { lock.acquire(); // Read/write shared state

    while (!testSharedState()) { cv.wait(&lock); }

    // Read/write shared state lock.release();}

    methodThatSignals() { lock.acquire(); // Read/write shared state // If testSharedState is now true cv.signal(&lock);

    // Read/write shared state lock.release();}

  • CS423: Operating Systems Design 25

    Ex: Bounded Queue w/ CV

    get() { lock.acquire(); while (front == tail) { empty.wait(lock); } item = buf[front % MAX]; front++; full.signal(lock); lock.release(); return item;}

    put(item) { lock.acquire(); while ((tail – front) == MAX) { full.wait(lock); } buf[tail % MAX] = item; tail++; empty.signal(lock); lock.release();}

    Initially: front = tail = 0; MAX is buffer capacity empty/full are condition variables

  • CS423: Operating Systems Design

    Pre/Post Conditions

    26

    • What is state of the bounded buffer at lock acquire? • front = tail

    • These are also true on return from wait

    • And at lock release

    • Allows for proof of correctness

  • CS423: Operating Systems Design

    Pre/Post Conditions

    27

    methodThatWaits() { lock.acquire(); // Pre-condition: State is consistent

    // Read/write shared state

    while (!testSharedState()) { cv.wait(&lock); } // WARNING: shared state may // have changed! But // testSharedState is TRUE // and pre-condition is true

    // Read/write shared state lock.release();}

    methodThatSignals() { lock.acquire(); // Pre-condition: State is consistent

    // Read/write shared state // If testSharedState is now true cv.signal(&lock);

    // NO WARNING: signal keeps lock

    // Read/write shared state lock.release();}

  • CS423: Operating Systems Design

    Condition Variables

    28

    • ALWAYS hold lock when calling wait, signal, broadcast • Condition variable is sync FOR shared state • ALWAYS hold lock when accessing shared state

    • Condition variable is memoryless • If signal when no one is waiting, no op • If wait before signal, waiter wakes up

    • Wait atomically releases lock • What if wait, then release? • What if release, then wait?

  • CS423: Operating Systems Design

    Condition Variables

    29

    • When a thread is woken up from wait, it may not run immediately

    • Signal/broadcast put thread on ready list • When lock is released, anyone might acquire it

    • Wait MUST be in a loop while (needToWait()) { condition.Wait(lock); }

    • Simplifies implementation • Of condition variables and locks • Of code that uses condition variables and locks

  • CS423: Operating Systems Design

    Mesa vs. Hoare Semantics• Mesa

    • Signal puts waiter on ready list

    • Signaller keeps lock and processor

    • Hoare

    • Signal gives processor and lock to waiter

    • When waiter finishes, processor/lock given back to signaller

    • Nested signals possible!

    30

  • CS423: Operating Systems Design

    FIFO Bounded Queue(Hoare Semantics)

    31

    get() { lock.acquire(); if (front == tail) { empty.wait(lock); } item = buf[front % MAX]; front++; full.signal(lock); lock.release(); return item;}

    put(item) { lock.acquire(); if ((tail – front) == MAX) { full.wait(lock); } buf[last % MAX] = item; last++; empty.signal(lock); // CAREFUL: someone else ran lock.release();}

    Initially: front = tail = 0; MAX is buffer capacity empty/full are condition variables

  • CS423: Operating Systems Design

    FIFO Bounded Queue(Mesa Semantics)

    • Create a condition variable for every waiter

    • Queue condition variables (in FIFO order)

    • Signal picks the front of the queue to wake up

    • CAREFUL if spurious wakeups!

    •Easily extends to case where queue is LIFO, priority, priority donation, …

    •With Hoare semantics, not as easy

    32

  • CS423: Operating Systems Design

    Synchronization Best Practices

    33

    • Identify objects or data structures that can be accessed by multiple threads concurrently

    • Add locks to object/module • Grab lock on start to every method/procedure • Release lock on finish

    • If need to wait • while(needToWait()) { condition.Wait(lock); } • Do not assume when you wake up, signaller just ran

    • If do something that might wake someone up • Signal or Broadcast

    • Always leave shared state variables in a consistent state • When lock is released, or when waiting

  • CS423: Operating Systems Design

    Remember the rules…• Use consistent structure

    • Always use locks and condition variables

    • Always acquire lock at beginning of procedure, release at end

    • Always hold lock when using a condition variable

    • Always wait in while loop

    • Never spin in sleep()

    34

  • CS 423: Operating Systems Design

    Implementing Synchronization

    35

    Interrupt Disable Atomic Read/Modify/Write Instructions

    Hardware InterruptsMultiple Processors

    Semaphores Locks Condition Variables

    Concurrent Applications

  • CS423: Operating Systems Design

    • Take 1: using memory load/store

    • See too much milk solution/Peterson’s algorithm

    • Take 2:

    • Lock::acquire()

    • Lock::release()

    36

    Implementing Synchronization

  • CS423: Operating Systems Design

    Lock Implementation for Uniprocessor?

    37

    Lock::acquire() { disableInterrupts(); if (value == BUSY) { waiting.add(myTCB); myTCB->state = WAITING; next = readyList.remove(); switch(myTCB, next); myTCB->state = RUNNING; } else { value = BUSY; } enableInterrupts(); }

    Lock::release() { disableInterrupts(); if (!waiting.Empty()) { next = waiting.remove(); next->state = READY; readyList.add(next); } else { 
 value = FREE;

    } enableInterrupts(); }