Top Banner
Critical Sections and Semaphores •A critical section is code that contains access to shared resources that can accessed by multiple processes. • Critical sections can be managed with semaphores • This chapter describes POSIX.1b semaphores and System V semaphores
57

Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Dec 19, 2015

Download

Documents

Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Critical Sections and Semaphores

• A critical section is code that contains access to shared resources that can accessed by multiple processes.

• Critical sections can be managed with semaphores

• This chapter describes POSIX.1b semaphores and System V semaphores

Page 2: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Protecting CS

• Mutual Exclusion – Only one process is in CS at a time

• Progress – If no process is in CS, a process that wishes to can get in

• Bounded Wait – No process can be postponed indefinitely (starved)

Page 3: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Non-Atomic Operations

Implementations of: c++; and c–– ;

r1 = c; r2 = c;r1 = r1 + 1; r2 = r2 – 1;c = r1; c = r2;

c = 6;Process A Process B…; c++; … …; c ––; …

At the end of processes A and B we expect c to be incremented and decremented so the final value is 6.

However, if process A is interrupted after completing the instruction r1 = c; and process B executes to completion, c = 5 at the end of B and it is set to 7 after A finishes

Page 4: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

test-and-set/swap

• Test-and-Set and Swap are routines implemented in hardware to coordinate lower level critical sections such as the implementing of a semaphore counter

• Review section 8.1 if you are unfamiliar with these operations

Page 5: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Busy-Wait Semaphoreswait – while (*s <= 0) noop;

(*s)––;signal – (*s)++;

*s = 1;Process A Process Bwait(&s); wait(&s);c++; c––;signal(&s); signal(&s);

• Busy-wait implementations waste CPU cycles• One process can starve the others

Page 6: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Waiting List Semaphores

wait – if (sp->value > 0) sp->value ––;

