0% found this document useful (0 votes)
19 views97 pages

Unit 2 Os

The document discusses process management and scheduling algorithms in computing systems, defining a process as a program in execution with various states such as new, waiting, ready, running, and terminated. It explains the structure of a process, including the process control block (PCB) and the concept of threads, which allow multiple tasks to be performed simultaneously within a process. Additionally, it covers process creation, termination, interprocess communication, and the importance of scheduling queues for efficient CPU resource allocation.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views97 pages

Unit 2 Os

The document discusses process management and scheduling algorithms in computing systems, defining a process as a program in execution with various states such as new, waiting, ready, running, and terminated. It explains the structure of a process, including the process control block (PCB) and the concept of threads, which allow multiple tasks to be performed simultaneously within a process. Additionally, it covers process creation, termination, interprocess communication, and the importance of scheduling queues for efficient CPU resource allocation.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 97

UNIT 2

PROCESS MANAGEMENT AND SCHEDULING ALGORITHM


Process Concept
1. The Process:
A process is a program in execution. A process is the unit of work in a modern
computing system.
The status of the current activity of a process is represented by the value of the
program counter and the contents of the processor’s registers.
The memory layout of a process is typically divided into multiple sections.
These sections include:
i. Text section— the executable code
ii. Data section—global variables
iii. Heap section—memory that is dynamically allocated during program run
time
iv. Stack section— temporary data storage when invoking functions (such as
function parameters, return addresses, and local variables)
Process concept
• The sizes of the text and data sections are fixed, as their sizes do not
change during program run time.
• However, the stack and heap sections can shrink and grow dynamically
during program execution.
• Each time a function is called, an activation record containing function
parameters, local variables, and the return address is pushed onto the
stack; when control is returned from the function, the activation record is
popped from the stack.
• Similarly, the heap will grow as memory is dynamically allocated, and will
shrink when memory is returned to the system
2. Process State
As a process executes, it changes state. The state of a process is defined in
part by the current activity of that process. A process may be in one of the
following states:
Process Concept
i. New - The process is being created.
ii. Waiting - The process is waiting for some
event to occur (such as an I/O
completion or reception of a signal).
iii. Ready - The process is waiting to be
assigned to a processor.
iv. Terminated - The process has finished
execution.
v. Running – Process instructions are
running in processor.
• It is important to realize that only one
process can be running on any processor
core at any instant.
• Many processes may be ready and waiting.
Process Concept
3. Process Control Block
Each process is represented in the operating
system by a process control block (PCB)—
also called a task control block. A PCB
contains many pieces of information
associated with a specific process, including
these:
i. Process state - The state may be new,
ready, running, waiting, halted, and so
on.
ii. Program counter -The counter indicates
the address of the next instruction to be
executed for this process.
Process Concept
iii. CPU registers - The registers vary in number and type, depending on the
computer architecture. They include accumulators, index registers, stack
pointers, and general-purpose registers, plus any condition-code information.
Along with the program counter, this state information must be saved when an
interrupt occurs, to allow the process to be continued correctly afterward when
it is rescheduled to run.
iv. CPU-scheduling information - This information includes a process priority,
pointers to scheduling queues, and any other scheduling parameters. Memory-
management information. This information may include such items as the value
of the base and limit registers and the page tables, or the segment tables,
depending on the memory system used by the operating system.
v. Accounting information - This information includes the amount of CPU and real
time used, time limits, account numbers, job or process numbers, and so on.
vi. I/O status information - This information includes the list of I/O devices allocated
to the process, a list of open files, and so on.
Process Concept
4. Thread:
• The process model discussed so far has implied that a process is a program
that performs a single thread of execution.
• For example, when a process is running a word-processor program, a single
thread of instructions is being executed.
• This single thread of control allows the process to perform only one task at a
time. Thus, the user cannot simultaneously type in characters and run the
spell checker.
• Most modern operating systems have extended the process concept to
allow a process to have multiple threads of execution and thus to perform
more than one task at a time.
• A multithreaded word processor could, for example, assign one thread to
manage user input while another thread runs the spell checker.
Process Scheduling
i. Each CPU core can run one process at a time.
ii. For a system with a single CPU core, there will never be more than
one process running at a time, whereas a multicore system can run
multiple processes at one time.
iii. If there are more processes than cores, excess processes will have
to wait until a core is free and can be rescheduled. The number of
processes currently in memory is known as the degree of
multiprogramming.
iv. An I/O-bound process is one that spends more of its time doing I/O
than it spends doing computations. A CPU-bound process, in
contrast, generates I/O requests infrequently, using more of its time
doing computations.
Process Scheduling
Process Scheduling
1. Scheduling Queues
As processes enter the system, they are put into a ready queue, where they are ready and waiting
to execute on a CPU’s core. This queue is generally stored as a linked list.
A ready-queue header contains pointers to the first PCB in the list, and each PCB includes a pointer
field that points to the next PCB in the ready queue. The system also includes other queues.
When a process is allocated a CPU core, it executes for a while and eventually terminates, is
interrupted, or waits for the occurrence of a particular event, such as the completion of an I/O
request.
Suppose the process makes an I/O request to a device such as a disk. Since devices run
significantly slower than processors, the process will have to wait for the I/O to become available.
Processes that are waiting for a certain event to occur — such as completion of I/O — are placed
in a wait queue.
Two types of queues are present: the ready queue and a set of wait queues. The circles represent
the resources that serve the queues, and the arrows indicate the flow of processes in the system.
A new process is initially put in the ready queue. It waits there until it is selected for execution, or
dispatched.
Process Scheduling
Once the process is allocated a CPU core and is executing, one of several
events could occur:
• The process could issue an I/O request and then be placed in an I/O wait
queue.
• The process could create a new child process and then be placed in a wait
queue while it awaits the child’s termination.
• The process could be removed forcibly from the core, as a result of an
interrupt or having its time slice expire, and be put back in the ready queue.
• In the first two cases, the process eventually switches from the waiting state
to the ready state and is then put back in the ready queue. A process
continues this cycle until it terminates, at which time it is removed from all
queues and has its PCB and resources deallocated.
Process Scheduling
Process Scheduling
2.CPU Scheduling
• A process migrates among the ready queue and various wait queues throughout its
lifetime.
• The role of the CPU scheduler is to select from among the processes that are in the ready
queue and allocate a CPU core to one of them. The CPU scheduler must select a new
process for the CPU frequently.
• An I/O-bound process may execute for only a few milliseconds before waiting for an I/O
request. Some operating systems have an intermediate form of scheduling, known as
swapping, whose key idea is that sometimes it can be advantageous to remove a process
from memory (and from active contention for the CPU) and thus reduce the degree of
multiprogramming.
• Later, the process can be reintroduced into memory, and its execution can be continued
where it left off. This scheme is known as swapping because a process can be “swapped
out” Processes from memory to disk, where its current status is saved, and later “swapped
in” from disk back to memory, where its status is restored. Swapping is typically only
necessary when memory has been overcommitted and must be freed up.
Process scheduling
3. Context Switch
When an interrupt occurs, the system needs to save the current context of the process
running on the CPU core so that it can restore that context when its processing is done,
essentially suspending the process and then resuming it.
The context is represented in the PCB of the process. It includes the value of the CPU
registers, the process state and memory-management information. Generically, we perform a
state save of the current state of the CPU core, be it in kernel or user mode, and then a state
restore to resume operations.
Switching the CPU core to another process requires performing a state save of the current
process and a state restore of a different process. This task is known as a context switch.
When a context switch occurs, the kernel saves the context of the old process in its PCB and
loads the saved context of the new process scheduled to run. Context switch time is pure
overhead, because the system does no useful work while switching.
Switching speed varies from machine to machine, depending on the memory speed, the
number of registers that must be copied, and the existence of special instructions (such as a
single instruction to load or store all registers). A typical speed is a several microseconds.
Process Scheduling
Operations on Process
1. Process Creation
• During the course of execution, a process may create several new processes. The creating process is
called a parent process, and the new processes are called the children of that process. Each of
these new processes may in turn create other processes, forming a tree of processes.
• Most operating systems (including UNIX, Linux, and Windows) identify processes according to a
unique process identifier (or pid), which is typically an integer number. The pid provides a unique
value for each process in the system, and it can be used as an index to access various attributes of a
process within the kernel.
• Once the system has booted, the system process creates processes which provide additional
services such as a web or print server, an ssh server, and the like. Two children of systemd—logind
and sshd. The logind process is responsible for managing clients that directly log onto the system.
• In this example, a client has logged on and is using the bash shell, which has been assigned pid
8416. Using the bash command-line interface, this user has created the process ps as well as the
vim editor. The sshd process is responsible for managing clients that connect to the system by using
ssh (which is short for secure shell).
Operations on Process
Operations on Process
When a process creates a new process, two possibilities for execution
exist:
1. The parent continues to execute concurrently with its children.
2. The parent waits until some or all of its children have terminated.

