/
Operating Systems , 132 Synchronization, Part 2 Operating Systems , 132 Synchronization, Part 2

Operating Systems , 132 Synchronization, Part 2 - PowerPoint Presentation

mjnt
mjnt . @mjnt
Follow
349 views
Uploaded On 2020-06-29

Operating Systems , 132 Synchronization, Part 2 - PPT Presentation

Semaphores Semaphores E nable simple synchronization An interface of atomic functions supplying mutual exclusion Programmers dont need to bother with synchronization algorithms Cou nting s ID: 789305

amp mutex pthread buffer mutex amp buffer pthread item question section critical code process semaphore void semaphores processes int

Share:

Link:

Embed:

Download Presentation from below link

Download The PPT/PDF document "Operating Systems , 132 Synchronization,..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

Operating Systems, 132

Synchronization, Part 2

Semaphores

Slide2

Semaphores

E

nable simple synchronization

An interface of atomic functions supplying mutual exclusion

Programmers don’t need to bother with synchronization algorithms

Slide3

Cou

nting

s

emaphore

3

Semaphore’s

interface doesn’t enforce the implementation of starvation freedom.All operations are ATOMIC! That is, up(s) is more than just s:=s+1There is no way to access the semaphore’s internal value. Any attempt to access it is a mistake.Always remember to initialize the semaphore

up(S) [the `v’ operation]If (there are blocked processes) wake-up one of themElse S++

down(S) [the ‘p’ operation]If (S≤0) the process is blocked. It will resume execution only after it is woken-upElse S--

Init(

i

)

S =

i

Slide4

Negative-valued semaphore

4

NOTE:

If S is negative, there are |S| blocked processes

up(S)

[the `v’ operation]

S++

If (there are blocked processes) wake-up one of themdown(S)

S--If (S<0) the process is blocked. It will resume execution only after it is woken-up

Slide5

Counting Semaphores (Barz)

5

down

(S)

down(S2);

down(S1);

S.value--;

if (S.value>0) then up(S2); up(S1);up(S): down(S1); S.value++; if (S.value == 1) then

up(S2); up(S1);S.value=init_value binary-semaphore: S1=1, S2=min(1, init_value), Create a counting semaphore, S, by using binary semaphores??

Variables ?

Slide6

Question 1

Consider the following code snippets run by two processes, P and Q:

Add the minimal number of semaphores, initialize them and place them in the code snippets, so the result of the calculation will be correct (5

2

=25).

Process P

loopP: if (n==0) goto endP; n=n-1; goto loopP;endP: print(sqr)

Process QloopQ: sqr = sqr + 2*n +1; goto loopQ;Shared memoryn=5;sqr=0;6

Slide7

Question 1

Note that we can break 25 in more than one way:

25=11+9+5=[(2*5+1)+(2*4+1)+(2*2+1)]

25=9+7+5+3+1=[(2*4+1)+(2*3+1)+(2*2+1)+(2*1+1)+(0+1)]

Process P

loopP

: if (n==0) goto endP; down(semA); n=n-1;

up(semB); goto loopP;endP: down(semA); print(sqr)Process QloopQ: down(semB); sqr = sqr + 2*n +1; up(semA); goto loopQ;Shared memoryn=5;sqr=0;semA=1;semB=0;7

Slide8

8

Question 2 (2007

Moed

A)

8

The following constraint graph is a DAG that defines a partial order over code lines. Each vertex is associated with a single line of code in a possible program. A directed edge e(

u,v) is used to represent the precedence constraint: code line u must be completed prior to the beginning of code line v.

For example, code line S1 should be completed before S2, S5 or S8 are executed, while S6 can only be executed after both S2 and S5 were completed. 

Slide9

Question 2a

The following code is executed by two processes, A and B.

Process A

Process B

S1

S2 S5 S3 S8 S6

S9 S4 S7

Slide10

10

Question 2a

Use

two counting semaphores

with properly initialized values so that in every execution of A and B the execution order of code lines will be consistent with the constraint graph defined above.

That is, add

up and down operations within A and B’s code lines so that no precedence constraint is violated.You may assume that in every execution both A and B run their code only once.Note: P

artial scoring will be given to solutions using more than two semaphores.10

Slide11

11

Question 2a

Semaphores:

semA

=0,

semB

=0Process A S1 SemB.up S5 SemB.up

S8 S9 SemA.downS7SemB.upProcess BSemB.downS2S3SemB.downS6SemA.up

SemB.downS411

Slide12

12

Question 2b

