Synchronization and Deadlock in Computer Systems: A Study of Semaphores and Shared Buffers, Slides of Computer System Design and Architecture

The concepts of synchronization in computer systems, focusing on the producer-consumer and readers-writers problems, thread safety, races, and deadlocks. It also delves into the use of semaphores to schedule access to shared resources and the implementation of a shared buffer package using semaphores. Examples of thread-unsafe functions and deadlock avoidance strategies are provided.

Typology: Slides

2010/2011

Uploaded on 10/08/2011

rolla45
rolla45 šŸ‡ŗšŸ‡ø

4

(6)

133 documents

1 / 39

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Carnegie Mellon
1
Synchroniza+on:-Advanced-
15#213:'Introduc0on'to'Computer'Systems'
24th'Lecture,'Nov.'18,'2010'
Instructors:''
Randy'Bryant'and'Dave'O’Hallaron'
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27

Partial preview of the text

Download Synchronization and Deadlock in Computer Systems: A Study of Semaphores and Shared Buffers and more Slides Computer System Design and Architecture in PDF only on Docsity!

Synchroniza+on: Advanced

15-­‐213: Introduc0on to Computer Systems

th

Lecture, Nov. 18, 2010

Instructors:

Randy Bryant and Dave O’Hallaron

Today

ļ‚¢ Producer-­‐consumer problem

ļ‚¢ Readers-­‐writers problem

ļ‚¢ Thread safety

ļ‚¢ Races

ļ‚¢ Deadlocks

Producer-­‐Consumer Problem

ļ‚¢ Common synchroniza+on paGern:

ļ‚§ Producer waits for empty slot , inserts item in buffer, and no0fies consumer

ļ‚§ Consumer waits for item , removes it from buffer, and no0fies producer

ļ‚¢ Examples

ļ‚§ Mul0media processing:

ļ‚§ Producer creates MPEG video frames, consumer renders them

ļ‚§ Event-­‐driven graphical user interfaces

ļ‚§ Producer detects mouse clicks, mouse movements, and keyboard hits

and inserts corresponding events in buffer

ļ‚§ Consumer retrieves events from buffer and paints the display

producer

thread

shared

buffer

consumer

thread

Producer-­‐Consumer on 1-­‐element Buffer

#include ā€œcsapp.hā€ #define NITERS 5 void *producer(void *arg); void *consumer(void arg); struct { int buf; / shared var / sem_t full; / sems */ sem_t empty; } shared; int main() { pthread_t tid_producer; pthread_t tid_consumer; _/ Initialize the semaphores /_ Sem_init(&shared.empty, 0, 1); Sem_init(&shared.full, 0, 0); _/ Create threads and wait /_ Pthread_create(&tid_producer, NULL, producer, NULL); Pthread_create(&tid_consumer, NULL, consumer, NULL); Pthread_join(tid_producer, NULL); Pthread_join(tid_consumer, NULL); exit(0); }

Producer-­‐Consumer on an n -­‐element Buffer

ļ‚¢ Requires a mutex and two coun+ng semaphores:

ļ‚§ mutex: enforces mutually exclusive access to the the buffer

ļ‚§ slots: counts the available slots in the buffer

ļ‚§ items: counts the available items in the buffer

ļ‚¢ Implemented using a shared buffer package called sbuf.

sbuf Package -­‐ Declara+ons

#include "csapp.hā€

typedef struct {

int buf; / Buffer array */

int n; /* Maximum number of slots */

int front; /* buf[(front+1)%n] is first item */

int rear; /* buf[rear%n] is last item */

sem_t mutex; /* Protects accesses to buf */

sem_t slots; /* Counts available slots */

sem_t items; /* Counts available items */

} sbuf_t;

void sbuf_init(sbuf_t *sp, int n);

void sbuf_deinit(sbuf_t *sp);

void sbuf_insert(sbuf_t *sp, int item);

int sbuf_remove(sbuf_t *sp);

sbuf.h