There are also two address-space possibilities for the new process:
1. The child process is a duplicate of the parent process (it has the same
program and data as the parent).
2. The child process has a new program loaded into it.
Operations on Process
1. Process Creation:
• A new process is created by the fork() system call. The new process consists of
a copy of the address space of the original process.
• This mechanism allows the parent process to communicate easily with its
child process.
• Both processes (the parent and the child) continue execution at the
instruction after the fork(), with one difference: the return code for the fork()
is zero for the new (child) process, whereas the (nonzero) process identifier of
the child is returned to the parent.
• After a fork() system call, one of the two processes typically uses the exec()
system call to replace the process’s memory space with a new program. The
exec() system call loads a binary file into memory (destroying the memory
image of the program containing the exec() system call)
Operations on Process
Operations on Process
2. Process Termination
• A process terminates when it finishes executing its final statement and asks the
operating system to delete it by using the exit() system call.
• At that point, the process may return a status value (typically an integer) to its waiting
parent process (via the wait() system call). All the resources of the process —including
physical and virtual memory, open files, and I/O buffers—are deallocated and reclaimed
by the operating system.
• A parent may terminate the execution of one of its children for a variety of reasons,
such as these:
i. The child has exceeded its usage of some of the resources that it has been allocated.
(To determine whether this has occurred, the parent must have a mechanism to
inspect the state of its children.)
ii. The task assigned to the child is no longer required.
iii. The parent is exiting, and the operating system does not allow a child to continue if
its parent terminates.
Operations on Process

• When a process terminates, its resources are deallocated by the operating


system.
• However, its entry in the process table must remain there until the parent
calls wait(), because the process table contains the process’s exit status.
• A process that has terminated, but whose parent has not yet called wait(),
is known as a zombie process. All processes transition to this state when
they terminate, but generally they exist as zombies only briefly.
• Once the parent calls wait(), the process identifier of the zombie process
and its entry in the process table are released. Now consider what would
happen if a parent did not invoke wait() and instead terminated, thereby
leaving its child processes as orphans.
Operations on Process
Android Process Hierarchy
i. Foreground process—The current process visible on the screen,
representing the application the user is currently interacting with
ii. Visible process—A process that is not directly visible on the foreground
but that is performing an activity that the foreground process is referring
to (that is, a process performing an activity whose status is displayed on
the foreground process)
iii. Service process—A process that is similar to a background process but is
performing an activity that is apparent to the user (such as streaming
music) Background process—A process that may be performing an activity
but is not apparent to the user.
iv. Empty process—A process that holds no active components associated
with any application
Process Scheduling
4. Inter process communication
Processes executing concurrently in the operating system may be either independent
processes or cooperating processes.
A process is independent if it does not share data with any other processes executing in the
system.
A process is cooperating if it can affect or be affected by the other processes executing in the
system. Clearly, any process that shares data with other processes is a cooperating process.
There are several reasons for providing an environment that allows process cooperation:
i. Information sharing - Since several applications may be interested in the same piece of
information (for instance, copying and pasting), we must provide an environment to allow
concurrent access to such information.
ii. Computation speedup - If we want a particular task to run faster, we must break it into
subtasks, each of which will be executing in parallel with the others. Notice that such a
speedup can be achieved only if the computer has multiple processing cores.
iii. Modularity - We may want to construct the system in a modular fashion, dividing the
system functions into separate processes or threads.
Process Scheduling

