Assignment 2 - PowerPoint PPT Presentation

1 / 45
About This Presentation
Title:

Assignment 2

Description:

A mutex is a variable that can be in two states, locked and unlocked. ... If the mutex is currently unlocked, the call succeeds and the calling thread is ... – PowerPoint PPT presentation

Number of Views:30
Avg rating:3.0/5.0
Slides: 46
Provided by: sinc150
Category:

less

Transcript and Presenter's Notes

Title: Assignment 2


1
Assignment 2
Thread Synchronization
http//www.2pass.co.uk/roundabout.htm
2
Roundabouts
3
Negotiating the Roundabout
4
Traffic Circle Simulation
5
Pthreads
Thread Synchronization
http//dis.cs.umass.edu/wagner/threads_html/tutor
ial.html http//www.fsmlabs.com/developers/docs/ht
ml/susv2/xsh/pthread.h.html
Silberchatz et al, Operating System Concepts,
Section 7.4 A. Tenanbaum, Modern Operating
Systems 2nd Ed., Section 2.3
6
Hello World
Main thread
void print_message_function( void ptr )
main() pthread_t thread1, thread2 char
message1 "Hello" char message2
"World" pthread_create( thread1,
pthread_attr_default,
(void)print_message_function, (void)
message1) pthread_create(thread2,
pthread_attr_default,
(void)print_message_function, (void)
message2) exit(0)
Page 1
7
Hello World
Print message function
void print_message_function( void ptr )
char message message (char )
ptr printf("s ", message)
Page 2
8
Race Conditions
  • One thread prints Hello, the other prints
    World.
  • Two flaws
  • Threads execute concurrently, so we may see
    either World Hello or Hello World.
  • If the main thread executes exit() before the
    printer threads finish, then no output will be
    generated.
  • Can be fixed with duct tape delays

9
Hello World
Main thread
void print_message_function( void ptr )
main() pthread_t thread1, thread2 char
message1 "Hello" char message2 "World"
pthread_create( thread1,
pthread_attr_default, (void )
print_message_function, (void ) message1)
sleep(10) pthread_create(thread2,
pthread_attr_default, (void )
print_message_function, (void ) message2)
sleep(10) exit(0)
Page 2
10
Hello World
Print message function
void print_message_function( void ptr )
char message message (char ) ptr
printf("s", message) pthread_exit(0)
Page 2
11
Race Conditions and Sleep
  • It is never safe to rely on timing delays to
    perform synchronization.
  • Two processes are competing for a resource
    (stdio)
  • If the process were distributed, the time allowed
    may be insufficient.
  • When a thread calls sleep, the entire process
    sleeps (i.e. all threads in the process sleep)
  • The same race condition exists, but 20 seconds
    longer
  • Use pthread_delay_np() (?)

12
Delaying a Thread
  • To delay a thread for two seconds (???)

struct timespec delay delay.tv_sec
2 delay.tv_nsec 0 pthread_delay_np( delay )
  • Possible in DEC OSF/1 OS, V 3.0 POSIX, but not
    under POSIX 1003.1C
  • The closest that we have is pthread_cond_timedwait
    ()

13
Race Condition
  • A race condition occurs when two or more
    processes or threads access and manipulate the
    same data concurrently, and
  • the outcome of the execution depends on the
    particular order in which the access takes place.
  • To ensure that only one process at a time
    accesses the data, we require some form of
    synchronization of the processes.

14
Mutual Exclusion
  • One way to avoid a race condition is to identify
    critical sections of the code, and ensure mutual
    exclusion of the two threads or processes.

Critical regions
Task A
Task B
B attempts to enter its critical region
B blocked
15
Mutual Exclusion
  • Four conditions for a good solution
  • No two processes may be simultaneously inside
    their critical regions.
  • No assumptions may be made about speeds or the
    number of CPUs
  • No process running outside its critical region
    may block other processes.
  • No process should have to wait forever to enter
    its critical region.

16
Lock Variable
  • A simple lock variable wont ensure mutual
    exclusion.

Lock check interrupted
Critical regions then interrupted
Task A
Task B
17
Lock Variable?
  • We could define a lock variable, Lock
  • If Task A wants to run, it checks Lock
  • If Lock 0, then no process is in its critical
    region
  • if Lock 1, then some process is in its critical
    region.
  • Task A sets Lock 1, enters its critical region,
    then finishes and sets Lock 0.
  • But Task B could interrupt Task A while it is
    reading the Lock. If Task A sees that Lock 0,
    then is bumped by Task B which begins running,
    then Task A starts running again, then both are
    in their critical regions at the same time.

18
Strict Alteration
Process B
Process A
while (TRUE) while(turn ! 1) / loop
/ critical_region() turn 0
noncritical_region()
while (TRUE) while(turn ! 0) / loop
/ critical_region() turn 1
noncritical_region()
Page 2
19
Strict Alteration
  • An integer variable turn keeps track of whos
    turn it is
  • When turn 0, its time for Process A
  • When turn 1, its time for Process B
  • Continually testing a variable until some value
    appears is called busy waiting
  • A lock that uses busy waiting is called a spin
    lock