Give a concise but accurate explanation why a single semaphore is insufficient for maintaining consistency of the above constraint graph and the two processes.

12

Slide13

13

Question 2b

A single semaphore is insufficient because there are constraints which require that A waits until B completes one of its lines and vice versa. In such a state, having A signaling B and immediately waiting for it on the same semaphore will result in either a deadlock or a breaking of one of its constraints.

13

Slide14

Question 3 – Producer Consumer Problem

14

#define N

100

/* Buffer size */

semaphore mutex = 1;

/* access control to critical section */semaphore empty = N; /* counts empty buffer slots */semaphore full = 0; /* full slots */void producer(void) { int item;

while(TRUE) { produce_item(&item); /* generate something... */ down(&empty); /* decrement count of empty */ down(&mutex); /* enter critical section */ enter_item(item); /* insert into buffer */ up(&mutex); /* leave critical section */ up(&full); /* increment count of full slots */

} }

Slide15

void

consume

r

(

void

){ int item; while(TRUE){

down(&full); /* decrement count of full */ down(&mutex); /* enter critical section */ remove_item(&item); /* take item from buffer */ up(&mutex);

/* leave critical section */ up(&empty); /* update count of empty */ consume_item(item); /* do something... */ }}Question 3 – Producer Consumer Problem15

Slide16

Question 3

1. The red lines of the following code were swapped. How will this affect the algorithm?

void

producer

(

void) { int item; while(TRUE) {

produce_item(&item); /* generate something... */ down(&empty); /* decrement count of empty */ down(&mutex); /* enter critical section */ up(&mutex); /* leave critical section */ enter_item

(item); /* insert into buffer */ up(&full); /* increment count of full slots */ } }16No mutual exclusion!

Slide17

Question 3

2. What will happen now?

void

producer

(

void) { int item; while(TRUE) {

produce_item(&item); /* generate something... */ down(&empty); /* decrement count of empty */ down(&mutex); /* enter critical section */ enter_item(item); /* insert into buffer */ up(&full); /* increment count of full slots */ up(&

mutex); /* leave critical section */ } }17No problems…

Slide18

Question 3

3. And now?

void

consume

r

(void){ int item; while(TRUE){

down(&mutex); /* enter critical section */ down(&full); /* decrement count of full */ remove_item(&item); /* take item from buffer */ up(&mutex); /* leave critical section */ up(&empty); /* update count of empty */ consume_item(item);

/* do something... */ }}18Deadlock!

Slide19

Question 4 (Moed

B 2010)

An

unfair semaphore

is a semaphore which does not guarantee that the wakeup order of processes is similar to their falling asleep order.

It does, however, provide the following simple guarantee: if there are sleeping processes on the semaphore while an

up operation is invoked, then one of these processes will be woken up (not necessarily the first amongst the waiting processes to do a down).

Slide20

Question 4

Now you are required to implement a

starvation free mutual exclusion algorithm

for

three processes

using 3

unfair counting semaphores: R, S and T, initialized to 1. You are not allowed to use any other variable but these semaphores. Add your code and complete the entry and exit section of each process.Briefly explain why your code satisfies both mutual exclusion and starvation freedom.

Slide21

Question 4

P1’s code:

entry:

Critical_section

()

exit:

P2’s code:

entry:

Critical_section()exit:P3’s code:entry:Critical_section()

exit:

unfair counting semaphores:

R, S and T initialized to 1

Slide22

Question 4

P1’s code:

entry:

Critical_section

()

exit:

P2’s code:

entry:

Critical_section()exit:P3’s code:entry:Critical_section()

exit:

unfair counting semaphores:

R, S and T initialized to 1

down (S)

down (R)

down (R)

down (T)

down (S)

down (T)

up(R)

up(S)

up(T)

up(R)

up(T)

up (S)

Slide23

Question 4

Mutual exclusion:

Any process wishing to enter its critical section must successfully complete two ‘down’ operations on two distinct semaphores. Since any process competes over one different “successful down” with each of the other processes, only a single process may successfully enter the critical section at any given moment.

Slide24

Question 4

Starvation freedom:

We first note that there is no starvation problem when using an unfair semaphore with 2 processes (convince yourselves!).

Since entrance to the critical section requires passing semaphores which are only shared in pairs no starvation problems will occur.

Slide25

Question 4, supplement

Will this solution work?

P1’s code:

entry:

Critical_section

()

exit:

P2’s code:

entry:Critical_section()exit:P3’s code:entry:

Critical_section

()

exit:

unfair counting semaphores:

R, S and T initialized to 1