Cooperating processes require an interprocess communication (IPC)


mechanism that will allow them to exchange data— that is, send data
to and receive data from each other.
There are two fundamental models of interprocess communication:
shared memory and message passing.
• shared-memory model - a region of memory that is shared by the
cooperating processes is established. Processes can then exchange
information by reading and writing data to the shared region.
• message passing model - communication takes place by means of
messages exchanged between the cooperating processes.
Process Scheduling
Process Scheduling
i) IPC for shared-memory Systems
1. Processes establish a shared memory region for communication, residing in the address space of the
creator, and other processes must attach it.
2. The OS prevents direct memory access between processes, but shared memory allows them to
bypass this restriction, requiring coordination to avoid simultaneous writes.
3. The producer-consumer problem involves a producer generating data that a consumer processes,
seen in examples like a compiler-assembler or web server-client relationship.
4. Two buffer types exist: an unbounded buffer with no size limit where the producer always
produces, and a bounded buffer with a fixed size where the producer and consumer may need to wait.
5. A bounded buffer uses a circular array with shared variables: `buffer[BUFFER_SIZE]`, `in`
(pointing to the next free slot), and `out` (pointing to the first occupied slot), with conditions `in ==
out` (empty) and `((in + 1) % BUFFER_SIZE) == out` (full).
6. The producer generates an item, stores it in `buffer[in]`, and updates `in`, ensuring space is
available before inserting new data.
7. Without proper synchronization, simultaneous access by both producer and consumer can cause
data corruption, requiring synchronization mechanisms to manage concurrent access.
Process Scheduling
ii) IPC for message-passings systems
1. Unlike shared memory, message passing allows processes to communicate and synchronize
without sharing the same address space.
2. It is especially useful in distributed environments where processes may reside on different
computers connected via a network.
3. A message-passing facility provides at least two basic operations: `send(message)` and
`receive(message)`.
4. Messages can be either fixed or variable in size; fixed-size messages simplify system
implementation but make programming harder, while variable-size messages ease programming but
require complex system-level implementation.
5. Communication between processes requires an established link, which can be logically
implemented in different ways.
6. Logical communication links can be categorized based on direct or indirect communication,
synchronous or asynchronous communication, and automatic or explicit buffering.
7. The physical implementation of these links (such as shared memory, hardware buses, or networks)
is a separate concern discussed in later sections.
CPU Scheduling
Basic Concepts
• Almost all computer resources are scheduled
before use. The CPU is, of course, one of the
primary computer resources. Thus, its
scheduling is central to operating-system
design.
CPU-I/O burst cycle:
• Process execution consists of a cycle of CPU
execution and I/O burst. Which is followed by
another CPU burst and I/O burst eventually
final CPU burst ends.
CPU scheduling
Preemptive and not preemptive scheduling:
• Whenever the CPU becames idle, the operating system must select one of the process in
the ready queues to be executed. The selection process is carried out by the CPU
scheduler.
• Ready queue is not necessary a FIFO queue, a priority queue, a tree or simply a unordered
linked list. The records in queue are generally process control blocks of the process.
• CPU scheduling decisions may take place under the following 4 circumstances:
i. When process switches from running state to wait state
ii. Running state to ready
iii. Waiting state to ready state
iv. When process terminates
1, 4 new process is selected for execution(non preemptive) or cooperative otherwise pre-
emptive.
CPU scheduling
• Non preemptive scheduling: once the CPU has been
allocated to a process keeps the CPU until it releases it
either by terminating or by switching to waiting state.
Virtually all modern OS windows, MACOS, Linux, UNIX
use pre-emptive scheduling algorithm.
• Pre-emptive results in race conditions were data is
shared along several processes leading to inconstant of
date.
Dispatcher:
The dispatcher is the module that gives control of the
CPU’s core of the process selected by CPU schedular.
The time it takes for the dispatcher to stop one process
and start another running is known as the dispatch latency.
CPU scheduling
The function involves the following:
• Switching context from one process to another
• Switching to user mode
• Jumping to the proper location in the user program to resume that
program The dispatcher should be as fast as possible, since it is
invoked during every context switch.
The time it takes for the dispatcher to stop one process and start
another running is known as the dispatch latency.
Scheduling Criteria
The Scheduling criteria include the following:
CPU utilization: We want to keep the CPU as busy as possible. Conceptually,
CPU utilization can range from 0 to 100 percent. In a real system, it should
range from 40 percent (for a lightly loaded system) to 90 percent (for a heavily
loaded system). (CPU utilization can be obtained by using the top command on
Linux, macOS, and UNIX systems.)
Throughput: If the CPU is busy executing processes, then work is being done.
One measure of work is the number of processes that are completed per time
unit, called throughput. For long processes, this rate may be one process over
several seconds; for short transactions, it may be tens of processes per second.
Turnaround time: The interval from the time of submission of a process to the
time of completion is the turnaround time. Turnaround time is the sum of the
periods spent waiting in the ready queue, executing on the CPU, and doing I/O.
Scheduling criteria
Waiting time: The CPU-scheduling algorithm does not affect the
amount of time during which a process executes or does I/O. It affects
only the amount of time that a process spends waiting in the ready
queue. Waiting time is the sum of the periods spent waiting in the
ready queue.
Response time: Is the time it takes to start responding, not the time it
takes to output the response.
In an interactive system, turnaround time may not be the best criterion.
Often, a process can produce some output fairly early and can continue
computing new results while previous results are being output to the
user. Thus, another measure is the time from the submission of a
request until the first response is produced.
Scheduling Algorithms
1. First come, First served(FCFS) -
Process, Arrival time/order of process, burst time(non-pre-emptive)