else { <block the current process and add it to waiting list sp->list>

signal – if (sp->list != NULL) <remove process at head of semaphore queue and place it in

ready queue>else sp->value++;

Page 7: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Motivation for ‘and’ Syncronization*A = 1; *B = 1;Process 1 Process 2 Process 3wait(&A); wait(&A); wait(&B);<use resource A> wait(&B); <use resource B>signal(&A); <use resources A and B> signal(&B);

signal(&B);signal(&A);

Page 8: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

‘and’ Syncronization*A = 1; *B = 1;

Process 1 Process 2 Process 3

wait(&A); wait(&A, &B); wait(&B);

<use resource A> <use resources A and B> <use resource B>

signal(&A); signal(&A, &B); signal(&B);

wait(&A, &B) denotes simultaneous wait on A and B. The semaphores A and B are decremented only if both of them can decremented without blocking

Page 9: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

‘and’ Syncronization Implementationwait – if ((ap->value > 0) && (bp->value > 0)) { (ap->value)--;

(bp->value)--; }

else if (ap->value <= 0) <add current process to ap->list> else <add current process to bp->list> <block process and reset pc to beginning of wait>

signal – ap->value++; <move all processes on ap->list to ready queue> bp->value++; <move all processes on bp->list to ready queue>

Page 10: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Why Wake All Processes on Signal?

Process 1 Process 2 Process 3

a1: wait(&A,&B); a2: wait(&B,&C); a3: signal(&B,&C);

b1: <critical section> b2: <critical section>

c1: signal(&A,&B); c2: signal(&B,&C);

Assume a1 is executed followed by a2, the semaphore queues are:

A: process 1

B: process 1, process 2

C: process 2

Then, if a3 is executed and the signal only wakes up the first process in each queue, the semaphore queues are:

A: process 1

B: process 2

C:

Now process 1 holds B while blocking on A. Process 2 cannot proceed until process 1 gets A. This defeats the purpose of

‘and’ synchronization

Page 11: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

POSIX.1b Semaphores

• POSIX.1b standard was adopted in 1993• Since they are new, POSIX semaphores may not

be available in all operating systems – even those that claim to be POSIX.1 compliant

• An implementation supports POSIX semaphores if _POSIX_SEMAPHORES is defined in unistd.h – It is defined there on the ect-unix machines

Page 12: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

POSIX.1b Semaphore Variables

• Semaphore variable is of type sem_t• Atomic operations for initializing, incrementing

and decrementing value• Unnamed semaphores – Can be used by a single

process or by children of a process that created it• Named semaphores – Can be used by all processes• Unnamed semaphores are similar in operation to

pipes, and named semaphores are similar to named pipes

Page 13: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

POSIX.1b Semaphore Declaration

#include <semaphore.h>sem_t sem;

• sem is a semaphore variable• POSIX.1b does not specify underlying type of

sem_t• One possibility is for it to act like a file descriptor

that points to a local table and the table entries point to entries in a system file table

Page 14: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore OperationsSYNOPSIS

#include <semaphore.h>

int sem_init (sem_t *sem, int pshared, unsigned int value);

int sem_destroy (sem_t *sem);

int sem_wait (sem_t *sem);

int sem_try (sem_t *sem);

int sem_post (sem_t *sem);

int sem_getvalue (sem_t *sem, int *sval);

POSIX.1b

• All semaphore functions return –1 and set errno on error

• It is uncertain what semaphore functions return on success, but usually 0

• _POSIX_SEMAPHORES may be defined but system may NOT support POSIX.1b semaphores

• POSIX.1b semaphores are counting semaphores

Page 15: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_init

• Initializes semaphore to value parameter• If the value of pshared is non-zero, the semaphore

can be used between processes (the process that initializes it and by children of that process)

• If the value of pshared is zero, the semaphore can only be used by threads of a single process

• Think of sem as referring to a semaphore rather than being the semaphore itself

Page 16: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_destroy

• Destroys a previously initialized semaphore

• If sem_destroy attempts to destroy a semaphore that is being used by another process, it may return –1 and set errno to EBUSY – Unfortunately, the specifications do not require that the system detect this

Page 17: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_wait and sem_trywait• sem_wait is a standard semaphore wait

operation

• If the semaphore value is 0, sem_wait blocks until it can successfully decrement value or when interrupted such as by SIGINT

• sem_trywait is similar to sem_wait except instead of blocking on 0, it returns –1 and sets errno to EAGAIN

Page 18: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_post

• sem_post increments the semaphore value and is the classical semaphore signal operation

• sem_post must be async_signal_safe and may be invoked from a signal handler

Page 19: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_getvalue

• Allows the user to examine the value of a named or unnamed semaphore

• Sets the integer referenced by sval to the value of the semaphore

• If there are processes waiting for the semaphore, POSIX.1b allows setting sval to either 0 or a negative number whose absolute value is equal to the number of waiting processes – ambiguity!

• Returns 0 on success and –1 and sets errno on error

Page 20: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Unnamed Semaphore Example

#include <semaphore.h>…void main();{

…if (sem_init(&my_lock, 1, 1) {

perror(“could not initialize my_lock semaphore);…for (i = 1; i < n; ++i)

if (childpid = fork()) break;…if (sem_wait (&my_lock) == – 1) {

perror (“semaphore invalid); exit (1); }Critical Section

if (sem_post (&my_lock) == – 1) { perror (“semaphore done”); exit(1); }

… }

Page 21: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Named Semaphores

• Named semaphores can synchronize processes that do not have common ancestors

• Have a name, user ID, group ID and permissions just like files do

• POSIX.1b does not require name to appear in file system nor does it specify consequences of having two processes refer to same name

• If name begins with a slash (/), two processes (or threads) open the same semaphore

Page 22: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_openSYNOPSIS

#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);

sem_t *sem_open(const char *namd, int oflag, mode_t mode,

unsigned int value);

POSIX.1b

• sem_open establishes a connection between a named semaphore and a sem_t value

• sem_open returns a pointer identifying the semaphore

Page 23: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_open oflag parameter• oflag determines whether sem_open access a

previously defined semaphore or creates a new one

• If oflag is 0 the semaphore is previously defined with the same name – If no such name is found sem_open returns –1 and sets errno to ENOENT

• oflag of O_CREAT or O_CREAT|O_EXCL means the semaphore is not previously defined and requires the second form of sem_open that includes permissions and semaphore value

• oflag of O_CREAT|O_EXCL opens a semaphore if one of that name does not exist or returns –1 if one DOES exist and sets errno to EEXIST

Page 24: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_closeSYNOPSIS#include < semaphore.h>int sem_close (sem_t *sem);int sem_unlink(const char *name);

POSIX.1b

• A process calls sem_close to deallocate system resources allocated to the user of the semaphore

• sem_close does not necessarily remove the semaphore, but makes it inaccessible to the process

• _exit and exec system calls also deallocate process semaphores

Page 25: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_unlink

• sem_unlink removes a named semaphore from the system

• If there is still a reference to the semaphore, destruction is delayed until the other references are closed by sem_close, _exit or exec

• Calls to sem_open with the same name after sem_unlink with refer to a different semaphore

Page 26: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Named Semaphore Example – (top)#include <semaphore.h>

#define S_MODE S_IRUSR | S_IWUSR

void main();

{

if ((my_lock = sem_open (“my.dat”, O_CREAT|O_EXCL,

S_MODE, 1) == – 1) && errno == ENOENT) {

perror(“semaphore open failed”); exit(1); }

for (i = 1; i < n; ++i)

if (childpid = fork()) break;

Page 27: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Named Semaphore Example – (bottom)

if (sem_wait (&my_lock) == – 1) {

perror (“semaphore invalid); exit (1); }

Critical Section

if (sem_post (&my_lock) == – 1) {

perror (“semaphore done”); exit(1); }

if (sem_close (&my_lock) == – 1) {

perror(“semaphore close failed”); exit(1); }

}

Page 28: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

System V Semaphores

• System V semaphores are part of the general System V interprocess communication facility

• A System V semaphore is created by executing a semget system call

• The semget creats a semaphore data structure in the kernel and returns an integer handle to the semaphore

• Processes cannot access semaphore data structures directly – only through system calls

• Semaphore ids or handles are analogous to file descriptors

Page 29: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Posix vs System V Semaphores

• System V semaphores, shared memory and message queues are not part of POSIX.1 – they are included in the Spec 1170 specification

• System V data structures are created and kept in the kernel and are referenced through integer handles

• In POSIX.1, a program declares a variable of type sem_t and passes a pointer to that variable

Page 30: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore Sets• A semaphore set is an array of semaphore elements

• A process can perform operations on the entire set in a single system call

• The internal representation of semaphore sets and semaphore elements is not directly accessible

• Each semaphore includes at least the following:

– A nonnegative integer representing semaphore value

– Process ID of the last process to manipulate the semaphore element

– Number of processes waiting for the semaphore element to increase

– Number of processes waiting for the semaphore element value to equal 0

Page 31: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore Sets (Cont)

• Semaphore operations allow a process to block until a semaphore element value is 0 or until it becomes positive

• Each element has two queues associated with it – a queue of processes waiting for the semaphore element value to increase and a queue of processes waiting for the value to equal 0

Page 32: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore Creation

SYNOPSIS

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semget (key_t key, int nsems, int semflg);

Spec 1170

Page 33: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

IPC_PRIVATE

#include <stdio.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#define PERMS S_IRUSR|S_IWUSR#define SET_SIZE 3

int semid;

void main(void){ int seimid;

if ((semid = semget(IPC_PRIVATE, SET_SIZE, PERMS)) < 0) perror("Could not create new private semaphore"); else printf("Semaphore created with ID %d\n",semid);}

Page 34: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

#include <stdio.h>#include <sys/stat.h>#include <sys/ipc.h>#include <sys/sem.h>#include <string.h>#include <errno.h>#define PERMS S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH#define SET_SIZE 1#define KEY ((key_t)99887)void main(void){ int semid; if ((semid = semget(KEY, SET_SIZE, PERMS | IPC_CREAT)) < 0) fprintf(stderr, "Error creating semaphore with key %d: %s\n", (int)KEY, strerror(errno)); else printf("Semaphore with ID %d created for key %d\n",semid,(int)KEY);}

Random Key

Page 35: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Generate Key from ftok int semid; key_t mykey;

if (argc != 3) { fprintf(stderr, "Usage: %s filename id\n", argv[0]); exit(1); } if ((mykey = ftok(argv[1], atoi(argv[2]))) == (key_t) -1) { fprintf(stderr, "Could not derive key from filename %s: %s\n", argv[1], strerror(errno)); exit(1); } else if ((semid = semget(mykey, SET_SIZE, PERMS | IPC_CREAT)) < 0) { fprintf(stderr, "Error creating semaphore with key %d: %s\n", (int)mykey, strerror(errno)); exit(1);

Page 36: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

semopSYNOPSIS#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semop(int semid, struct sembuf *sops, int nsops);

Spec 1170• A process can increment, decrement or test individual

semaphore elements with the semop system call• semid is handle returned by semget• sops points to an array of element operations• nsops specifies the number of element operations in the

sops array• semop returns –1 and sets errno on error

Page 37: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

struct sembuf

• struct sembuf has the following three fields– short sem_num: The number of the semaphore

element– short sem_op: The particular operation to be

performed on the semaphore element– shore sem_flg: The flags to specify options for

the opration

Page 38: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_op• If sem_op > 0, semop adds the value to the corresponding

semaphore element and awakens processes waiting for semaphore element to increase

• If sem_op = 0, and semaphore element value is not 0, semop blocks the calling process (waiting for 0) and increments the count of processes waiting for a zero value of that element

• If sem_op < 0, semop adds the value to the corresponding semaphore element value provided the result would not be negative. If the operation would make the element value negative, semop blocks the process on the event that the semaphore element value increases. If the resulting value is 0, semop wakes the processes waiting for 0

Page 39: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

set_sembuf_struct/* Example 8.21 */#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>

void set_sembuf_struct(struct sembuf *s, int num, int op, int flg)

{ s->sem_num = (short) num; s->sem_op = op; s->sem_flg = flg; return;}

Do not set sembuf elements in a declaration such as:struct sembuf myopbuf = {1, –1, 0}

Page 40: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore – Example 1struct sembuf GET_TAPES[2]struct sembuf RELEASE_TAPES[2]set_sembuf_struct(&(GET_TAPES[0]), 0,–1,0);set_sembuf_struct(&(GET_TAPES[1]), 1,–1,0);set_sembuf_struct(&(RELEASE_TAPES[0]), 0,1,0);set_sembuf_struct(&(RELEASE_TAPES[0]), 1,1,0);Process 1: semop(S, GET_TAPES,1);

<use tape A>semop(S, RELEASE_TAPES,1);

Process 2: semop(S,GET_TAPES,2);<use tapes A and B>

semop(S,RELEASE_TAPES,2);Process 3: semop(S, GET_TAPES + 1,1);

<use tape B>semop(S, RELEASE_TAPES + 1,1);

Page 41: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

struct sembuf – Example 1

GET_TAPES[0] RELEASE_TAPES[0]

num = 0 num = 0

op = –1 op = 1

flg = 0 flg = 0

GET_TAPES[1] RELEASE_TAPES[1]

num = 1 num = 1

op = –1 op = 1

flg = 0 flg = 0

Page 42: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore – Ex 2 (1)…

int semid; int semop_ret; struct sembuf semwait[1]; struct sembuf semsignal[1]; … if ( (argc != 2) || ((n = atoi (argv[1])) <= 0) ) { fprintf (stderr, "Usage: %s number_of_processes\n", argv[0]); exit(1); } /* Create a semaphore containing a single element */ if ((semid = semget(IPC_PRIVATE, SET_SIZE, PERMS)) == -1) { fprintf(stderr, "[%ld]: Could not access semaphore: %s\n", (long)getpid(), strerror(errno)); exit(1); }

Page 43: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore – Ex 2 (2)/* Initialize the semaphore element to 1 */

set_sembuf_struct(semwait, 0, -1, 0);

set_sembuf_struct(semsignal, 0, 1, 0);

if (semop(semid, semsignal, 1) == -1) {

fprintf(stderr, "[%ld]: semaphore increment failed - %s\n",

(long)getpid(), strerror(errno));

if (remove_semaphore(semid) == -1)

fprintf(stderr, "[%ld], could not delete semaphore - %s\n",

(long)getpid(), strerror(errno));

exit(1);

}

Page 44: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

for (i = 1; i < n; ++i) if (childpid = fork()) break; Each child sends pid and ppid info to buffer while(( (semop_ret = semop(semid, semwait, 1)) == -1) && (errno == EINTR)) ; if (semop_ret == -1) fprintf(stderr, "[%ld]: semaphore decrement failed - %s\n", (long)getpid(), strerror(errno)); else { Each child prints out its pid and ppid buffer while(((semop_ret = semop(semid, semsignal, 1)) == -1) && (errno == EINTR)) ; if (semop_ret == -1) fprintf(stderr, "[%ld]: semaphore increment failed - %s\n", (long)getpid(), strerror(errno)); }

Semaphore – Ex 2 (3)

Page 45: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore – Ex 2 (4)

while((wait(&status) == -1) && (errno == EINTR)) ; if (i == 1) /* the original process removes the semaphore */ if (remove_semaphore(semid) == -1) fprintf(stderr, "[%ld], could not delete semaphore - %s\n", (long)getpid(), strerror(errno)); exit(0);}

Page 46: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Semaphore – Example 3#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include < string.h>#include < errno.h>#define SET_SIZE 2struct sembuf myop[SET_SIZE];set_sembuf_struct(&(myop[0]), 0, 0, 0);set_sembuf_struct(&(myop[1]), 0, 1, 0);if (semop(semid, myop, 2) == -1)

perror(“Semaphore operation failed”);

Page 47: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

struct sembuf – Example 2

myop[0]

num = 0

op = 0

flg = 0

myop[1]

num = 0

op = 1

flg = 0

Page 48: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

#include <sys/stat.h>#include <sys/ipc.h>#include <sys/sem.h>#include <stdio.h>#include <errno.h>#define PERMS S_IRUSR|S_IWUSR#define SET_SIZE 2int create_and_initialize(key_t mykey, int value){ int semid; struct sembuf getlock, setlock, setinit; semid = semget(mykey, SET_SIZE, PERMS|IPC_CREAT|IPC_EXCL); if ((semid < 0) && (errno != EEXIST)) { perror("Semaphore create failed"); return -1; } else if (semid > 0) { /* initialize the semaphore and open the lock */ set_sembuf_struct(&setinit, 1, value, 0); semop(semid, &setinit, 1); set_sembuf_struct(&setlock, 0, 1, 0); semop(semid, &setlock, 1);

Create and Set Semaphore (top)

Page 49: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Create and Set Semaphore (bottom)

} else { /* semaphore already exists -- wait for initialization */ if ((semid = semget(mykey, SET_SIZE, PERMS)) < 0) { perror("Could not access existing semaphore"); return -1; } set_sembuf_struct(&getlock, 0, -1, 0); semop(semid, &getlock, 1); set_sembuf_struct(&setlock, 0, 1, 0); semop(semid, &setlock, 1); } return semid;}

