locks and semaphores - kth

161
Locks and semaphores Johan Montelius KTH 2021 1 / 40

Upload: others

Post on 10-Apr-2022

15 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Locks and semaphores - KTH

Locks and semaphores

Johan Montelius

KTH

2021

1 / 40

Page 2: Locks and semaphores - KTH

recap, what’s the problem:

# include <pthread .h>

volatile int count = 0;

void *hello(void *arg) {for(int i = 0; i < 10; i++) {

count ++;}

}

int main () {pthread_t p1 , p2;

pthread_create (&p1 , NULL , hello , NULL );pthread_create (&p2 , NULL , hello , NULL );

:}

2 / 40

Page 3: Locks and semaphores - KTH

Peterson’s algorithm

int request [2] = {0 ,0};int turn = 0;

int lock(int id) {

request [id] = 1;int other = 1-id;turn = other;

while ( request [other] == 1 && turn == other) {}; // spin

return 1;}

void release (int id) {request [id] = 0;

}

3 / 40

Page 4: Locks and semaphores - KTH

Total Store Order

P1 P2

4 / 40

Page 5: Locks and semaphores - KTH

Total Store Order

P1 P2

a b0 0

4 / 40

Page 6: Locks and semaphores - KTH

Total Store Order

P1 P2

a b0 0a = 1

1

4 / 40

Page 7: Locks and semaphores - KTH

Total Store Order

P1 P2

a b0 0a = 1 b = 1

1 1

4 / 40

Page 8: Locks and semaphores - KTH

Total Store Order

P1 P2

a b0 0a = 1 b = 1

read b read a

1 1

4 / 40

Page 9: Locks and semaphores - KTH

Total Store Order

P1 P2

a b0 0a = 1 b = 1

read b read a

0 01 1

4 / 40

Page 10: Locks and semaphores - KTH

atomic memory operations

All CPU:s provide several versions of atomic operations that both read and write to amemory element in one atomic operation.

test-and-set: swap i.e. read and write to a memory location, the simplestprimitivefetch-and-add/and/xor/... : update the value with a given operation, moreflexiblecompare-and-swap : if the memory location contains a specific value then swap

5 / 40

Page 11: Locks and semaphores - KTH

atomic memory operations

All CPU:s provide several versions of atomic operations that both read and write to amemory element in one atomic operation.

test-and-set: swap i.e. read and write to a memory location, the simplestprimitive

fetch-and-add/and/xor/... : update the value with a given operation, moreflexiblecompare-and-swap : if the memory location contains a specific value then swap

5 / 40

Page 12: Locks and semaphores - KTH

atomic memory operations

All CPU:s provide several versions of atomic operations that both read and write to amemory element in one atomic operation.

test-and-set: swap i.e. read and write to a memory location, the simplestprimitivefetch-and-add/and/xor/... : update the value with a given operation, moreflexible

compare-and-swap : if the memory location contains a specific value then swap

5 / 40

Page 13: Locks and semaphores - KTH

atomic memory operations

All CPU:s provide several versions of atomic operations that both read and write to amemory element in one atomic operation.

test-and-set: swap i.e. read and write to a memory location, the simplestprimitivefetch-and-add/and/xor/... : update the value with a given operation, moreflexiblecompare-and-swap : if the memory location contains a specific value then swap

5 / 40

Page 14: Locks and semaphores - KTH

try to lock by swap

int try(int *lock) {return __sync_val_compare_and_swap (lock , 0, 1);

}

pushq %rbpmovq %rsp , %rbpmovq %rdi , -8(% rbp)movq -8(% rbp), %rdxmovl $0 , %eaxmovl $1 , %ecxlock cmpxchgl %ecx , (% rdx)popq %rbpret

This is using GCC extensions to C, similar extensions available in all compilers.

6 / 40

Page 15: Locks and semaphores - KTH

try to lock by swap

int try(int *lock) {return __sync_val_compare_and_swap (lock , 0, 1);

}