2. Shortest Job First(SJF) –


Arrival time differs, burst time(pre-emptive)
Process, burst time(non-pre-emptive)

3. Round Robin(RR) –
Process, burst time, time quantum.

4. Priority Scheduling –
Process, burst time, priority
Scheduling Algorithms
5. Multilevel queue scheduling 6. Multilevel feedback queue
Multi thread models
Many-to-One One-to-one Many-to-many

• Maps many user level threads to • Allows multiple threads to run • Many user level threads are
one kernel level thread. parallel on multiprocessor. mapped to small or equal
number of kernel threads
• Thread management is done by • Drawback: creating a user depending of specific
the thread library in user space. thread require creating application and machine the
However, entire process will corresponding kernel thread. number of kernel threads differ.
block if a thread makes a Large number of kernel thread
blocking system call. may burden the whole system. • Two level model – variant of
many- to-many model.
• Only one thread can access • Application: Linux along with
kernel at a time. family of windows OS • one user thread is mapped to
implement one to one model. small or equal number of kernel
thread also allows user level
threads to bound to kernel
threads
Multi thread models
Many-to-one One-to-one Many-to-many

• Application: Green thread • Concurrency: As many user • Applications: API for creating
library for solarisis systems and threads and kernel threads may and managing threads, POSIX,
adopted in early versions of run if there is a blocking system Pthreads, windows, java.
java. call, the kernel can schedule
another thread of execution. • Concurrency: As many user
• Concurrency: Allows users to threads and kernel threads may
develop as many user threads as run if there is a blocking system
they wish if it does not result in call, the kernel can schedule
parallelism because kernel can another thread of execution.
schedule only one thread at a
time. • Many-to-many is not practical
but looks flexible. Limiting
number of kernel threads less
important cause of increasing
number of process cores.
Threading Issues
1. The fork() and exec() system call:
Fork() process either duplicates all threads or duplicates only the thread that initiates fork()..
Version of fork() depends on application that executes next.
Exec() program specified in parameter will replace entire process including all threads.
Calling exec() after fork() then duplicates all the threads is unnecessary duplication only the
calling thread is appropriate.

2. Signal handling:
Signal in UNIX system to notify a process that a particular event has occurred. Signal can be
synchronized or asynchronous follows same pattern:
• Signal is generated by occurance of particular events.
• Signal is delivered to a process
• once delivered signal must be handled
Threading Issues
Syncronous signals: if signals are delivered to the same process that
creates it then it is synchronous signal. Example illegal memory access,
divided by zero.
Asyncronous signals: generated by event external to running process.
Example terminating process using ctrl +c and having timer expire.
A signal is handled by one of 2 possible handlers:
• A default signal handler
• A user defined signal handler
Every signal have default signal handler overwritten by default signal
handler over written by user defined signal handler.
Threading Issues
• Delivering signal in multi thread environment:
• Deliver signal to thread to which the signal applies
• Deliver every thread in process
• Certain thread in process
• Assign a specific thread to receive all signals
UNIX function to deliver signals: Kill(pid_t pid, int signal)
Windows: Asyncronous procedure call specifies function to be called when a signal
is delivered in windows.
3. Thread Cancellation:
Closing browser, searching a database with multiple threads in which only one
thread can access and others cancel is example of thread cancellation.
The thread that is to be cancelled is called target thread.
Threading Issues
• Asyncronous cancellation: one thread immediately terminates target thread.(ex. middle of
uploading data)
• Deffered cancellation: The target thread should check wether it should terminate itself in an
orderly fashion(check for flags).
Pthreads allows thread to enable or disable cancellaion. Cancellaion occurs only when thread
reaches cancellation point.
Cleanup handler is pthread function that allows the thread to release resource that is acquired.
4. Thread local storage:
Each thread shares one copy of data of a process(ex. Transaction processing) Java provide
Thread Local<T> class with get(), set() methods.
5. Schedular Activations:
Final issue is communication between the kernel and thread library. Data structure between
user ad kernel thread is called light weight process(LWP). LWP is a virtual process to schedule
user threads.
Threading Issues
• Schedular activation is the scheme of communication between user
and thread library and kernel thread library.
• Upcall procedure used by kernel to inform about certain events to
applications.
• Event that triggers upcall occurs when application thread is about to
be blocked. Kernel makes upcall to information that thread is about to
be blocked. The kernel that allocates new virtual processor to the
app. This will run upcall handler that saves states of blocking thread.
Process Syncronization
Race condition: several process access and manipulate the same data
consistently and outcome of execution depends on particular order in
which the process takes place is called race condition.
Example: producer consumer problem.
Code for producer process Code for consumer process
Process Syncronization
As an illustration, suppose that the value of the variable count is currently 5 and
that the producer and consumer processes.