down (S)

down (R)

down (R)

down (T)

down (T)

down (S)

up(R)

up(S)

up(T)

up(R)

up(S)

up (T)

Deadlock!

Slide26

Question 5 (Midterm 2009)

בסעיף זה עליכם לממש

event counter

תוך שימוש בסמאפורים בינאריים

וברגיסטרים (משתנים התומכים בקריאות ובכתיבות בלבד). כפי שלמדתם,

event counter E

מכיל ערך שלם ומאותחל ל- 0. הוא תומך בשלוש פעולות אטומיות:פעולת Advance(E) מקדמת את ערכו של E ב-1 מערך v-1 לערך v (כאשר v-1 הוא ערכו של E לפני הפעולה) ומעירה את כל התהליכים אשר ישנו על E בהמתנה לערך

v. פעולת Await(E,v) גורמת לתהליך הקורא לישון עד אשר ערכו של E מגיע ל-v. אם ערכו של E גדול או שווה ל-v בעת הקריאה לפעולת Await, אזי התהליך ממשיך בריצתו. פעולת Read(E) מחזירה את ערכו הנוכחי של E.ממשו event counter תוך שימוש בסמאפורים בינאריים (ניתן להניח כי הם הוגנים). הניחו כי ישנם N תהליכים המשתמשים ב-

E וכי המזהים שלהם הינם 0, 1,…,N-1. כל תהליך יכול להשתמש במשתנה MyID השומר את המזהה שלו.26

Slide27

Question 5

int

waitval

[N] (all are initialized to 0)

int

v = 0semaphore wait[N] (all are initialized to 0)semaphore mutex (initialized to 1)

Advance(E)down(mutex);E.v++;for (i = 0; i < N; i++) if (waitval[i] == E.v)

up(wait[i]);up(mutex);Await(E,v)boolean wait = false;down(mutex)if (v > E.v) { wait = true; waitval[MyId] = v;}up(mutex);if

(wait)

down

(wait[

MyId

]);

Read(E)

return

E.v

;

27

Shared variables

Slide28

Question 5b

Counting semaphore

mutex

=

1

Counting semaphore b=0

register v=0, register waiting=0procedure down( ) { mutex.down( ) if (v == 1){

v=0 mutex.up( )} else { waiting=waiting+1 mutex.up( ) b.down( ) }}procedure up( ){ mutex.down( ) if (waiting > 0){

waiting=waiting-1 b.up( )} else if (v == 0) v=1 mutex.up( )}למדתם כי אין זה פשוט לממש סמאפור כללי (counting semaphore) מסמאפורים בינאריים. מסתבר כי גם הכוון ההפוך אינו פשוט. להלן קטע קוד המכיל מימוש של סמאפור בינארי מסמאפורים כלליים (counting semaphores) ומרגיסטרים.28

Slide29

Question 5b

ניתן להניח כי

הסמאפורים

הכלליים בהם משתמש הקוד שלמעלה הוגנים. עליכם להסביר מדוע קטע הקוד שלמעלה אינו מממש

סמאפור

בינארי בצורה נכונה.

הסבירו במדויק מהי הסמאנטיקה של סמאפור בינארי. בעל טווח הערכים 0, 1בלבדפעולת down: אם ערך הסמאפור הוא 0 אזי חוסם את התהליך, אחרת משנה את ערך הסמאפור ל-0.

פעולת up: אם ישנו תהליך שממתין- מעיר אותו, אחרת משנה את ערך הסמאפור ל-1.29

Slide30

Question 5b

תארו במדויק תסריט בו מספר תהליכים מבצעים פעולות על המימוש לעיל ובו המימוש אינו מקיים סמאנטיקה זו.

Process p1 does down and stops prior to

b.down

Process p2 does down and stops prior to

b.down

Process p3 does up and finishes the operation (b == 1)Process p4 does up and finishes the operation (b == 2)Process p5 does down and finishes the operation (b == 1)

Process p6 does down and finishes the operation (b == 0)התסריט אינו אפשרי כאשר משתמשים בסמפור בינארי מכיוון שלא יכול להיות מצב שבו שני תהליכים יעשו DOWN ושניהם יצליחו.30

Slide31

POSIX synchronization primitives

POSIX defines the following:

Semaphore (counting)

Mutex

Condition variable

Read/Write locks

Slide32

Mutex

Resembles a binary semaphore, but has the notion of ownership. I.e., only the thread which locked the mutex is allowed to unlock it. Supports the following operations:

pthread_mutex_init