pushq %rbpmovq %rsp , %rbpmovq %rdi , -8(% rbp)movq -8(% rbp), %rdxmovl $0 , %eaxmovl $1 , %ecxlock cmpxchgl %ecx , (% rdx)popq %rbpret

This is using GCC extensions to C, similar extensions available in all compilers.

6 / 40

Page 16: Locks and semaphores - KTH

try to lock by swap

int try(int *lock) {return __sync_val_compare_and_swap (lock , 0, 1);

}

pushq %rbpmovq %rsp , %rbpmovq %rdi , -8(% rbp)movq -8(% rbp), %rdxmovl $0 , %eaxmovl $1 , %ecxlock cmpxchgl %ecx , (% rdx)popq %rbpret

This is using GCC extensions to C, similar extensions available in all compilers.

6 / 40

Page 17: Locks and semaphores - KTH

a spin-lock

int lock(int *lock) {

while (try(lock) != 0) {}

return 1;}

void release (int *lock) {*lock = 0;

}

7 / 40

Page 18: Locks and semaphores - KTH

a spin-lock

int lock(int *lock) {

while (try(lock) != 0) {}

return 1;}

void release (int *lock) {*lock = 0;

}

7 / 40

Page 19: Locks and semaphores - KTH

finally - we’re in control

int global = 0;

int count = 0;

void *hello(void *name) {for(int i = 0; i < 10; i++) {

lock (& global );count ++;release (& global );

}}

try using taskset -c 1 ./spin 10000

8 / 40

Page 20: Locks and semaphores - KTH

spin locks

9 / 40

Page 21: Locks and semaphores - KTH

spin locks

9 / 40

Page 22: Locks and semaphores - KTH

avoid spinning

We need to talk to the operating system.

void lock(int *lock) {

while (try(lock) != 0) {sched_yield (); // in Linux

}

}

10 / 40

Page 23: Locks and semaphores - KTH

avoid spinning

We need to talk to the operating system.

void lock(int *lock) {

while (try(lock) != 0) {sched_yield (); // in Linux

}

}

10 / 40

Page 24: Locks and semaphores - KTH

Wham - .....For how long should we sleep?

We would like to be woken up as the lock is released - before you go-go.

11 / 40

Page 25: Locks and semaphores - KTH

Wham - .....For how long should we sleep?

We would like to be woken up as the lock is released - before you go-go.

11 / 40

Page 26: Locks and semaphores - KTH

Wham - .....For how long should we sleep?

We would like to be woken up as the lock is released - before you go-go.11 / 40

Page 27: Locks and semaphores - KTH

a detour in Sun Solaris