Notice that we have arrived at the incorrect state “count == 4”, indicating that four
buffers are full, when, in fact, five buffers are full. If we reversed the order of the
statements at T4 and T5, we would arrive at the incorrect state “count ==
6”concurrently execute the statements “count++” and “count--”.
A situation like this, where several processes access and manipulate the same data
concurrently and the outcome of the execution depends on the particular order in
which the access takes place, is called a race condition.
Process Syncronization
Critical Section problem
• Consider a system consisting of n processes {P0, P1, ..., Pn−1}. Each process
has a segment of code, called a critical section, in which the process may be
accessing — and updating — data that is shared with at least one other
process.
• The important feature of the system is that, when one process is executing in
its critical section, no other process is allowed to execute in its critical section.
That is, no two processes are executing in their critical sections at the same
time. The critical-section problem is to design a protocol that the processes
can use to synchronize their activity so as to cooperatively share data.
• Each process must request permission to enter its critical section. The section
of code implementing this request is the entry section. The critical section may
be followed by an exit section. The remaining code is the remainder section.
Critical Section problem
A solution to the critical-section problem must satisfy the following three
requirements:
1. Mutual exclusion. If process Pi is executing in its critical section, then
no other processes can be executing in their critical sections.
2. Progress. If no process is executing in its critical section and some
processes wish to enter their critical sections, then only those
processes that are not executing in their remainder sections can
participate in deciding which will enter its critical section next, and this
selection cannot be postponed indefinitely.
3. Bounded waiting. There exists a bound, or limit, on the number of
times that other processes are allowed to enter their critical sections
after a process has made a request to enter its critical section and
before that request is granted.
Critical Section problem
Critical Section problem
Two general approaches are used to handle critical sections in operating
systems:
A preemptive kernel: Allows a process to be preempted while it is
running in kernel mode. Preemptive kernels, must be carefully designed
to ensure that shared kernel data are free from race conditions.
Preemptive kernels are especially difficult to design for SMP
architectures, since in these environments it is possible for two kernel-
mode processes to run simultaneously on different CPU cores.
A non-preemptive: kernel does not allow a process running in kernel
mode to be preempted; a kernel-mode process will run until it exits
kernel mode, blocks, or voluntarily yields control of the CPU. A non-
preemptive kernel is essentially free from race conditions on kernel data
structures, as only one process is active in the kernel at a time.
Hardware support for syncronization
1. Memory Barriers
System may reorder instructions, a policy that can lead to unreliable data states. How a
computer architecture determines what memory guarantees it will provide to an application
program is known as its memory model. In general, a memory model falls into one of two
categories: 1. Strongly ordered, where a memory modification on one processor is
immediately visible to all other processors. 2. Weakly ordered, where modifications to memory
on one processor may not be immediately visible to other processors.
2. Hardware Instructions
Many modern computer systems provide special hardware instructions that allow us either to
test and modify the content of a word or to swap the contents of two words atomically— that
is, as one uninterruptible unit.
We can use these special instructions to solve the critical-section problem in a relatively simple
manner.
Rather than discussing one specific instruction for one specific machine, we abstract the main
concepts behind these types of instructions by describing the test and set() and compare and
swap() instructions.
Hardware support for syncronization
1. test and set() instruction: The important characteristic of test and
set() instruction is that it is executed atomically. Thus, if two test and
set() instructions are executed simultaneously (each on a different
core), they will be executed sequentially in some arbitrary order. If the
machine supports the test and set() instruction, then we can
implement mutual exclusion by declaring a boolean variable lock,
initialized to false.
Hardware support for syncronization
• The compare and swap() instruction (CAS), operates on two words
atomically, but uses a different mechanism that is based on swapping
the content of two words. The operand value is set to new value only
if the expression (*value == expected) is true. Regardless, CAS always
returns the original value of the variable value.
• The important characteristic of this instruction is that it is executed
atomically. Thus, if two CAS instructions are executed simultaneously
(each on a different core), they will be executed sequentially in some
arbitrary order.
Hardware support for syncronization
Hardware support for syncronization
3. Automic Variables:
Atomic variables are basic building block for constructing other tools that
solve the critical-section problem. One such tool is an atomic variable,
which provides atomic operations on basic data types such as integers and
Booleans.
Atomic variables can be used in to ensure mutual exclusion in situations
where there may be a data race on a single variable while it is being
updated, as when a counter is incremented.
Most systems that support atomic variables provide special atomic data
types as well as functions for accessing and manipulating atomic variables.
Software - Mutex Locks
Hardware based solutions are inaccessible to applications
programmers. Mutex locks are high level programs
software to solve critical section problem and to avoid
race condition.
Acquire() - Process must acquire a lock before entering
critical section.
Release() – returns lock when process exits critical
section.
A process that attempts acquire an unavailable lock is
blocked until lock is released.
CPU utilization is high because bust waiting.
Software - Spin lock
Spin lock - When lock is to be held for short duration while thread goes
for waiting state and restored the general rule is to use spin lock . Spin
lock will be held for the duration of 2 context switch.
Semaphores: A semaphore S is a integer variable apart from
initialization it is accessed only through 2 standard atomic operations
wait() and signal().
Software - Semaphores
Semaphores:
Semaphores can solve various synchronization problems. For example, consider two concurrently
running processes: P1 with a statement S1 and P2 with a statement S2. Suppose we require that S2
be executed only after S1 has completed.
We can implement this scheme readily by letting P1 and P2 share a common semaphore synch,
initialized to 0. In process P1, we insert the statements S1; signal(synch);
In process P2, we insert the statements wait(synch); S2; Because synch is initialized to 0, P2 will
execute S2 only after P1 has invoked signal(synch), which is after statement S1 has been executed.
Semaphore Implementation:
To avoid busy waiting in mutex lock modify wait() and signal() add the waiting process in the
waiting queue and control transfer to CPU scheduler.
The sleep() operation suspends the process that invokes it. The wakeup(P) operation resumes the
execution of a suspended process P. These two operations are provided by the operating system as
basic system calls.
Negative list indicates the number of waiting process.
Semaphore
Monitors

Monitors:
All process share binary semaphore
variable mutex which is initialized to 1.
Each process must execute wait()
mutex and signal() mutex.
Monitor usage: An abstract datatype or
ADT encapsulates data with set of
functions to operate independently of
any specific implementaion of ADT.
The monitor constructor ensures that
only one process is executed inside
monitor.
Monitors

Additional synchronization mechanisms are produced by conditional construct. A programmer who


need to write a tailor made syncronization scheme can define one or more variables of type
condition.
The only operation that can be invoked in conditional variables are wait() and signal().
Conditon x, y;
x.wait();
x.signal();
If no process is suspended then the state of x is same as if no operation has been executed.
Now suppose that, when the x.signal() operation is invoked by a process P, there exists a suspended
process Q associated with condition x.
Clearly, if the suspended process Q is allowed to resume its execution, the signaling process P must
wait. Otherwise, both P and Q would be active simultaneously within the monitor. Note, however,
that conceptually both processes can continue with their execution. Two possibilities exist:
1. Signal and wait. P either waits until Q leaves the monitor or waits for another condition.
2. Signal and continue. Q either waits until P leaves the monitor or waits for another condition.
Monitors
Monitors

