Critical Sections and Semaphores - PowerPoint PPT Presentation

1 / 57
About This Presentation
Title:

Critical Sections and Semaphores

Description:

Critical Sections and Semaphores. A critical section is code that contains access ... A. Process 2 cannot proceed until process 1 gets A. This defeats the purpose of ... – PowerPoint PPT presentation

Number of Views:246
Avg rating:3.0/5.0
Slides: 58
Provided by: ralphh
Category:

less

Transcript and Presenter's Notes

Title: Critical Sections and Semaphores


1
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

2
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)

3
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

4
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

5
Busy-Wait Semaphores
  • wait while (s lt 0) noop
  • (s)
  • signal (s)
  • s 1
  • Process A Process B
  • wait(s) wait(s)
  • c c
  • signal(s) signal(s)
  • Busy-wait implementations waste CPU cycles
  • One process can starve the others

6
Waiting List Semaphores
  • wait if (sp-gtvalue gt 0)
  • sp-gtvalue
  • else
  • ltblock the current process and add it to
    waiting list sp-gtlistgt
  • signal if (sp-gtlist ! NULL)
  • ltremove process at head of semaphore queue
    and place it in
  • ready queuegt
  • else
  • sp-gtvalue

7
Motivation for and Syncronization
  • A 1 B 1
  • Process 1 Process 2 Process 3
  • wait(A) wait(A) wait(B)
  • ltuse resource Agt wait(B) ltuse resource Bgt
  • signal(A) ltuse resources A and Bgt signal(B)
  • signal(B)
  • signal(A)

8
and Syncronization
A 1 B 1 Process 1 Process 2 Process
3 wait(A) wait(A, B) wait(B) ltuse
resource Agt ltuse resources A and Bgt ltuse
resource Bgt 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
9
and Syncronization Implementation
  • wait if ((ap-gtvalue gt 0) (bp-gtvalue gt 0))
  • (ap-gtvalue)--
  • (bp-gtvalue)--
  • else
  • if (ap-gtvalue lt 0)
  • ltadd current process to ap-gtlistgt
  • else
  • ltadd current process to bp-gtlistgt
  • ltblock process and reset pc to beginning of
    waitgt
  • signal ap-gtvalue
  • ltmove all processes on ap-gtlist to ready
    queuegt
  • bp-gtvalue
  • ltmove all processes on bp-gtlist to ready queuegt

10
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 ltcritical sectiongt b2 ltcritical sectiongt
  • 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

11
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

12
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

13
POSIX.1b Semaphore Declaration
  • include ltsemaphore.hgt
  • 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

14
Semaphore Operations
  • SYNOPSIS
  • include ltsemaphore.hgt
  • 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

15
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

16
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

17
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

18
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

19
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

20
Unnamed Semaphore Example
  • include ltsemaphore.hgt
  • void main()
  • if (sem_init(my_lock, 1, 1)
  • perror(could not initialize my_lock
    semaphore)
  • for (i 1 i lt 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)

21
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

22
sem_open
  • SYNOPSIS
  • include ltsemaphore.hgt
  • 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

23
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_CREATO_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_CREATO_EXCL opens a semaphore if one
    of that name does not exist or returns 1 if one
    DOES exist and sets errno to EEXIST

24
sem_close
  • SYNOPSIS
  • include lt semaphore.hgt
  • 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

25
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

26
Named Semaphore Example (top)
include ltsemaphore.hgt define S_MODE S_IRUSR
S_IWUSR void main() if ((my_lock sem_open
(my.dat, O_CREATO_EXCL, S_MODE, 1) 1)
errno ENOENT) perror(semaphore open
failed) exit(1) for (i 1 i lt n
i) if (childpid fork()) break
27
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)
28
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

29
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

30
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

31
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

32
Semaphore Creation
  • SYNOPSIS
  • include ltsys/types.hgt
  • include ltsys/ipc.hgt
  • include ltsys/sem.hgt
  • int semget (key_t key, int nsems, int semflg)
  • Spec 1170