void lock( lock_t *m) {

while (try(m->guard) != 0) {};

if(m->flag == 0) {m->flag = 1;m->guard = 0;

} else {queue_add (m->queue , gettid ());m->guard = 0;park ();

}

void unlock ( lock_t *m) {

while (try(m->guard) != 0) {};

if(empty(m->queue )) {m->flag = 0;

} else {unpark ( dequeue (m->queue ));

}m->guard = 0;

}

12 / 40

Page 28: Locks and semaphores - KTH

a detour in Sun Solaris

void lock( lock_t *m) {

while (try(m->guard) != 0) {};

if(m->flag == 0) {m->flag = 1;m->guard = 0;

} else {queue_add (m->queue , gettid ());m->guard = 0;park ();

}

void unlock ( lock_t *m) {

while (try(m->guard) != 0) {};

if(empty(m->queue )) {m->flag = 0;

} else {unpark ( dequeue (m->queue ));

}m->guard = 0;

}

12 / 40

Page 29: Locks and semaphores - KTH

it’s not easy

It’s not easy to to get it right.

/* m->flag == 1 */:

queue_add (m->queue , gettid ());m->guard = 0;park ();// when I wake up the flag is set

if(empty(m->queue )) {m->flag = 0;

} else {// don ’t reset the flagunpark ( dequeue (m->queue ));

}

13 / 40

Page 30: Locks and semaphores - KTH

it’s not easy

It’s not easy to to get it right.

/* m->flag == 1 */:

queue_add (m->queue , gettid ());setpark ();// if somone unparks now my park () is a noopm->guard = 0;park ();

if(empty(m->queue )) {m->flag = 0;

} else {// don ’t reset the flagunpark ( dequeue (m->queue ));

}

13 / 40

Page 31: Locks and semaphores - KTH

back to Linux

Introducing futex: fast user space mutex.

futex_wait(mutex, val) : suspend on the mutex if its equal to val.futex_wake(mutex) : wake one of the treads suspended on the mutex

In GCC you have to call them using a syscall()

14 / 40

Page 32: Locks and semaphores - KTH

back to Linux

Introducing futex: fast user space mutex.

futex_wait(mutex, val) : suspend on the mutex if its equal to val.futex_wake(mutex) : wake one of the treads suspended on the mutex

In GCC you have to call them using a syscall()

14 / 40

Page 33: Locks and semaphores - KTH

back to Linux

Introducing futex: fast user space mutex.

futex_wait(mutex, val) : suspend on the mutex if its equal to val.futex_wake(mutex) : wake one of the treads suspended on the mutex

In GCC you have to call them using a syscall()

14 / 40

Page 34: Locks and semaphores - KTH

back to Linux

Introducing futex: fast user space mutex.

futex_wait(mutex, val) : suspend on the mutex if its equal to val.futex_wake(mutex) : wake one of the treads suspended on the mutex

In GCC you have to call them using a syscall()

14 / 40

Page 35: Locks and semaphores - KTH

a futex lock

void lock( volatile int *lock) {while (try(lock) != 0) {

// time to sleep ...futex_wait (lock , 1);

}}

void unlock ( volatile int *lock) {*lock = 0;futex_wake (lock );

}

Not very efficient - we want to avoid calling futex_wake() if no one is waiting.

15 / 40

Page 36: Locks and semaphores - KTH

a futex lock

void lock( volatile int *lock) {while (try(lock) != 0) {

// time to sleep ...futex_wait (lock , 1);

}}

void unlock ( volatile int *lock) {*lock = 0;futex_wake (lock );

}

Not very efficient - we want to avoid calling futex_wake() if no one is waiting.

15 / 40

Page 37: Locks and semaphores - KTH

a futex lock

void lock( volatile int *lock) {while (try(lock) != 0) {

// time to sleep ...futex_wait (lock , 1);

}}

void unlock ( volatile int *lock) {*lock = 0;futex_wake (lock );

}

Not very efficient - we want to avoid calling futex_wake() if no one is waiting.

15 / 40

Page 38: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 39: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 40: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutex

pthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 41: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 42: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 43: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 44: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 45: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 46: Locks and semaphores - KTH

pthread mutexUsing Linux futex or Sun park/unpark directly is error prone and not very portable.

It’s better to use the pthread library API, probably more efficient and definitely lessproblems.

Introducing pthread mutex locks:pthread_mutex_t : structure that is the mutexpthread_mutex_init(pthread_mutex_t *mutex, ... *attr)

pthread_mutex_destroy(pthread_mutex_t *mutex)

pthread_mutex_lock(pthread_mutex_t *mutex)

pthread_mutex_unlock(pthread_mutex_t *mutex)

The lock procedure is platform specific, normally implemented as a combination ofspinning and yield.

16 / 40

Page 47: Locks and semaphores - KTH

What could go wrong?

Nothing works, will not even compile.Deadlock: the execution is stuck, no thread is making progress.Livelock: we’re moving around in circles, all threads think that they are doingprogress but we’re stuck in a loop.Starvation: we’re making progress but some threads are stuck waiting.Unfairness: we’re making progress but some threads are given more of theresources.

17 / 40

Page 48: Locks and semaphores - KTH

What could go wrong?

Nothing works, will not even compile.

Deadlock: the execution is stuck, no thread is making progress.Livelock: we’re moving around in circles, all threads think that they are doingprogress but we’re stuck in a loop.Starvation: we’re making progress but some threads are stuck waiting.Unfairness: we’re making progress but some threads are given more of theresources.

17 / 40

Page 49: Locks and semaphores - KTH

What could go wrong?

Nothing works, will not even compile.Deadlock: the execution is stuck, no thread is making progress.

Livelock: we’re moving around in circles, all threads think that they are doingprogress but we’re stuck in a loop.Starvation: we’re making progress but some threads are stuck waiting.Unfairness: we’re making progress but some threads are given more of theresources.

17 / 40

Page 50: Locks and semaphores - KTH

What could go wrong?

Nothing works, will not even compile.Deadlock: the execution is stuck, no thread is making progress.Livelock: we’re moving around in circles, all threads think that they are doingprogress but we’re stuck in a loop.

Starvation: we’re making progress but some threads are stuck waiting.Unfairness: we’re making progress but some threads are given more of theresources.

17 / 40

Page 51: Locks and semaphores - KTH

What could go wrong?

Nothing works, will not even compile.Deadlock: the execution is stuck, no thread is making progress.Livelock: we’re moving around in circles, all threads think that they are doingprogress but we’re stuck in a loop.Starvation: we’re making progress but some threads are stuck waiting.

Unfairness: we’re making progress but some threads are given more of theresources.

17 / 40

Page 52: Locks and semaphores - KTH

What could go wrong?

Nothing works, will not even compile.Deadlock: the execution is stuck, no thread is making progress.Livelock: we’re moving around in circles, all threads think that they are doingprogress but we’re stuck in a loop.Starvation: we’re making progress but some threads are stuck waiting.Unfairness: we’re making progress but some threads are given more of theresources.

17 / 40

Page 53: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:

18 / 40

Page 54: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:

18 / 40

Page 55: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:

18 / 40

Page 56: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:

18 / 40

Page 57: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:

18 / 40

Page 58: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:

18 / 40

Page 59: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:takes lock

18 / 40

Page 60: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:takes lock

18 / 40

Page 61: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:takes lock

18 / 40

Page 62: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:takes lock

suspends on lock

18 / 40

Page 63: Locks and semaphores - KTH

Resources, priorities and scheduling

Assume we have a fixed priority scheduler, three processes with high (H), medium (M)and low (L) priority and one critical resource.

0 10 20 30 40 50 60 70 80 90 100 110 120

H:

M:

L:takes lock

suspends on lock

18 / 40

Page 64: Locks and semaphores - KTH

Mars Pathfinder and Priority Inversion

19 / 40

Page 65: Locks and semaphores - KTH

Some examples

concurrent countera lista queue

20 / 40

Page 66: Locks and semaphores - KTH

the concurrent counter

s t r u c t counte r_t {i n t v a l ;

}

vo id i n c r ( s t r u c t counte r_t ∗c ) {c−>v a l ++;

}

s t r u c t counte r_t {i n t v a l ;pthread_mutex_t l o c k ;

}

vo id i n c r ( s t r u c t counte r_t ∗c ) {p th r ead_ lock ( c−>l o c k ) ;c−>v a l ++;pth read_un lock ( c−>l o c k ) ;

}

21 / 40

Page 67: Locks and semaphores - KTH

the concurrent counter

s t r u c t counte r_t {i n t v a l ;

}

vo id i n c r ( s t r u c t counte r_t ∗c ) {c−>v a l ++;

}

s t r u c t counte r_t {i n t v a l ;pthread_mutex_t l o c k ;

}

vo id i n c r ( s t r u c t counte r_t ∗c ) {p th r ead_ lock ( c−>l o c k ) ;c−>v a l ++;pth read_un lock ( c−>l o c k ) ;

}

21 / 40

Page 68: Locks and semaphores - KTH

Do the right thingDoing the right thing often has a price.

22 / 40

Page 69: Locks and semaphores - KTH

Do the right thingDoing the right thing often has a price.

22 / 40

Page 70: Locks and semaphores - KTH

sloppy counter

counter

thread 1

Sloppy vs Speed - do the right thing.

23 / 40

Page 71: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2

Sloppy vs Speed - do the right thing.

23 / 40

Page 72: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

Sloppy vs Speed - do the right thing.

23 / 40

Page 73: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

Sloppy vs Speed - do the right thing.

23 / 40

Page 74: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

0

Sloppy vs Speed - do the right thing.

23 / 40

Page 75: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

0

1

Sloppy vs Speed - do the right thing.

23 / 40

Page 76: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

0

1 1

Sloppy vs Speed - do the right thing.

23 / 40

Page 77: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

0

12

Sloppy vs Speed - do the right thing.

23 / 40

Page 78: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

0

12 1

Sloppy vs Speed - do the right thing.

23 / 40

Page 79: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local

0

1 13

Sloppy vs Speed - do the right thing.

23 / 40

Page 80: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local13 2

Sloppy vs Speed - do the right thing.

23 / 40

Page 81: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local124

Sloppy vs Speed - do the right thing.

23 / 40

Page 82: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local24 2

Sloppy vs Speed - do the right thing.

23 / 40

Page 83: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local2 25

Sloppy vs Speed - do the right thing.

23 / 40

Page 84: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local2 25

5

Sloppy vs Speed - do the right thing.

23 / 40

Page 85: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local2 2

5

0

Sloppy vs Speed - do the right thing.

23 / 40

Page 86: Locks and semaphores - KTH

sloppy counter

counter

thread 1 thread 2 thread 3

local local local2 2

5

0

Sloppy vs Speed - do the right thing.

23 / 40

Page 87: Locks and semaphores - KTH

how about a list

Simple solution: protect the list with one lock.

Concurrent solution: allow several thread to operate on the list concurrently.

concurrent reading: not a problemconcurrent updating: .... hmm, how would you solve it?

24 / 40

Page 88: Locks and semaphores - KTH

how about a list

Simple solution: protect the list with one lock.

Concurrent solution: allow several thread to operate on the list concurrently.

concurrent reading: not a problemconcurrent updating: .... hmm, how would you solve it?

24 / 40

Page 89: Locks and semaphores - KTH

how about a list

Simple solution: protect the list with one lock.

Concurrent solution: allow several thread to operate on the list concurrently.

concurrent reading: not a problem

concurrent updating: .... hmm, how would you solve it?

24 / 40

Page 90: Locks and semaphores - KTH

how about a list

Simple solution: protect the list with one lock.

Concurrent solution: allow several thread to operate on the list concurrently.

concurrent reading: not a problemconcurrent updating: ....

hmm, how would you solve it?

24 / 40

Page 91: Locks and semaphores - KTH

how about a list

Simple solution: protect the list with one lock.

Concurrent solution: allow several thread to operate on the list concurrently.

concurrent reading: not a problemconcurrent updating: .... hmm, how would you solve it?

24 / 40

Page 92: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

25 / 40

Page 93: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

front end

dummy1615

25 / 40

Page 94: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

front end

dummy1615

25 / 40

Page 95: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

front end

dummy1615 dummy

25 / 40

Page 96: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

front end

dummy1615 dummy

25 / 40

Page 97: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

front end

dummy1615 dummy

25 / 40

Page 98: Locks and semaphores - KTH

What about a queue

Simple solution: protect the queue with one lock.

Concurrent solution: allow threads to add elements to the queue at the same time asother remove elements.

front end

1615 dummy17

25 / 40

Page 99: Locks and semaphores - KTH

an operating system

Traditionally operating systems were single threaded - the obvious solution.

The first systems that operated on multi-cpu architectures used one big kernel lock toavoid any problems with concurrency.

An operating system that is targeting multi-core architectures will today be multithreaded and use fine grain locking to increase performance.

How are things done in for example the JVM or Erlang?

26 / 40

Page 100: Locks and semaphores - KTH

an operating system

Traditionally operating systems were single threaded - the obvious solution.

The first systems that operated on multi-cpu architectures used one big kernel lock toavoid any problems with concurrency.

An operating system that is targeting multi-core architectures will today be multithreaded and use fine grain locking to increase performance.

How are things done in for example the JVM or Erlang?

26 / 40

Page 101: Locks and semaphores - KTH

an operating system

Traditionally operating systems were single threaded - the obvious solution.

The first systems that operated on multi-cpu architectures used one big kernel lock toavoid any problems with concurrency.

An operating system that is targeting multi-core architectures will today be multithreaded and use fine grain locking to increase performance.

How are things done in for example the JVM or Erlang?

26 / 40

Page 102: Locks and semaphores - KTH

an operating system

Traditionally operating systems were single threaded - the obvious solution.

The first systems that operated on multi-cpu architectures used one big kernel lock toavoid any problems with concurrency.

An operating system that is targeting multi-core architectures will today be multithreaded and use fine grain locking to increase performance.

How are things done in for example the JVM or Erlang?

26 / 40

Page 103: Locks and semaphores - KTH

beyond locks

The locks that we have seen are all right:

We can take a lock and prevent others from obtaining the lock.

If someone holds the lock we will suspend execution.When the lock is released we will wake up and try to grab the lock again.

We would like to suspend and only be woken up if a specified condition holds true.

27 / 40

Page 104: Locks and semaphores - KTH

beyond locks

The locks that we have seen are all right:

We can take a lock and prevent others from obtaining the lock.If someone holds the lock we will suspend execution.

When the lock is released we will wake up and try to grab the lock again.

We would like to suspend and only be woken up if a specified condition holds true.

27 / 40

Page 105: Locks and semaphores - KTH

beyond locks

The locks that we have seen are all right:

We can take a lock and prevent others from obtaining the lock.If someone holds the lock we will suspend execution.When the lock is released we will wake up and try to grab the lock again.

We would like to suspend and only be woken up if a specified condition holds true.

27 / 40

Page 106: Locks and semaphores - KTH

beyond locks

The locks that we have seen are all right:

We can take a lock and prevent others from obtaining the lock.If someone holds the lock we will suspend execution.When the lock is released we will wake up and try to grab the lock again.

We would like to suspend and only be woken up if a specified condition holds true.

27 / 40

Page 107: Locks and semaphores - KTH

the queue revisited

What do we do now?

28 / 40

Page 108: Locks and semaphores - KTH

the queue revisited

front end

dummy1615

What do we do now?

28 / 40

Page 109: Locks and semaphores - KTH

the queue revisited

front end

dummy1615

What do we do now?

28 / 40

Page 110: Locks and semaphores - KTH

the queue revisited

front end

dummy1615

What do we do now?

28 / 40

Page 111: Locks and semaphores - KTH

the queue revisited

front end

dummy1615

What do we do now?

28 / 40

Page 112: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 113: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variable

pthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 114: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 115: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 116: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 117: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 118: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 119: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 120: Locks and semaphores - KTH

conditional variables

Introducing pthread conditional variables:

pthread_cond_t : the data structure of a conditional variablepthread_cond_init(pthread_cond_t *restrict cond, ...)

pthread_cond_destroy(pthread_cond_t *cond)

pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

pthread_cond_signal(pthread_cond_t *cond)

pthread_cond_broadcast(pthread_cond_t *cond)

The exact declarations are slightly more complicated, check the man pages.

29 / 40

Page 121: Locks and semaphores - KTH

the producer/consumer

A single element buffer, multiple consumers, multiple producers.int buffer ;int count = 0;

void put(int value) {assert (count == 0);count = 1;buffer = value;

}

int get () {assert (count == 1);count = 0;return buffer ;

}

Let’s try to make this work.

30 / 40

Page 122: Locks and semaphores - KTH

the producer/consumer

A single element buffer, multiple consumers, multiple producers.int buffer ;int count = 0;

void put(int value) {assert (count == 0);count = 1;buffer = value;

}

int get () {assert (count == 1);count = 0;return buffer ;

}

Let’s try to make this work.

30 / 40

Page 123: Locks and semaphores - KTH

the producer/consumer

A single element buffer, multiple consumers, multiple producers.int buffer ;int count = 0;

void put(int value) {assert (count == 0);count = 1;buffer = value;

}

int get () {assert (count == 1);count = 0;return buffer ;

}

Let’s try to make this work.

30 / 40

Page 124: Locks and semaphores - KTH

this will not work

void produce (int val) {put(val );

}

int consume () {int val = get ();return val;

}

31 / 40

Page 125: Locks and semaphores - KTH

add a mutex and cond variable

pthread_cond_t cond;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;i f ( count == 1)

pthread_cond_wait (&cond , &mutex ) ;put ( v a l ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;i f ( count == 0)

pthread_cond_wait (&cond , &mutex ) ;i n t v a l = get ( ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;re tu rn v a l ;

}

When does this work, when does it not work?

32 / 40

Page 126: Locks and semaphores - KTH

add a mutex and cond variable

pthread_cond_t cond;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;i f ( count == 1)

pthread_cond_wait (&cond , &mutex ) ;put ( v a l ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;i f ( count == 0)

pthread_cond_wait (&cond , &mutex ) ;i n t v a l = get ( ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;re tu rn v a l ;

}

When does this work, when does it not work?

32 / 40

Page 127: Locks and semaphores - KTH

add a mutex and cond variable

pthread_cond_t cond;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;i f ( count == 1)

pthread_cond_wait (&cond , &mutex ) ;put ( v a l ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;i f ( count == 0)

pthread_cond_wait (&cond , &mutex ) ;i n t v a l = get ( ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;re tu rn v a l ;

}

When does this work, when does it not work?

32 / 40

Page 128: Locks and semaphores - KTH

add a mutex and cond variable

pthread_cond_t cond;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;i f ( count == 1)

pthread_cond_wait (&cond , &mutex ) ;put ( v a l ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;i f ( count == 0)

pthread_cond_wait (&cond , &mutex ) ;i n t v a l = get ( ) ;p th r ead_cond_s igna l (&cond ) ;pthread_mutex_unlock(&mutex ) ;re tu rn v a l ;

}

When does this work, when does it not work?

32 / 40

Page 129: Locks and semaphores - KTH

a race condition

If you’re signaled to wake up - it might take some time before you do wake up.

33 / 40

Page 130: Locks and semaphores - KTH

better

pthread_cond_t filled , empty;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;whi le ( count == 1)

pthread_cond_wait (&empty , &mutex ) ;:p th r ead_cond_s igna l (& f i l l e d ) ;:

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;whi le ( count == 0)

pthread_cond_wait (& f i l l e d , &mutex ) ;:

p th r ead_cond_s igna l (&empty ) ;:

}

34 / 40

Page 131: Locks and semaphores - KTH

better

pthread_cond_t filled , empty;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;whi le ( count == 1)

pthread_cond_wait (&empty , &mutex ) ;:p th r ead_cond_s igna l (& f i l l e d ) ;:

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;whi le ( count == 0)

pthread_cond_wait (& f i l l e d , &mutex ) ;:

p th r ead_cond_s igna l (&empty ) ;:

}

34 / 40

Page 132: Locks and semaphores - KTH

better

pthread_cond_t filled , empty;pthread_mutex_t mutex;

produce ( i n t v a l ) {pthread_mutex_lock(&mutex ) ;whi le ( count == 1)

pthread_cond_wait (&empty , &mutex ) ;:p th r ead_cond_s igna l (& f i l l e d ) ;:

}

i n t consume ( ) {pthread_mutex_lock(&mutex ) ;whi le ( count == 0)

pthread_cond_wait (& f i l l e d , &mutex ) ;:

p th r ead_cond_s igna l (&empty ) ;:

}

34 / 40

Page 133: Locks and semaphores - KTH

a larger buffer

int buffer [MAX ];int *getp = 0;in *putp = 0;int count = 0;

void put(int value) {assert (count < MAX );buffer [putp] = value;putp = putp + 1 % MAX;count ++;

}

int get () {assert (count > 0);int val = buffer [getp ];getp = getp + 1 % MAXcount --return val;

}

35 / 40

Page 134: Locks and semaphores - KTH

final touch

produce (int val) {:while (count == MAX)

pthread_cond_wait (& empty , &mutex );:

}

int consume () {:

while (count == 0)pthread_cond_wait (& filled , &mutex );

:}

Can we allow a producer to add an entry while another removes an entry?

36 / 40

Page 135: Locks and semaphores - KTH

final touch

produce (int val) {:while (count == MAX)

pthread_cond_wait (& empty , &mutex );:

}

int consume () {:

while ( count == 0)pthread_cond_wait (& filled , &mutex );

:}

Can we allow a producer to add an entry while another removes an entry?

36 / 40

Page 136: Locks and semaphores - KTH

final touch

produce (int val) {:while (count == MAX)

pthread_cond_wait (& empty , &mutex );:

}

int consume () {:

while ( count == 0)pthread_cond_wait (& filled , &mutex );

:}

Can we allow a producer to add an entry while another removes an entry?36 / 40

Page 137: Locks and semaphores - KTH

Where are we now?

atomic test and set: we need it

spin locks: simple to use but have some problemswait and wake : avoid spinningcondition variables : don’t wake up if it’s not time to continue

Is there more?

37 / 40

Page 138: Locks and semaphores - KTH

Where are we now?

atomic test and set: we need itspin locks: simple to use but have some problems

wait and wake : avoid spinningcondition variables : don’t wake up if it’s not time to continue

Is there more?

37 / 40

Page 139: Locks and semaphores - KTH

Where are we now?

atomic test and set: we need itspin locks: simple to use but have some problemswait and wake : avoid spinning

condition variables : don’t wake up if it’s not time to continue

Is there more?

37 / 40

Page 140: Locks and semaphores - KTH

Where are we now?

atomic test and set: we need itspin locks: simple to use but have some problemswait and wake : avoid spinningcondition variables : don’t wake up if it’s not time to continue

Is there more?

37 / 40

Page 141: Locks and semaphores - KTH

Where are we now?

atomic test and set: we need itspin locks: simple to use but have some problemswait and wake : avoid spinningcondition variables : don’t wake up if it’s not time to continue

Is there more?

37 / 40

Page 142: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:holds a number

only allow threads to pass is number is above 0passing threads decremented the numbera thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 143: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:

holds a numberonly allow threads to pass is number is above 0

passing threads decremented the numbera thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 144: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:holds a number

only allow threads to pass is number is above 0passing threads decremented the number

a thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 145: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:holds a numberonly allow threads to pass is number is above 0

passing threads decremented the numbera thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 146: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:holds a numberonly allow threads to pass is number is above 0passing threads decremented the number

a thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 147: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:holds a numberonly allow threads to pass is number is above 0passing threads decremented the numbera thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 148: Locks and semaphores - KTH

Semaphores

Properties of a semaphore:holds a numberonly allow threads to pass is number is above 0passing threads decremented the numbera thread can increment the number

A semaphore is a counter of resources.

38 / 40

Page 149: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structuresem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processesint sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 150: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structure

sem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processesint sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 151: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structuresem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processes

int sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 152: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structuresem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processesint sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 153: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structuresem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processesint sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 154: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structuresem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processesint sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 155: Locks and semaphores - KTH

POSIX semaphores

#include <semaphore.h>

sem_t : the semaphore data structuresem_init(sem_t *sem, int pshared, unsigned int value): could beshared between processesint sem_destroy(sem_t *sem)

sem_wait(sem_t *sem)

sem_post(sem_t *sem)

39 / 40

Page 156: Locks and semaphores - KTH

Summary

40 / 40

Page 157: Locks and semaphores - KTH

Summary

40 / 40

Page 158: Locks and semaphores - KTH

Summary

40 / 40

Page 159: Locks and semaphores - KTH

Summary

40 / 40

Page 160: Locks and semaphores - KTH

Summary

40 / 40

Page 161: Locks and semaphores - KTH

Summary

40 / 40