Implementing monitors using semaphores:


The signal-and-wait scheme in our implementation. Since a signaling
process must wait until the resumed process either leaves or waits, an
additional binary semaphore, next, is introduced, initialized to 0. The
signaling processes can use next to suspend themselves. An integer
variable next count is also provided to count the number of processes
suspended on next. Thus, each external function F is replaced by:
Mutual execution in monior implementation of wait() implementation of signal()
Monitors

Resuming process within monitor:


If several process are suspended on condition x.signal() operation is executed then which process
should resume? FCFS not adequate. Insteard conditions wait is used.
x.wait(c);
C is an integer expression that is evaluated when wait() operation is executed, the value of c is called
priority number. Is then stored with the name of process that is suspended. When x.signal() is
executed the process with small priority number is resumed next.
Each process requesting for resource allocation specifies maximum time it plans to use the resource.
The process which needs shortest time is executed first. The process that needs to access th resource
in question must observe the following sequence.
R.acquire(t);
..
Access resource;

R.release();
Monitors

In particular, the following problems can occur:


• A process might access a resource without first gaining access permission to the resource.
• A process might never release a resource once it has been granted access to the resource.
• A process might attempt to release a resource that it never requested.
• A process might request the same resource twice (without first releasing the resource).

We must check two conditions to establish the correctness of this system.


First, user processes must always make their calls on the monitor in a correct sequence.
Second, we must be sure that an uncooperative process does not simply ignore the mutual-
exclusion gateway provided by the monitor and try to access the shared resource directly, without
using the access protocols. Only if these two conditions can be ensured can we guarantee that no
time-dependent errors will occur and that the scheduling algorithm will not be defeated.
Liveliness: refers to set of properties that a system must satisfy to ensure that process make
progress during execution.
Efforts at providing mutual execution may lead to liveliness failure.
1. Deadlock: two or more process are waiting indefinitely for a event that can be caused only by
one of the waiting process. Such as signal() when such a state is reached this is called deadlock.
Example:
Suppose that P0 executes wait(S) and then P1 executes wait(Q). When P0 executes wait(Q), it must
wait until P1 executes signal(Q). Similarly, when P1 executes wait(S), it must wait until P0 executes
signal(S). Since these signal() operations cannot be executed, P0 and P1 are deadlocked.
2. Priority inversion:
A scheduling challenge arises when a higher-priority process needs to read or modify kernel
data that are currently being accessed by a lower-priority process—or a chain of lower-
priority processes. Since kernel data are typically protected with a lock, the higher-priority
process will have to wait for a lower-priority one to finish with the resource. The situation
becomes more complicated if the lower-priority process is preempted in favor of another
process with a higher priority.
As an example, assume we have three processes—L, M, and H—whose priorities follow the
order L < M < H. Assume that process H requires a semaphore S, which is currently being
accessed by process L. Ordinarily, process H would wait for L to finish using resource S.
However, now suppose that process M becomes runnable, thereby preempting process L.
Indirectly, a process with a lower priority—process M—has affected how long process H
must wait for L to relinquish resource S.
This liveness problem is known as priority inversion, and it can occur only in systems with
more than two priorities. Typically, priority inversion is avoided by implementing a priority-
inheritance protocol.
Classical problem of syncronization
1. The Bounded Buffer problem:
The bounded-buffer problem is commonly used to illustrate the power of synchronization primitives. In our problem, the
producer and consumer processes share the following data structures:

We assume that the pool consists of n buffers, each capable of holding one item. The mutex binary semaphore provides
mutual exclusion for accesses to the buffer pool and is initialized to the value 1. The empty and full semaphores count the
number of empty and full buffers. The semaphore empty is initialized to the value n; the semaphore full is initialized to the
value 0.
Classical problem of syncronization
2. The readers writer problem
Suppose that a database is to be shared among several concurrent processes. Some of these processes
may want only to read the database, whereas others may want to update (that is, read and write) the
database between these two types of processes by referring to the former as readers and to the latter
as writers.
Obviously, if two readers access the shared data simultaneously, no adverse effects will result. However,
if a writer and some other process (either a reader or a writer) access the database simultaneously,
chaos may ensue. This synchronization problem is referred to as the readers–writers problem.
The readers–writers problem has several variations, all involving priorities.
• The simplest one, referred to as the first readers–writers problem, requires that no reader be kept
waiting unless a writer has already obtained permission to use the shared object. In other words, no
reader should wait for other readers to finish simply because a writer is waiting.
• The second readers–writers problem requires that, once a writer is ready, that writer perform its
write as soon as possible. In other words, if a writer is waiting to access the object, no new readers
may start reading.
A solution to either problem may result in starvation. In the first case, writers may starve; in the second
case, readers may starve. For this reason, other variants of the problem have been proposed
Classical problem of syncronization
In the solution to the first readers–writers problem, the reader processes share the
following data structures:
semaphore rw mutex = 1; semaphore mutex = 1; int read count = 0;
The binary semaphores mutex and rw mutex are initialized to 1; read count is a
counting semaphore initialized to 0.
The semaphore rw mutex is common to both reader and writer processes.
The mutex semaphore
is used to ensure mutual exclusion when the variable read count is updated. The read
count variable keeps track of how many processes are currently reading the object.
The semaphore rw mutex functions as a mutual exclusion semaphore for the writers.
It is also used by the first or last reader that enters or exits the critical section.
Classical problem of syncronization
Classical problem of syncronization
Reader–writer locks are most useful in the following situations:
• In applications where it is easy to identify which processes only read shared data and which processes
only write shared data.
• In applications that have more readers than writers. This is because reader–writer locks generally
require more overhead to establish than semaphores or mutual-exclusion locks. The increased
concurrency of allowing multiple readers compensates for the overhead involved in setting up the
reader–writer lock.