20
Test and Set Lock (TSL)
  • Many computers have an instruction
  • TSL RX,LOCK
  • Read the contents of memory word lock into
    register RX
  • Store a non-zero value at memory address lock.
  • The operations of reading the word and storing
    into it are guaranteed to be indivisible.
  • In a multi-CPU system, the memory bus is locked
    to prevent other CPUs from accessing memory until
    the TSL is complete

21
Using Test and Set Lock
Enter critical region
Copy lock to register and set lock to 1 Was lock
0? If it was non-zero, lock was set, so loop If
zero, return to caller, enter critical
region
enter_region TSL REGISTER,LOCK CMP
REGISTER,0 JNE enter_region RET
Leave critical region
Leave_region MOVE LOCK,0 RET
Store a 0 in lock
Page 2
22
Mutex
  • A mutex is a variable that can be in two states,
    locked and unlocked.
  • When a thread or process needs access to a
    critical region, it calls mutex_lock.
  • If the mutex is currently unlocked, the call
    succeeds and the calling thread is free to enter
    the critical region.
  • If the mutex is currently locked, the calling
    thread is blocked until the thread in the
    critical region is finished and calls
    mutex_unlock.

23
Code for Mutex
Mutex_lock
Mutex_lock TSL REGISTER,MUTEX CMP
REGISTER,0 JZE ok CALL thread_yield
JMP mutex_lock Ok RET
Copy mutex to register and set mutex to 1 Was
lock 0? If it was zero, mutex unlocked, so
return If non-zero, mutex busy schedule another
thread Try again later Return to caller enter
critical region
Mutex_unlock
Mutex_unlock MOVE MUTEX,0 RET
Store a 0 in mutex Return to caller
24
Code for Mutex
  • Threads will go on indefinitely if in a loop
    processes are eventually timed out.
  • When mutex_lock fails, it calls thread_yield to
    give up the CPU to another thread. Hence, there
    is no busy waiting.
  • Neither mutex_lock nor mutex_unlock require
    kernel calls. Thread_yield is a fast call to
    thread scheduler in user space.

25
Using Mutex
Thread 2
Thread 1
mutex_lock(m) Local global mutex_unlock(m)
mutex_lock(m) global mutex_unlock(m)
  • Mutex is the simplest and most primitive
    synchronization variable.
  • It provides a single, absolute owner for the
    section of code between mutex_lock() and
    mutex_unlock()

26
Mutex with Three Threads
  • Threads T1, T2, T3 request a mutex one after the
    other.
  • Their priority levels are T1,0 T2,1 T3,2
  • T1 gets the mutex, T2, T3 go onto the sleep queue
    in their order of priority
  • When T1 releases the mutex, T3 will be awakened
    to claim the mutex

27
Mutex with Three Threads
28
Condition Variables
Acquire mutex Test condition False! Release
mutex Sleep on CV
Acquire mutex Change condition Signal
T1 Release mutex
Reacquire mutex Retest condition Success!
Do thing Release mutex
29
Condition Variables
  • A condition can be complex
  • e.g. X gt 17 and Y is prime
  • CVs always have an associated mutex
  • Procedure
  • A thread obtains the associated mutex
  • Test condition under protection of mutex
  • If condition true, complete task, release mutex
  • If condition false, mutex is released for you,
    thread goes to sleep on the CV
  • When another thread changes the condition, it
    calls cond_signal() to wake up the thread, regain
    mutex, retest the condition, and act according to
    condition.

30
Using a Condition Variable
Thread 2
Thread 1
mutex_lock(m) while (!my_condition) while(cond_w
ait(c, m) ! 0)
mutex_lock(m) my_condition TRUE cond_signal(
c) mutex_unlock(m)
do_thing() mutex_unlock(m)
31
Using Condition Variables
  • A thread can wake up all sleepers with
    cond_broadcast()
  • A thread can have limited sleep time by calling
    cond_timedwait()
  • When timer expires, cond_timedwait() returns
    ETIME
  • Both cond_wait() and cond_timed() return without
    holding the mutex
  • (hence extra while loop in Thread 1)

32
Pthreads and Solaris Threads
  • pthread_mutex_t
  • pthread_cond_t
  • pthread_t
  • pthread_create()
  • pthread_destroy()
  • pthread_exit()
  • pthread_join()
  • pthread_mutex_init()
  • pthread_mutex_destroy()
  • pthread_mutex_lock()
  • pthread_mutex_unlock()
  • pthread_cond_init()
  • pthread_cond_destroy()
  • pthread_cond_wait()
  • pthread_cond_broadcast()
  • pthread_cond_signal()
  • mutex_t
  • cond_t
  • thread_t
  • thr_create()
  • thr_exit()
  • thr_join()
  • mutex_init()
  • mutex_destroy()
  • mutex_lock()
  • mutex_unlock()
  • cond_init()
  • cond_destroy()
  • cond_wait()
  • cond_broadcast()
  • cond_signal()