33
IPC_PRIVATE
include ltstdio.hgtinclude ltsys/stat.hgtinclude
ltsys/types.hgtinclude ltsys/ipc.hgtinclude
ltsys/sem.hgtdefine PERMS S_IRUSRS_IWUSRdefine
SET_SIZE 3int semidvoid main(void) int
seimid if ((semid semget(IPC_PRIVATE,
SET_SIZE, PERMS)) lt 0) perror("Could not
create new private semaphore") else
printf("Semaphore created with ID d\n",semid)
34
Random Key
include ltstdio.hgtinclude ltsys/stat.hgtinclude
ltsys/ipc.hgtinclude ltsys/sem.hgtinclude
ltstring.hgtinclude lterrno.hgtdefine PERMS
S_IRUSRS_IWUSRS_IRGRPS_IWGRPS_IROTHS_IWOTHd
efine SET_SIZE 1define KEY ((key_t)99887)void
main(void) int semid if ((semid
semget(KEY, SET_SIZE, PERMS IPC_CREAT)) lt 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)

35
Generate Key from ftok
int semid key_t mykey if (argc ! 3)
fprintf(stderr, "Usage s filename
id\n", argv0) exit(1) if
((mykey ftok(argv1, atoi(argv2)))
(key_t) -1) fprintf(stderr, "Could not
derive key from filename s s\n",
argv1, strerror(errno)) exit(1)
else if ((semid semget(mykey, SET_SIZE, PERMS
IPC_CREAT)) lt 0) fprintf(stderr, "Error
creating semaphore with key d s\n",
(int)mykey, strerror(errno)) exit(1)
36
semop
  • SYNOPSIS
  • include ltsys/types.hgt
  • include ltsys/ipc.hgt
  • include ltsys/sem.hgt
  • 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

37
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

38
sem_op
  • If sem_op gt 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 lt 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

39
set_sembuf_struct
/ Example 8.21 /include ltsys/types.hgtinclude
ltsys/ipc.hgtinclude ltsys/sem.hgtvoid
set_sembuf_struct(struct sembuf s, int num,
int op, int flg) s-gtsem_num (short)
num s-gtsem_op op s-gtsem_flg flg
return Do not set sembuf elements in a
declaration such as struct sembuf myopbuf 1,
1, 0
40
Semaphore Example 1
  • struct sembuf GET_TAPES2
  • struct sembuf RELEASE_TAPES2
  • set_sembuf_struct((GET_TAPES0), 0,1,0)
  • set_sembuf_struct((GET_TAPES1), 1,1,0)
  • set_sembuf_struct((RELEASE_TAPES0), 0,1,0)
  • set_sembuf_struct((RELEASE_TAPES0), 1,1,0)
  • Process 1 semop(S, GET_TAPES,1)
  • ltuse tape Agt
  • semop(S, RELEASE_TAPES,1)
  • Process 2 semop(S,GET_TAPES,2)
  • ltuse tapes A and Bgt
  • semop(S,RELEASE_TAPES,2)
  • Process 3 semop(S, GET_TAPES 1,1)
  • ltuse tape Bgt
  • semop(S, RELEASE_TAPES 1,1)

41
struct sembuf Example 1
  • GET_TAPES0 RELEASE_TAPES0
  • num 0 num 0
  • op 1 op 1
  • flg 0 flg 0
  • GET_TAPES1 RELEASE_TAPES1
  • num 1 num 1
  • op 1 op 1
  • flg 0 flg 0

42
Semaphore Ex 2 (1)
int semid int semop_ret struct
sembuf semwait1 struct sembuf
semsignal1 if ( (argc ! 2) ((n
atoi (argv1)) lt 0) ) fprintf (stderr,
"Usage s number_of_processes\n", argv0)
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)
43
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)

44
Semaphore Ex 2 (3)
for (i 1 i lt 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))
45
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)
46
Semaphore Example 3
  • include ltstdio.hgt
  • include ltsys/types.hgt
  • include ltsys/ipc.hgt
  • include ltsys/sem.hgt
  • include lt string.hgt
  • include lt errno.hgt
  • define SET_SIZE 2
  • struct sembuf myopSET_SIZE
  • set_sembuf_struct((myop0), 0, 0, 0)
  • set_sembuf_struct((myop1), 0, 1, 0)
  • if (semop(semid, myop, 2) -1)
  • perror(Semaphore operation failed)

47
struct sembuf Example 2
  • myop0
  • num 0
  • op 0
  • flg 0
  • myop1
  • num 0
  • op 1
  • flg 0

48
Create and Set Semaphore (top)
include ltsys/stat.hgtinclude ltsys/ipc.hgtinclud
e ltsys/sem.hgtinclude ltstdio.hgtinclude
lterrno.hgtdefine PERMS S_IRUSRS_IWUSRdefine
SET_SIZE 2int create_and_initialize(key_t mykey,
int value) int semid struct sembuf getlock,
setlock, setinit semid semget(mykey,
SET_SIZE,
PERMSIPC_CREATIPC_EXCL) if ((semid lt 0)
(errno ! EEXIST)) perror("Semaphore
create failed") return -1 else if
(semid gt 0) / initialize the semaphore
and open the lock / set_sembuf_struct(set
init, 1, value, 0) semop(semid, setinit,
1) set_sembuf_struct(setlock, 0, 1, 0)
semop(semid, setlock, 1)
49
Create and Set Semaphore (bottom)
else / semaphore already exists --
wait for initialization / if ((semid
semget(mykey, SET_SIZE, PERMS)) lt 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
50
semctl
  • include ltsys/types.hgt
  • include ltsys/ipc.hgt
  • include ltsys/sem.hgt
  • 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

51
Important Commands
  • GETVAL Return the value of a specific semaphore
    element
  • GETPID Return process ID of last process to
    manipulate
  • element
  • GETNCNT Return number of processes waiting for
    element to
  • increment
  • GETZCNT Return number of processes waiting for
    element to
  • become 0
  • SETVAL Set value of a specific semaphore
    element to arg.val
  • IPC_RMID Remove the semaphore identified by
    semid
  • IPC_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

52
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

53
initialize _sem_element
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)) lt 0)
perror("Could not create new private
semaphore") retval initialize_sem_element(se
mid,1,3) printf("initialize_sem_element
returned d\n",retval) initialize_sem_element
returns 0 on success and 1 and sets errno on
error
54
remove_semaphore
/ Example 8.26 /include ltsys/types.hgtinclude
ltsys/ipc.hgtinclude ltsys/sem.hgt int
remove_semaphore(int semid) return
semctl(semid, 0, IPC_RMID)
55
Command Prompt Semaphore Ops
  • List all semaphores ipcs s
  • Remove semaphore id 12345 ipcrm 12345

56
semop_restart
/ Example 8.29 /include ltsys/types.hgtinclude
ltsys/ipc.hgtinclude ltsys/sem.hgtinclude
lterrno.hgtint semop_restart(int semid, struct
sembuf sops, int nsops) int retval
while ( ((retval semop(semid, sops, nsops))
-1) (errno EINTR) )
return retval
57
sem_wait_restart
/ Example 8.30 /include ltsemaphore.hgtinclude
lterrno.hgtint sem_wait_restart(sem_t sem)
int retval while ( ((retval sem_wait(sem))
-1) (errno EINTR) )
return retval
Write a Comment
User Comments (0)
About PowerShow.com