3. The Dining philosophers problem:


Consider five philosophers who spend their lives thinking and eating. The philosophers share a circular
table surrounded by five chairs, each belonging to one philosopher. In the center of the table is a bowl
of rice, and the table is laid with five single chopsticks. When a philosopher thinks, she does not interact
with her colleagues.
From time to time, a philosopher gets hungry and tries to pick up the two chopsticks that are closest to
her (the chopsticks that are between her and her left and right neighbors). A philosopher may pick up
only one chopstick at a time.
Obviously, she cannot pick up a chopstick that is already in the hand of a neighbor. When a hungry
philosopher has both her chopsticks at the same time, she eats without releasing the chopsticks. When
she is finished eating, she puts down both chopsticks and starts thinking again.
Classical problem of syncronization
Classical problem of syncronization
Semaphore solution:
One simple solution is to represent each chopstick with a semaphore. A philosopher tries to
grab a chopstick by executing a wait() operation on that semaphore. She releases her
chopsticks by executing the signal() operation on the appropriate semaphores. Thus, the
shared data are semaphore chopstick[5]; where all the elements of chopstick are initialized
to 1.
Several possible remedies to the deadlock problem are the following:
• Allow at most four philosophers to be sitting simultaneously at the table.
• Allow a philosopher to pick up her chopsticks only if both chopsticks are available (to do
this, she must pick them up in a critical section).
• Use an asymmetric solution— that is, an odd-numbered philosopher picks up first her left
chopstick and then her right chopstick, whereas an even numbered philosopher picks up her
right chopstick and then her left chopstick.
Classical problem of syncronization
Monitor Solution:
This solution imposes the restriction that a philosopher may pick up her chopsticks only if both of them are
available.
enum {THINKING, HUNGRY, EATING} state[5];
Philosopher i can set the variable state[i] = EATING only if her two neighbors are not eating: (state[(i+4) % 5] !=
EATING) and (state[(i+1) % 5] != EATING).
We also need to declare condition self[5]; This allows philosopher i to delay herself when she is hungry but is
unable to obtain the chopsticks she needs.
Each philosopher, before starting to eat, must invoke the operation pickup(). This act may result in the suspension
of the philosopher process.
After the successful completion of the operation, the philosopher may eat. Following this, the philosopher invokes
the putdown() operation. Thus, philosopher i must invoke the operations pickup() and putdown() in the following
sequence: DiningPhilosophers.pickup(i);
...
eat
...
DiningPhilosophers.putdown(i);
It is easy to show that this solution ensures that no two neighbors are eating simultaneously and that no deadlocks
will occur.
Classical synchronization problem
Deadlock
Necessary Conditions for deadlock:
i. Mutual exclusion - At least one resource must be held in a nonsharable mode;
that is, only one thread at a time can use the resource. If another thread
requests that resource, the requesting thread must be delayed until the
resource has been released.
ii. Hold and wait - A thread must be holding at least one resource and waiting to
acquire additional resources that are currently being held by other threads.
iii. No preemption - Resources cannot be preempted; that is, a resource can be
released only voluntarily by the thread holding it, after that thread has
completed its task.
iv. Circular wait - A set {T0, T1, ..., Tn} of waiting threads must exist such that T0 is
waiting for a resource held by T1, T1 is waiting for a resource held by T2, ..., Tn−1
is waiting for a resource held by Tn, and Tn is waiting for a resource held by T0.
Deadlock
Resource-Allocation Graph
• Deadlocks can be described more precisely in terms of a directed graph called a system resource-
allocation graph. This graph consists of a set of vertices V and a set of edges E. The set of vertices V is
partitioned into two different types
• of nodes: T = {T1, T2, ..., Tn}, the set consisting of all the active threads in the system, and R = {R1, R2, ...,
Rm}, the set consisting of all resource types in the system.
• A directed edge from thread Ti to resource type Rj is denoted by Ti → Rj; it signifies that thread Ti has
requested an instance of resource type Rj and is currently waiting for that resource.
• A directed edge from resource type Rj to thread Ti is denoted by Rj → Ti; it signifies that an instance of
resource type Rj has been allocated to thread Ti. A directed edge Ti → Rj is called a request edge; a
directed edge Rj → Ti is called an assignment edge.
• Pictorially, we represent each thread Ti as a circle and each resource type Rj as a rectangle.
• Since resource type Rj may have more than one instance, we represent each such instance as a dot
within the rectangle. Note that a request edge points only to the rectangle Rj
• whereas an assignment edge must also designate one of the dots in the rectangle.
• When thread Ti requests an instance of resource type Rj, a request edge is inserted in the resource-
allocation graph. When this request can be fulfilled, the request edge is instantaneously transformed to
an assignment edge. When the thread no longer needs access to the resource, it releases the resource.
As aresult, the assignment edge is deleted.
Deadlock
Deadlock
Deadlock
Methods for Handling Deadlocks
Generally speaking, we can deal with the deadlock problem in one of three ways:
• We can ignore the problem altogether and pretend that deadlocks never occur in the system.
• We can use a protocol to prevent or avoid deadlocks, ensuring that the system will never
enter a deadlocked state.
• We can allow the system to enter a deadlocked state, detect it, and recover To ensure that
deadlocks never occur, the system can use either a deadlock prevention or a deadlock-
avoidance scheme.
Deadlock prevention provides a set of methods to ensure that at least one of the necessary
conditions cannot hold. These methods prevent deadlocks by constraining how requests for
resources can be made.
Deadlock avoidance requires that the operating system be given additional information in
advance concerning which resources a thread will request and use during its lifetime. With this
additional knowledge, the operating system can decide for each request whether or not the
thread should wait
Deadlock
Deadlock Avoidance:
Safe State
A state is safe if the system can allocate resources to each thread (up to its maximum) in some order and still avoid a deadlock.
More formally, a system is in a safe state only if there exists a safe sequence.
A sequence of threads is a safe sequence for the current allocation state if, for each Ti , the resource requests that Ti can still
make can be satisfied by the currently available resources plus the resources held by all Tj , with j < i
Consider system with 12 resources
Free resources = 12 – 5 – 2 -2 = 3
For t1 to execute
Holded resources by to and t2 = 5 + 2= 7
Free resources =12 - 7 =5
T1 holds 5 resources and 5 free resources are available t1 can execute
For t0 to execute
free resources + need = 5 + 5
For t2 t execute
Free resources = 10
Free resources + need = 12
Deadlock
Resource allocation
data structures encode the state of the resource-allocation system. We need the
following data structures, where n is the number of threads in the system and m
is the number of resource type.
• Max. An n × m matrix defines the maximum demand of each thread. If Max[i][j]
equals k, then thread Ti may request at most k instances of resource type Rj .
• Allocation. An n × m matrix defines the number of resources of each type
currently allocated to each thread. If Allocation[i][j] equals k, then thread Ti is
currently allocated k instances of resource type Rj .
• Need. An n × m matrix indicates the remaining resource need of each thread. If
Need[i][j] equals k, then thread Ti may need k more instances of resource type
Rj to complete its task. Note that Need[i][j] equals Max[i][j] − Allocation[i][j].
Deadlock
Safety Algorithm
Let Work and Finish be vectors of length m and n, respectively. Initialize
Work = Available and Finish[i] = false for i = 0, 1, ..., n − 1.
2. Find an index i such that both
a. Finish[i] == false
b. Need i ≤ Work
If no such i exists, go to step 4.
3. Work = Work + Allocation i
Finish[i] = true
Go to step 2.
4. If Finish[i] == true for all i, then the system is in a safe state.
Deadlock
Resource request algorithm
Let Requesti be the request vector for thread Ti
If Request [i] [j] == k, then thread Ti wants k instances of resource type Rj
When a request or resources is made by thread Ti , the following actions are taken:
1. If Requesti ≤ Needi , go to step 2. Otherwise, raise an error condition, since
the thread has exceeded its maximum claim.
2. If Requesti ≤ Available, go to step 3. Otherwise, Ti must wait, since the
resources are not available.
3. Have the system pretend to have allocated the requested resources to
thread Ti by modifying the state as follows:
Available = Available i–Requesti
Allocationi = Allocationi + Requesti
Needi = Needi –Requesti
If the resulting resource-allocation state is safe, the transaction is completed, and thread Ti is allocated its
resources. However, if the new state is unsafe, then Ti must wait for Request i, and the old resource-allocation
state is restored.
Deadlock
Check if the system is in safe state using safety algorithm
Deadlock