sbuf Package -­‐ Implementa+on

/* Insert item onto the rear of shared buffer sp */ void sbuf_insert(sbuf_t sp, int item) { P(&sp->slots); / Wait for available slot / P(&sp->mutex); / Lock the buffer / sp->buf[(++sp->rear)%(sp->n)] = item; / Insert the item / V(&sp->mutex); / Unlock the buffer / V(&sp->items); / Announce available item */ }

sbuf.c

Inser+ng an item into a shared buffer:

sbuf Package -­‐ Implementa+on

/* Remove and return the first item from buffer sp */ int sbuf_remove(sbuf_t sp) { int item; P(&sp->items); / Wait for available item / P(&sp->mutex); / Lock the buffer / item = sp->buf[(++sp->front)%(sp->n)]; / Remove the item / V(&sp->mutex); / Unlock the buffer / V(&sp->slots); / Announce available slot */ return item; }

sbuf.c

Removing an item from a shared buffer:

Readers-­‐Writers Problem

ļ‚¢ Generaliza+on of the mutual exclusion problem

ļ‚¢ Problem statement:

ļ‚§ Reader threads only read the object

ļ‚§ Writer threads modify the object

ļ‚§ Writers must have exclusive access to the object

ļ‚§ Unlimited number of readers can access the object

ļ‚¢ Occurs frequently in real systems, e.g.,

ļ‚§ Online airline reserva0on system

ļ‚§ Mul0threaded caching Web proxy

Variants of Readers-­‐Writers

ļ‚¢ First readers-­‐writers problem (favors readers)

ļ‚§ No reader should be kept wai0ng unless a writer has already been

granted permission to use the object.

ļ‚§ A reader that arrives a[er a wai0ng writer gets priority over the

writer.

ļ‚¢ Second readers-­‐writers problem (favors writers)

ļ‚§ Once a writer is ready to write, it performs its write as soon as

possible

ļ‚§ A reader that arrives a[er a writer must wait, even if the writer is

also wai0ng.

ļ‚¢ Starva5on (where a thread waits indefinitely) is possible

in both cases.

Case Study: Prethreaded Concurrent Server

Master

thread

Buffer

Accept ...

connec5ons Insert descriptors (^) Remove descriptors

Worker

thread

Worker

thread

Client

Client

Service client Service client

Pool of

worker

threads

Prethreaded Concurrent Server

sbuf_t sbuf; /* Shared buffer of connected descriptors */ int main(int argc, char *argv) { int i, listenfd, connfd, port; socklen_t clientlen=sizeof(struct sockaddr_in); struct sockaddr_in clientaddr; pthread_t tid; port = atoi(argv[1]); sbuf_init(&sbuf, SBUFSIZE); listenfd = Open_listenfd(port); for (i = 0; i < NTHREADS; i++) / Create worker threads */ Pthread_create(&tid, NULL, thread, NULL); while (1) { connfd = Accept(listenfd, (SA ) &clientaddr, &clientlen); sbuf_insert(&sbuf, connfd); / Insert connfd in buffer */ } }

echoservert_pre.c

Prethreaded Concurrent Server

static int byte_cnt; /* Byte counter / static sem_t mutex; / and the mutex that protects it */ static void init_echo_cnt(void) { Sem_init(&mutex, 0, 1); byte_cnt = 0; }

echo_cnt.c

echo_cnt ini+aliza+on rou+ne:

Prethreaded Concurrent Server

void echo_cnt(int connfd) { int n; char buf[MAXLINE]; rio_t rio; static pthread_once_t once = PTHREAD_ONCE_INIT; Pthread_once(&once, init_echo_cnt); Rio_readinitb(&rio, connfd); while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { P(&mutex); byte_cnt += n; printf("thread %d received %d (%d total) bytes on fd %d\nā€, (int) pthread_self(), n, byte_cnt, connfd); V(&mutex); Rio_writen(connfd, buf, n); } }

Worker thread service rou+ne:

echo_cnt.c