(

mutex,attr)pthread_mutex_destroy

(mutex)pthread_mutex_lock (mutex)pthread_mutex_trylock (mutex)pthread_mutex_unlock (mutex)

Slide33

pthread_mutex_init

(

mutex,attr

)

The attributes allow you to set or get:

the 

type (deadlocking, deadlock-detecting, recursive, etc).the robustness (what happens when you acquire a mutex and the original owner died while possessing it).the process-shared attribute (for sharing a mutex across process boundaries, useful for multi-threading and multi-processing).the protocol (how a thread behaves in terms of priority when a higher-priority thread wants the

mutex).the priority ceiling (the priority at which the critical section will run, a way of preventing priority inversion).

Slide34

pthread_mutex_lock

VS.

pthread_mutex_trylock

The 

pthread_mutex_trylock() function shall be equivalent to 

pthread_mutex_lock(), except that if the mutex object referenced by mutex is currently locked the call shall return immediately.If successful, the pthread_mutex_lock() and pthread_mutex_unlock() functions shall return zero; otherwise, an error number shall be returned to indicate the error.The pthread_mutex_trylock

() function shall return zero if a lock on the mutex object referenced by mutex is acquired. Otherwise, an error number is returned to indicate the error.

Slide35

Condition Variables

Are used to wait

until a particular condition occurs

. Enable

threads to atomically release a lock and enter the sleeping state

. A mutex must be associated with a condition variable

. Supports the following operations:pthread_cond_init (condition, attr)pthread_cond_destroy (condition)pthread_cond_wait (condition, mutex)pthread_cond_signal (condition)pthread_cond_broadcast (condition)

Slide36

Producer-consumer problem using mutexes

and condition variables

#include <

pthread.h

>

#include <

stdio.h>#define BSIZE 4

#define NUMITEMS 30typedef struct { char buf[BSIZE]; int occupied; int

nextin, nextout; pthread_mutex_t mutex; pthread_cond_t more; pthread_cond_t less;} buffer_t;

Slide37

buffer_t

buffer

;

void

*

producer(void *);void * consumer(

void *);main( int argc, char *argv[] ) { int i

; buffer.occupied = 0; buffer.nextin = buffer.nextout = 0; pthread_cond_init(&(buffer.more), NULL);

pthread_cond_init

(&(

buffer

.

less

),

NULL

);

pthread_t

tid

[

2

];

pthread_create

(&

tid

[

1

],

NULL

,

consumer

,

NULL

);

pthread_create

(&

tid

[

0

],

NULL

,

producer

,

NULL

);

for

(

i

=

0

;

i

<

NUM_THREADS

;

i

++)

pthread_join

(

tid

[

i

],

NULL

);

printf

(

"main

() reporting that all %d threads have terminated\n"

,

i

);

}

Slide38

void

*

producer

(

void

* parm){ char item[NUMITEMS] =

"IT'S A SMALL WORLD, AFTER ALL."; int i; for(i=0;i<NUMITEMS;i++){ /* produce an item, one character from item[]

*/ if (item[i] == '\0') break; /* stop if at end of string. */ pthread_mutex_lock(&(buffer.mutex)); if (buffer.occupied

>=

BSIZE

)

printf

(

"producer waiting.\n"

);

while

(

buffer

.

occupied

>=

BSIZE

)

pthread_cond_wait

(&(

buffer

.

less

),

&(

buffer

.

mutex

)

);

printf

(

"producer executing.\n"

);

buffer

.

buf

[

buffer

.

nextin

++]

=

item

[

i

];

buffer

.

nextin

%=

BSIZE

;

buffer

.

occupied

++;

pthread_cond_signal

(&(

buffer

.

more

));

pthread_mutex_unlock

(&(

buffer

.

mutex

));

}

}

Slide39

void

*

consumer

(

void

* parm){ char item; int

i; for(i=0;i<NUMITEMS;i++){ pthread_mutex_lock(&(buffer.mutex)

); if (buffer.occupied <= 0) printf("consumer waiting.\n"); while(buffer.occupied <= 0) pthread_cond_wait(&(

buffer

.

more

),

&(

buffer

.

mutex

)

);

printf

(

"consumer executing.\n"

);

item

=

buffer

.

buf

[

buffer

.

nextout

++];

printf

(

"%c\

n"

,

item

);

buffer

.

nextout

%=

BSIZE

;

buffer

.

occupied

--;

pthread_cond_signal

(&(

buffer

.

less

));

pthread_mutex_unlock

(&(

buffer

.

mutex

));

}

}