Need = Max – Allocation


Deadlock

Available
3 2 2
T1 0 1 0
3 3 2
Deadlock

Available

3 3 2
T1 2 0 0
5 3 2
T3 2 1 1
7 4 3
Deadlock

Available
3 3 2
T1 2 0 0
<T1, T3, T0, >
5 3 2
T3 2 1 1
7 4 3
T4 0 0 2
7 4 5
Deadlock

Available
3 3 2
T1 2 0 0
5 3 2
T3 2 1 1 <T1, T3, T4, T2, T0>
7 4 3
T4 0 0 2
7 4 5
T0 0 1 0
7 5 5
Deadlock
Available
3 3 2
T1 2 0 0
5 3 2
T3 2 1 1
7 4 3
T4 0 0 2
7 4 5
<T1, T3, T4, T0, T2> T0 0 1 0
7 5 5
T2 3 0 2
10 5 7
Deadlock
Deadlock detection
1. Single Instance of Each Resource Type
Resource Ri -> tx -> Rj
allocation Graph
Wait – for graph Ri -> Rj
Deadlock
2. Several Instances of a Resource Type
Deadlock
Detection-Algorithm Usage
1. How often is a deadlock likely to occur?
2. How many threads will be affected by deadlock when it happens?
Recovery from Deadlock
Abort all deadlocked processes: This method clearly will break the
deadlock cycle, but at great expense. The deadlocked processes may have
computed for a long time, and the results of these partial computations
must be discarded and probably will have to be recomputed later.
Abort one process at a time: until the deadlock cycle is eliminated. This
method incurs considerable overhead, since after each process is aborted,
a deadlock-detection algorithm must be invoked to determine whether
any processes are still deadlocked.
Deadlock
Many factors may affect which process is chosen, including:
1. What the priority of the process
2. How long the process has computed and how much longer the process will
compute before completing its designated task.
3. How many and what types of resources the process has used (for example,
whether the resources are simple to preempt)
4. How many more resources the process needs in order to complete.
5. How many processes will need to be terminated.
Resource pre-emption:
i. Selecting a victim
ii. Rollback
iii. starvation
Deadlock
1. Selecting a victim: Which resources and which processes are to be preempted? As in process
termination, we must determine the order of preemption to minimize cost. Cost factors may
include such parameters as the number of resources a deadlocked process is holding and the
amount of time the process has thus far consumed.
2. Rollback: If we preempt a resource from a process, what should be done with that process?
Clearly, it cannot continue with its normal execution; it is missing some needed resource. We must
roll back the process to some safe state and restart it from that state. Since, in general, it is difficult
to determine what a safe state is, the simplest solution is a total rollback: abort the process and
then restart it. Although it is more effective to roll back the process only as far as necessary to
break the deadlock, this method requires the system to keep more information about the state of
all running processes.
3. Starvation: How do we ensure that starvation will not occur? That is, how can we guarantee that
resources will not always be preempted from the same process? In a system where victim
selection is based primarily on cost factors, it may happen that the same process is always picked
as a victim. As a result, this process never completes its designated task, a starvation situation any
practical system must address. Clearly, we must ensure that a process can be picked as a victim
only a (small) finite number of times. The most common solution is to include the number of
rollbacks in the cost factor

You might also like