Page 50: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

semctl

#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, /* union semun arg */• semctl querries or sets the values of individual semaphore

elements• semid identifies the semaphore set• semnum indicates the semaphore element within the set• cmd refers to individual elements and specifies which

command is to be executed• arg is used differently for different cmd values

Page 51: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Important CommandsGETVAL: Return the value of a specific semaphore elementGETPID: Return process ID of last process to manipulate

elementGETNCNT: Return number of processes waiting for element to

incrementGETZCNT: Return number of processes waiting for element to

become 0SETVAL: Set value of a specific semaphore element to

arg.valIPC_RMID: Remove the semaphore identified by semidIPC_SET: Set the permissions of the semaphore

semctl returns –1 on error and and sets errno – On success the return value is 0 for all commands except GETVAL, GETPID, GETNCNT, and GETZCNT return the value of the command

Page 52: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

semnum Paramater

union semnum {int val;struct semid_ds *buf;ushort *array; };

May not be included directly in programs, since some systems do not define it in semaphore header files

Page 53: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

…int initialize_sem_element(int semid, int semnum, int semvalue){ union semun arg; arg.val = semvalue; return semctl(semid, semnum, SETVAL, arg);}

void main(void){ int semid; int retval;

if ((semid = semget(IPC_PRIVATE, 2, 0600)) < 0) perror("Could not create new private semaphore"); retval = initialize_sem_element(semid,1,3); printf("initialize_sem_element returned %d\n",retval);}

initialize_sem_element returns 0 on success and –1 and sets errno on error

initialize _sem_element

Page 54: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

remove_semaphore

/* Example 8.26 */#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h> int remove_semaphore(int semid){ return semctl(semid, 0, IPC_RMID);}

Page 55: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

Command Prompt Semaphore Ops

• List all semaphores: ipcs –s

• Remove semaphore id 12345: ipcrm 12345

Page 56: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

/* Example 8.29 */#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>#include <errno.h>

int semop_restart(int semid, struct sembuf *sops, int nsops)

{ int retval; while ( ((retval = semop(semid, sops, nsops))

== -1) && (errno == EINTR) ) ; return retval;}

semop_restart

Page 57: Critical Sections and Semaphores A critical section is code that contains access to shared resources that can accessed by multiple processes. Critical.

sem_wait_restart

/* Example 8.30 */#include <semaphore.h>#include <errno.h>

int sem_wait_restart(sem_t *sem){ int retval; while ( ((retval = sem_wait(sem)) == -1) && (errno == EINTR) ) ; return retval;}