71
CS 2200 Presentation 20 Threads & Synchronization

CS 2200 Presentation 20 Threads & Synchronization

Embed Size (px)

Citation preview

Page 1: CS 2200 Presentation 20 Threads & Synchronization

CS 2200

Presentation 20

Threads & Synchronization

Page 2: CS 2200 Presentation 20 Threads & Synchronization

Question 1• Why are threads becoming increasingly

important?

1. Widespread influence of Java (GUI's)

2. Increasing availability of SMP's

3. Importance of computer gaming market

4. Logical way of abstracting complex task

Page 3: CS 2200 Presentation 20 Threads & Synchronization

Question 2• Why use a "while" loop around a

pthread_cond_wait() call?

1. In order to properly spinlock

2. To insure that the wait gets executed

3. To verify that the resource is free

4. SMP cache coherency

Page 4: CS 2200 Presentation 20 Threads & Synchronization

Question 3• Why should we minimize lock scope

(minimize the extent of code within a lock/unlock block)?

1. Allow for more concurrency

2. Depends

3. 42

4. Add a bit

Page 5: CS 2200 Presentation 20 Threads & Synchronization

Question 4• Do you have any control over thread

scheduling?

1. Yes

2. No

3. Why would I want to?

4. Maybe

Page 6: CS 2200 Presentation 20 Threads & Synchronization

Questions?

Page 7: CS 2200 Presentation 20 Threads & Synchronization

Our Road Map

Processor

Networking

Parallel Systems

I/O Subsystem

Memory Hierarchy

Page 8: CS 2200 Presentation 20 Threads & Synchronization

What’s wrong with Semaphores?void wait(int *s) { /* P */

while (*S <= 0) {

/* spin */

}

*s = *s - 1;

}

void signal(int *s) { /* V */

*s = *s + 1;

}

Page 9: CS 2200 Presentation 20 Threads & Synchronization

What’s wrong with Semaphores?void wait(int *s) { /* P */

while (*S <= 0) {

/* spin */

}

*s = *s - 1;

}

void signal(int *s) { /* V */

*s = *s + 1;

}

Page 10: CS 2200 Presentation 20 Threads & Synchronization

Solution• Block thread while waiting.

• How?

• Let’s examine a simple threads package...

Page 11: CS 2200 Presentation 20 Threads & Synchronization

Typical API• Thread_init

• Thread_create

• Thread_yield

• Thread_exit

• Mutex_create

• Mutex_lock

• Mutex_unlock

• Alarm

Page 12: CS 2200 Presentation 20 Threads & Synchronization

Nothing muchhappening inThreadland

Program starts in main• main is going to call thread_init

Page 13: CS 2200 Presentation 20 Threads & Synchronization

Thread_init• Create linked list of thread control blocks

– Context– Status

• RUNNING• READY• DONE• BLOCKED

– Pointer to mutex thread is waiting for.

• Start timer (Request from OS) – Which will be handled by "Alarm"

Page 14: CS 2200 Presentation 20 Threads & Synchronization

Thread_Init

TCB

Context

RUNNING

mutexPointer

next

I even created a TCB for myself!

But, I'm so lonely...

Page 15: CS 2200 Presentation 20 Threads & Synchronization

Thread_create• Make a new TCB

• malloc space for the new threads stack

• Get current context

• Modify context – stack address– stack size– starting address

• Note: Context is in TCB

• Add TCB to linked list (Ready)

Page 16: CS 2200 Presentation 20 Threads & Synchronization

Thread_create (3 times)

TCB

Context

READY

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next

I think I'llmake me amutex

Page 17: CS 2200 Presentation 20 Threads & Synchronization

Mutex_create• malloc new mutex variable (struct)

– status = UNLOCKED– Pointer to thread holding lock

Page 18: CS 2200 Presentation 20 Threads & Synchronization

Mutex_create

TCB

Context

READY

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

unlock

Holder

I just madea mutex!

Page 19: CS 2200 Presentation 20 Threads & Synchronization

Alarm

• Reset alarm• Thread_yield

Thread_yield• If no other threads

– return• Else

– Make current threads status READY (if not DONE or BLOCKED)

– Make “next” thread RUNNING– Context switch current with next

Page 20: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

unlock

Holder

Page 21: CS 2200 Presentation 20 Threads & Synchronization

Mutex_lock• If mutex is already locked

– Mark thread as blocked– Note in TCB mutex being waited on– Thread_yield

• Else– Make mutex locked– Point mutex at thread holding lock

Page 22: CS 2200 Presentation 20 Threads & Synchronization

Lock Mutex

TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

I have the mutex!

Page 23: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

Page 24: CS 2200 Presentation 20 Threads & Synchronization

Mutex_lock• If mutex is already locked

– Mark thread as blocked– Note in TCB mutex being waited on– Thread_yield

• Else– Make mutex locked– Point mutex at thread holding lock

Page 25: CS 2200 Presentation 20 Threads & Synchronization

Try to Lock Mutex (Fails)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next

Mutex

lock

Holder

• If mutex is already locked– Mark thread as blocked

– Note in TCB mutex being waited on

– Thread_yield

• Else– Make mutex locked

– Point mutex at thread holding lock

I want themutex!

Page 26: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

Page 27: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

Page 28: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next

Mutex

lock

Holder

Note: The yield routinecan check each blockedthread to make sure mutex is still locked

Stillwaiting!

Page 29: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

Page 30: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

Guess I don'tneed the

mutex anymore

Page 31: CS 2200 Presentation 20 Threads & Synchronization

Mutex_unlock• Check to see if thread trying to unlock is

the holder of the mutex

• Set mutex status to unlock

Page 32: CS 2200 Presentation 20 Threads & Synchronization

Unlocks Mutex

TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

unlock

Holder

Page 33: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

BLOCKED

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

unlock

Holder

Since mutex is unlocked we canchange status to RUNNING

Page 34: CS 2200 Presentation 20 Threads & Synchronization

Same Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

unlock

Holder

Since mutex is unlocked we canchange status to RUNNING

Page 35: CS 2200 Presentation 20 Threads & Synchronization

Same Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

RUNNING

mutexPointer

next

TCB

Context

READY

mutexPointer

next

Mutex

lock

Holder

And give the mutexto the requestor

Page 36: CS 2200 Presentation 20 Threads & Synchronization

Timer Interrupt (Alarm)

TCB

Context

READY

mutexPointer

next

TCB

Context

READY

mutexPointer

next TCB

Context

READY

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next

Mutex

unlock

Holder

I'm done!

Page 37: CS 2200 Presentation 20 Threads & Synchronization

Thread_exit• Make status DONE

• Thread_yield

Page 38: CS 2200 Presentation 20 Threads & Synchronization

Thread Exits

TCB

Context

READY

mutexPointer

next

TCB

Context

RUNNING

mutexPointer

next TCB

Context

READY

mutexPointer

next

TCB

Context

DONE

mutexPointer

next

Mutex

unlock

Holder

Page 39: CS 2200 Presentation 20 Threads & Synchronization

etc.

Page 40: CS 2200 Presentation 20 Threads & Synchronization

Question 51. Those slides made things much clearer

2. Those slides made things clearer

3. Those slides took up some time

4. Those slides confused me

5. Those slides baffled me

Page 41: CS 2200 Presentation 20 Threads & Synchronization

Questions?

Page 42: CS 2200 Presentation 20 Threads & Synchronization

Considerlock(m)

while(resource == busy)

wait(c, m)

resource = busy

unlock(m)

/* doing work... */

lock(m)

resource = available

unlock(m)

signal(c)

Page 43: CS 2200 Presentation 20 Threads & Synchronization

Demo

Sample pthreads program

Page 44: CS 2200 Presentation 20 Threads & Synchronization

1000

10

sortersortersortersortersortersortersorter

7

Scoreboard

producer

Page 45: CS 2200 Presentation 20 Threads & Synchronization

Operation• mainmain starts up operation• producerproducer thread

– Locks scoreboard– Waits for row to be available– Marks row as in use– Unlocks scoreboard – Fills buffer row with random ints– Locks scoreboard– Marks row as sortable– Unlocks scoreboard

AVAILABLE 0#define FILLING 1#define SORTABLE 2#define SORTING 3

Scoreboard

Row Status

0 AVAILABLE

1 AVAILABLE

2 AVAILABLE

3 AVAILABLE

4 AVAILABLE

5 AVAILABLE

... ...

Page 46: CS 2200 Presentation 20 Threads & Synchronization

Operation• mainmain starts up operation• producerproducer thread

– Locks scoreboard– Waits for row to be available– Marks row as in use– Unlocks scoreboard – Fills buffer row with random ints– Locks scoreboard– Marks row as sortable– Unlocks scoreboard

AVAILABLE 0#define FILLING 1#define SORTABLE 2#define SORTING 3

Scoreboard

Row Status

0 FILLING

1 AVAILABLE

2 AVAILABLE

3 AVAILABLE

4 AVAILABLE

5 AVAILABLE

... ...

Page 47: CS 2200 Presentation 20 Threads & Synchronization

Operation• mainmain starts up operation• producerproducer thread

– Locks scoreboard– Waits for row to be available– Marks row as in use– Unlocks scoreboard – Fills buffer row with random ints– Locks scoreboard– Marks row as sortable– Unlocks scoreboard

AVAILABLE 0#define FILLING 1#define SORTABLE 2#define SORTING 3

Scoreboard

Row Status

0 SORTABLE

1 AVAILABLE

2 AVAILABLE

3 AVAILABLE

4 AVAILABLE

5 AVAILABLE

... ...

Page 48: CS 2200 Presentation 20 Threads & Synchronization

Operation• sortersorter threads

– Lock scoreboard– Wait for row to be sortable– Mark row as sorting– Unlock scoreboard– Sort row (using bubblesort)– Lock scoreboard– Mark row as available

Scoreboard

Row Status

0 SORTABLE

1 AVAILABLE

2 AVAILABLE

3 AVAILABLE

4 AVAILABLE

5 AVAILABLE

... ...

Page 49: CS 2200 Presentation 20 Threads & Synchronization

Operation• sortersorter threads

– Lock scoreboard– Wait for row to be sortable– Mark row as sorting– Unlock scoreboard– Sort row (using bubblesort)– Lock scoreboard– Mark row as available

Scoreboard

Row Status

0 SORTING

1 AVAILABLE

2 AVAILABLE

3 AVAILABLE

4 AVAILABLE

5 AVAILABLE

... ...

Page 50: CS 2200 Presentation 20 Threads & Synchronization

Operation• sortersorter threads

– Lock scoreboard– Wait for row to be sortable– Mark row as sorting– Unlock scoreboard– Sort row (using bubblesort)– Lock scoreboard– Mark row as available

• Runnable as user level threads or kernel level (lwp/thread). [SOLARIS ONLY]

Scoreboard

Row Status

0 AVAILABLE

1 AVAILABLE

2 AVAILABLE

3 AVAILABLE

4 AVAILABLE

5 AVAILABLE

... ...

Page 51: CS 2200 Presentation 20 Threads & Synchronization

/* td -- Thread Demo */

#include <pthread.h>

#include <stdio.h>

#include <stdlib.h>

#define _REENTRANT

#define SIZE 1000 /* Size of sort buffers */

#define SCOUNT 7 /* Number of sorters */

#define ROWS 10 /* Number of buffers */

#define STEPS 22 /* Buffers full of data to

sort */

#define NONEFOUND -1 /* Used in searching */

Page 52: CS 2200 Presentation 20 Threads & Synchronization

/* Allowable states for row buffers (in scoreboard) */

enum {AVAILABLE, FILLING, SORTABLE, SORTING};

enum {NO, YES};

static int data[ROWS][SIZE]; /* The buffers */

static int available; /* Num of buffers

available to fill */

static int sortable; /* How many are

avail to sort */

static int scoreboard[ROWS]; /* Row access

scoreboard */

static int run; /* Flag used to

shutdown

gracefully */

Page 53: CS 2200 Presentation 20 Threads & Synchronization

/* Scoreboard mutex lock */

static pthread_mutex_t scorelock;

/* The producer can work! */

static pthread_cond_t pcanwork;

/* A sorter can work! */

static pthread_cond_t sorterworkavail;

/* Function prototypes */

static void *producer();

static void *sorter();

void sort(int);

Creatingnecessarymutex andconditionvariables

Page 54: CS 2200 Presentation 20 Threads & Synchronization

int main(int argc, char* argv[])

{

pthread_t producer_id;

pthread_t sorter_id[SCOUNT];

pthread_attr_t attr;

int i;

available = ROWS;

sortable = 0;

run = YES;

Threads haveid numbers!

Page 55: CS 2200 Presentation 20 Threads & Synchronization

pthread_attr_init(&attr);

/* This binds thread to lwp allowing kernel to

schedule thread (Will allow threads to run on

different cpu's) */

pthread_attr_setscope(&attr,PTHREAD_SCOPE_SYSTEM);

pthread_mutex_init(&scorelock, NULL);

pthread_cond_init(&pcanwork, NULL);

pthread_cond_init(&sorterworkavail, NULL);

for (i=0; i < ROWS; i++) {

scoreboard[i] = AVAILABLE;

}

if(argc == 1) /* No concurrency */

pthread_create

(&producer_id, NULL, producer, NULL);

else

pthread_create

(&producer_id, &attr, producer, NULL);

This trick onlyworks on Solaris

Page 56: CS 2200 Presentation 20 Threads & Synchronization

for(i = 0; i < SCOUNT; i++)

{

if(argc == 1)

pthread_create

(&sorter_id[i], NULL, sorter, NULL);

else

pthread_create

(&sorter_id[i], &attr, sorter, NULL);

}

printf("main> All threads running\n");

pthread_join(producer_id, NULL);

Page 57: CS 2200 Presentation 20 Threads & Synchronization

/* After the producer is finished we send signals

to all sorters to wake up and see that they

should quit */

for(i = 0; i < SCOUNT; i++)

{

pthread_cond_signal(&sorterworkavail);

}

for(i = 0; i < SCOUNT; i++)

{

pthread_join(sorter_id[i], NULL);

}

printf("Normal Termination\n");

return 0;

}

Page 58: CS 2200 Presentation 20 Threads & Synchronization

static void *producer() {

int pcount;

int target;

int i;

for(pcount = 0; pcount < STEPS; pcount++) {

pthread_mutex_lock(&scorelock);

while(available == 0) {

pthread_cond_wait(&pcanwork, &scorelock);

}

target = NONEFOUND;

for(i=0; i< ROWS; i++) {

if(scoreboard[i] == AVAILABLE) {

target = i;

available = available - 1;

break;

}

}

This is the loop which controls the total number of rows we process

Page 59: CS 2200 Presentation 20 Threads & Synchronization

pthread_mutex_unlock(&scorelock);

if(target == NONEFOUND) {

printf("*** Producer cannot find"

" available row!\n");

pthread_exit(NULL);

}

printf("p> Filling row %d\n", target);

for(i=0; i < SIZE; i++) {

data[target][i] = rand();

}

printf("p> Row %d complete\n", target);

pthread_mutex_lock(&scorelock);

scoreboard[target] = SORTABLE;

sortable = sortable + 1;

pthread_mutex_unlock(&scorelock);

pthread_cond_signal(&sorterworkavail);

}

Page 60: CS 2200 Presentation 20 Threads & Synchronization

run = NO;

return NULL;

/* pthread_exit(NULL); */

}

This means that we can quitonce we finish all sorting

Page 61: CS 2200 Presentation 20 Threads & Synchronization

static void *sorter() {

int i;

int target;

pthread_t me;

me = pthread_self();

while(1) {

pthread_mutex_lock(&scorelock);

while(sortable == 0 && run == YES) {

pthread_cond_wait

(&sorterworkavail, &scorelock);

}

Page 62: CS 2200 Presentation 20 Threads & Synchronization

/* If the producer says stop and there is no

work...exit */

if(run == NO && available == ROWS) {

printf(" S> %x Exiting..."

"prod done & no filled rows\n", me);

pthread_mutex_unlock(&scorelock);

pthread_exit(NULL);

}

target = NONEFOUND;

for(i = 0; i < ROWS; i++) {

if(scoreboard[i] == SORTABLE) {

target = i;

sortable = sortable - 1;

scoreboard[target] = SORTING;

break;

}

}

Page 63: CS 2200 Presentation 20 Threads & Synchronization

if(target == NONEFOUND) {

/* We get here if the producer is finished

and some threads are being sorted but

none are available for sorting */

printf("S> %x couldn't find thread to "

"sort.\n", me);

pthread_mutex_unlock(&scorelock);

pthread_exit(NULL);

}

pthread_mutex_unlock(&scorelock);

printf("S> %x starting...\n", me);

sort(target);

printf("S> %x finishing min = %d max = %d\n",

me, data[target][0],

data[target][SIZE-1]);

Page 64: CS 2200 Presentation 20 Threads & Synchronization

pthread_mutex_lock(&scorelock);

scoreboard[target] = AVAILABLE;

available = available + 1;

pthread_mutex_unlock(&scorelock);

pthread_cond_signal(&pcanwork);

}

}

Page 65: CS 2200 Presentation 20 Threads & Synchronization

void sort(int target) {

int outer;

int inner;

int temp;

outer = SIZE - 1;

for(outer = SIZE - 1; outer > 0; outer--) {

for(inner=0; inner < outer; inner++) {

if(data[target][inner] >

data[target][inner+1]) {

temp = data[target][inner];

data[target][inner] =

data[target][inner+1];

data[target][inner+1] = temp;

}

}

}

}

Page 66: CS 2200 Presentation 20 Threads & Synchronization

Questions?

Page 67: CS 2200 Presentation 20 Threads & Synchronization
Page 68: CS 2200 Presentation 20 Threads & Synchronization

System Calls getcontext(2)

NAME getcontext, setcontext - get and set current user context

SYNOPSIS #include

int getcontext(ucontext_t *ucp);

int setcontext(const ucontext_t *ucp);

DESCRIPTION The getcontext() function initializes the structure pointed to by ucp to the current user context of the calling pro- cess. The ucontext_t type that ucp points to defines the user context and includes the contents of the calling pro- cess' machine registers, the signal mask, and the current execution stack.

The setcontext() function restores the user context pointed to by ucp. A successful call to setcontext() does not return; program execution resumes at the point specified by the ucp argument passed to setcontext(). The ucp argument should be created either by a prior call to getcontext(), or by being passed as an argument to a signal handler. If the ucp argument was created with getcontext(), program execu- tion continues as if the corresponding call of getcontext() had just returned. If the ucp argument was created with makecontext(3C), program execution continues with the func- tion passed to makecontext(3C). When that function returns, the process continues as if after a call to setcontext() with the ucp argument that was input to makecontext(3C). If the ucp argument was passed to a signal handler, program execution continues with the program instruction following

Page 69: CS 2200 Presentation 20 Threads & Synchronization

the instruction interrupted by the signal. If the uc_link member of the ucontext_t structure pointed to by the ucp argument is equal to 0, then this context is the main con- text, and the process will exit when this context returns. The effects of passing a ucp argument obtained from any other source are unspecified.

RETURN VALUES On successful completion, setcontext() does not return and getcontext() returns 0. Otherwise, -1 is returned.

ERRORS No errors are defined.

USAGE When a signal handler is executed, the current user context is saved and a new context is created. If the process leaves the signal handler via longjmp(3B), then it is unspecified whether the context at the time of the

SunOS 5.7 Last change: 8 Oct 1996 1

System Calls getcontext(2)

corresponding setjmp(3B) call is restored and thus whether future calls to getcontext() will provide an accurate representation of the current context, since the context restored by longjmp(3B) may not contain all the information that setcontext() requires. Signal handlers should use siglongjmp(3C) or setcontext() instead.

Portable applications should not modify or access the uc_mcontext member of ucontext_t. A portable application cannot assume that context includes any process-wide static

Page 70: CS 2200 Presentation 20 Threads & Synchronization

data, possibly including errno. Users manipulating contexts should take care to handle these explicitly when required.

SEE ALSO sigaction(2), sigaltstack(2), sigprocmask(2), bsd_signal(3C), makecontext(3C), setjmp(3B), sigsetjmp(3C), ucontext(5)

Page 71: CS 2200 Presentation 20 Threads & Synchronization