33
Producer/Consumer Example
  • Producer adds items to a buffer, consumer removes
    items from the buffer
  • Structure Buf holds the buffered data and the
    condition variables
  • When the producer wants to add data, it checks to
    see if the buffer is full
  • If full, the producer blocks on cond_wait()
  • When the consumer removes an item, the buffer is
    no longer full, so the producer is awakened from
    the cond_wait() call.
  • If empty, the consumer blocks on cond_wait()
  • When the producer adds an item, the consumers
    condition is satisfied, so it can remove an item
    from the buffer

34
Producer/Consumer Example
Variable Initialization
define _REEENTRANT include ltstdio.hgt include
ltthread.hgt include ltfcntl.hgt include
ltunistd.hgt include ltsys/stat.hgt include
ltsys/types.hgt include ltsys/uio.hgt define
BUFSIZE 512 define BUFCNT 4
Page 1
35
Producer/Consumer Example
Variable initialization
/ this is the data structure that is used
between the producer and consumer threads
/ struct char bufferBUFCNTBUFSIZE
int byteinbufBUFCNT mutex_t buflock
mutex_t donelock cond_t adddata cond_t
remdata int nextadd, nextrem, occ, done
Buf / function prototype / void
consumer(void )
Page 2
36
Producer/Consumer Example
Main thread
main(int argc, char argv) int ifd,
ofd thread_t cons_thr / check the command line
arguments / if (argc ! 3) printf("Usage s
ltinfilegt ltoutfilegt\n", argv0) exit(O) /
open the input file for the producer to use / if
((ifd - open(argvl, 0_RDONLY)) -1)
fprintf(stderr, "Can't open file s\n",
argvl) exit(1)
Page 3
37
Producer/Consumer Example
Main thread
/ open the output file for the consumer to use
/ if ((ofd open(argv2, 0_WRONLY0_CREAT,
0666)) -1) fprintf(stderr, "Can't open
file s\n", argv2) exit(1)
Page 4
38
Producer/Consumer Example
Main thread
/ zero the counters / Buf.nextadd Buf.nextrem
Buf.occ Buf.done 0 / set the thread
concurrency to 2 so the producer and consumer can
run concurrently / thr_setconcurrency(2) /
create the consumer thread / thr_create(NULL, 0,
consumer, (void )ofd, NULL, cons_thr)
Page 5
39
Producer/Consumer Example
Main thread - producer
/ the producer ! / while (1) / lock the
mutex / mutex_lock(Buf.buflock) / check
to see if any buffers are empty / / If not
then wait for that condition to become true /
while (Buf.occ BUFCNT) cond_wait(Buf.remd
ata, Buf.buflock) / read from the file and
put data into a buffer / Buf.byteinbufBuf.nex
tadd read(ifd,Buf.bufferBuf.nextadd,BUFS
IZE)
Page 6
40
Producer/Consumer Example
Main thread - producer
/ check to see if done reading / if
(Buf.byteinbufBuf.nextadd 0) / lock
the done lock / mutex_lock(Buf.donelock)
/ set the done flag and release the
mutex lock / Buf.done 1
mutex_unlock(Buf.donelock) / signal the
consumer to start consuming /
cond_signal(Buf.adddata) / release the
buffer mutex /' mutex_unlock(Buf-buflock)
/ leave the while loop / break

Page 7
41
Producer/Consumer Example
Main thread - producer
/ set the next buffer to fill / Buf.nextadd
Buf.nextadd BUFCNT / increment the
number of buffers that are filled /
Buf.occ / signal the consumer to start
consuming / cond_signal(Buf.adddata) /
release the mutex / mutex_unlock(Buf.buflock)

Page 8
42
Producer/Consumer Example
Main thread - producer
close(ifd) / wait for the consumer to
finish / thr_join(cons_thr, 0, NULL) / exit
the program / return(0)
Page 9
43
Producer/Consumer Example
Consumer thread
/ The consumer thread / void consumer(void
arg) int fd (int) arg / check to see if
any buffers are filled or if the done flag is set
/ while (1) / lock the mutex /
mutex_lock(Buf.buflock) if (!Buf.occ
Buf.done) mutex_unlock(Buf.buflock)
break
Page 10
44
Producer/Consumer Example
Consumer thread
/ check to see if any buffers are filled /
/ if not then wait for the condition to become
true / while (Buf.occ 0 !Buf.done)
cond_wait(Buf.adddata, Buf.buflock) /
write the data from the buffer to the file /
write(fd, Buf.bufferBuf.nextrem,
Buf.byteinbufBuf.nextrem) / set the next
buffer to write from / Buf.nextrem
Buf.nextrem BUFCNT / decrement the
number of buffers that are full / Buf.occ--
Page 11
45
Producer/Consumer Example
Consumer thread
/ signal the producer that a buffer is empty
/ cond_signal(Buf.remdata) / release
the mutex / mutex_unlock(Buf.buflock)
/ exit the thread / thr_exit((void )0)
Page 12
Write a Comment
User Comments (0)
About PowerShow.com