Title: Semaphores and typical applications
1Semaphores and typical applications
- What are semaphores and messages
- How to control a critical section with semaphores
- Typical process coordination problems
2Semaphore code from Stevens (QEPD)
include ltsys/types.hgt // The header file
info include ltsys/ipc.hgt include ltsys/sem.hgt
define KEY ((key_t) 54321) // an unlikely key
define COUNT 20000 struct sembuf op_up1
0, 1, 0 // A useful trick for semops struct
sembuf op_down1 0, -1, 0 // use -1 for
down use this in wrappers main() register int
i, semid // Always protect system code if (
(semid semget(KEY, 1, 0666 IPC_CREAT)) lt 0)
err_sys("semget error") for (i 0 i lt COUNT
i) if (semop(semid, op_up0, 1) lt 0)
err_sys("semop up error") if (semop(semid,
op_down0, 1) lt 0) err_sys("semop down error")
if (semctl(semid, 0, IPC_RMID, (struct
semid_ds ) 0) lt 0) err_sys("IPC_RMID error")
exit(0)
The header
3Concurrency - From last time
- The theoretical core of OS
- An OS creates a set of processes that run
concurrently - A process is like a person - it has
- a stream of consciousness
- possessions - memory, files, data
- is created, reproduces, dies
- interacts with other processes
- In actuality, it is a program in execution
- Concurrent process misbehaviors
- Race conditions - unpredictable results because
processes simultaneously modify data or devices - Deadlocks - Each has what the other wants
- Starvation - some processes go hungry - others
eat well
4Some operating system ideas - also review
- Everything is a file - even devices
- This allows a program to work with human input,
or a device, or a temporary or permanent file - Interrupt-driven behavior
- Example - windows - process is simultaneously
sensitive to events from mouse, keyboard, process
subsystem, and window manager - Caching - Foreground and background copies
- Used in
- Cache memory
- Swapping
- The disk block cache - recent transactions are in
memory - Networking utilities
5Processes and their states
- The process state includes the following
- Running/ready/blocked (waiting on an
event/events) - Priority
- Kernel/User mode
- In-memory/swapped
- Process ID
- Priority
- The process owns
- U-area (but user cant examine/modify it)
- Entries in the system open-file table
- Its own file control blocks (linked to the system
table) - Its own memory space
6The system process table
- Used for scheduling and control of processes
- Scheduler acts on timer interrupt or a process
state change - It schedules the highest-priority process that is
ready - It causes a context switch (gives the process
control) - This mechanism
- Gives system and I/O processes high priority
- Keeps the CPU puercos from monopolizing
- Interrupts are outside process country
- This avoids make a context switch for each
interrupt - It means the interrupt service routines use only
the kernels memory
7Mutual Exclusion - software solutions
- Unsuccessful solutions (on separate slides)
- Strict alternation
- Algorithms where mutual exclusion fails
- Petersons algorithm
- Description of Bakery Algorithm
- Just like Baskin-Robbins - incoming process takes
a number - Since two users can grab same number,
lowest-number process gets priority
8Avoiding busy waiting - Semaphores and messages
- Classical semaphores
- The semaphore is an ADT with a counter, a process
queue, and two operations - The down operation sleeps enqueued if the counter
is zero, and then decrements the counter - The up operation increments the counter and
awakens a sleeper if the counter was 0. - The down operation enters a critical section, the
up leaves it. - Messages
- Reliable messages to an administrator work like a
down or up - Messages and semaphores are equivalent
- Thats why
9Semaphores and messages - continued
- Mistakes are easy
- Deadlock
- Gateway-controlling and resource-controlling
semaphores invoked in wrong order - deadlocks and
slow performance - Example of a deadlock creator
//process 0 Wait(a) Wait(b) //critical
section Signal(a) Signal(b)
//process 1 Wait(b) Wait(a) //critical
section Signal(b) Signal(a)
a
b
If process 1 is like process 0 (semaphores a and
b requested In same order, this deadlock cant
occur
10Producer-consumer problem again
- Definition
- Producers
- They produce items and place in a buffer as long
as one is available. - They wait (and stop producing) when no buffer is
available - Consumers
- They wait until a buffer contains an item and
then take it - They then consume the item
- What needs protection
- The buffer place and take operations, not the
producing or consuming - Possible deadlock
- Producer is waiting for a consumer to take, but
consumer cant take because producer has
buffering operation locked - This problem cant be solved with only one
semaphore
11Producer-consumer with general semaphores
- Global variables
- Item buffersNbuffers
- Int last_filledN_buffers, oldest_item0,
number_filled0 - // underrated programming technique, give
descriptive and nonambiguous names, not i, j, in,
out - Semaphores
- Buffer_availablen,items_available0pool_availabl
e1 - Technique
- Circular buffering step operation
- Next (next1)N_buffers // steps pointer from
end to start
12The code itself
Producer() While(1) New_itemproduce() Wait
(buffer_available) Wait (pool_available) Buffers
next_availablenew_item Countstep(last_fille
d) Signal(items_available) Signal(pool_available)
consumer() While(1) Wait (items_available) Wa
it (pool_available) Old_itemBuffersoldest_item
Count--step(oldest_item) Signal(buffer_availabl
e) Signal(pool_available) New_itemproduce()
13Language Mechanisms - Monitors
- Monitor is a class with mutual exclusion it has
- Member functions
- Data members
- Condition variables (user processes wait on
these) - Two ways to enter
- Normal
- Returning from wait on a condition variable
- Two ways to leave
- Normal (return from a member function)
- Waiting on a condition variable
- Monitors can be implemented by
- Preprocessor that generates semaphore code
- Compiler modification
14Classical IPC problems
- Producer-consumer
- Scenario
- Producer produces information
- Consumer consumes it
- Both must wait on buffer availability
- Problem resembler disk I/O and print servers
- Code is in book - both C and monitor
- Readers-Writers
- Scenario
- Readers can write whenever no writer is active
- Writers must have solitude
- Problem resembles database
- Code in book - both C and monitor
- Dining Philosophers
- Scenario
- N philosophers think, wait for chopsticks, and
eat - Problem is useless but illustrative
- Code - both C and monitor
15System V IPC
- xxxget call
- int xxxget(key, type-dependent, flags)
- returns
- Positive number, which is the instance ID
- For error
- xxxop call
- The basic operation
- Works on regions, groups of semops, or message
queues - xxxctl call
- Does specialized operations removes instance,
sets values and permissions
16Stevens semaphore get
include ltsys/types.hgt include ltsys/ipc.hgt inclu
de ltsys/sem.hgt define KEY ((key_t)
98765L) define PERMS 0666 main() int i,
semid for (i 0 i lt 1000 i) if (
(semid semget(KEY, 1, PERMS IPC_CREAT)) lt
0) err_sys("can't create semaphore") printf
("semid d\n", semid) if (semctl(semid, 0,
IPC_RMID, (struct semid_ds ) 0) lt
0) err_sys("can't remove semaphore")
17include "msgq.h" main() int readid,
writeid / Open the message queues. The
server must have already created them.
/ if ( (writeid msgget(MKEY1, 0)) lt
0) err_sys("client can't msgget message queue
1") if ( (readid msgget(MKEY2, 0)) lt
0) err_sys("client can't msgget message queue
2") client(readid, writeid) / Now we
can delete the message queues. / if
(msgctl(readid, IPC_RMID, (struct msqid_ds ) 0)
lt 0) err_sys("client can't RMID message queue
1") if (msgctl(writeid, IPC_RMID, (struct
msqid_ds ) 0) lt 0) err_sys("client can't RMID
message queue 2") exit(0)
18Wrapper function for msgsnd
mesg_send(id, mesgptr) int id / really an
msqid from msgget() / Mesg mesgptr /
Send the message - the type followed by the
optional data. / if (msgsnd(id, (char )
(mesgptr-gtmesg_type), mesgptr-gtmesg_len, 0)
! 0) err_sys("msgsnd error") / Receive
a message from a System V message queue. The
caller must fill in the mesg_type field with the
desired type. Return the number of bytes in
the data portion of the message. A 0-length
data message implies end-of-file. /
19Wrapper for msgrcv
int mesg_recv(id, mesgptr) int id / really an
msqid from msgget() / Mesg mesgptr int n
/ Read the first message on the queue of the
specified type. / n msgrcv(id, (char )
(mesgptr-gtmesg_type), MAXMESGDATA, mesgptr-gt
mesg_type, 0) if ( (mesgptr-gtmesg_len n) lt
0) err_dump("msgrcv error") return(n) / n
will be 0 at end of file /
20Header for both wrapper functions
/ Definition of "our" message. You may
have to change the 4096 to a smaller value, if
message queues on your system were configured
with "msgmax" less than 4096. / define MAXMESG
DATA (4096-16) / we don't want sizeof(Mesg)
gt 4096 / define MESGHDRSIZE (sizeof(Mesg) -
MAXMESGDATA) / length of mesg_len and
mesg_type / typedef struct int mesg_len /
bytes in mesg_data, can be 0 or gt 0 /
long mesg_type / message type, must be gt 0 /
char mesg_dataMAXMESGDATA Mesg
21General pattern for an IPC example
- Main program
- Create the IPC (xxxget)
- Initialize the IPC (xxxctl)
- Set up the cleanup() function
- Create children to be the actors using a loop
containing fork() - Does monitoring function or creates a monitor
- note Global variables are usually needed
- Child actors
- Can be persistent (barbers, philosophers)
- Can be temporary (readers, customers, Loreina
says writers are immortal) - Either live forever (with while loop) if immortal
or exit(0) if mortal
22Some specifics
- Definition
- Decide what IPC is needed and give valid names
- Decide what other global variables are needed and
what protection is needed - Write pseudocode, then fill in to readable code
- Program operation
- Examples can be done as real-time (uses sleep())
or discrete-time simulation - DTS is faster, gives better statistics, but takes
some thought - Terminal output can be a problem output from
child needs a flush, especially if control
characters are involved - Think about the statistics, there is usually a
dimensionless utilization parameter or ratio - Example of this is ratio of haircutting capacity
to offered business in the barbershop
23Example of a cleanup() function
void cleanup() if (0gt(msgctl(semid, IPC_RMID,
(struct msqid_ds ) 0) ) error_exit(couldnt
remove Message queue) exit(0) / code
segment to set up signals for cleanup extern void
cleanup for (int signal0signallt32signal
) signal(signal,cleanup)
- Comments
- Cleanup must be declared extern or the signal
mechanism wont find it - This wont work for all signals, notably 9
- Response to 9 (SIGKILL) isnt alterable because
it is important to be able to really control the
system
24Methodology for the sleepy barber
- Semaphores
- awaitingBarber
- awaitingCustomer
- mutex controls waiting-room variables, used
whenever a customer arrives or a haircut starts - Global variables
- emptyChairs -