0% found this document useful (0 votes)
6 views15 pages

p22 9117 Assignment4

Uploaded by

Kashan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views15 pages

p22 9117 Assignment4

Uploaded by

Kashan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 15

Ikrama Shah

22p-9117

Assignment # 4

Q1.Store the above file as rollnumber_pc.pml (e.g. p20-


1234_pc.pml). Then, head over
https://www.geeksforgeeks.org/producer-consumer-problem-
in-c/ and download the provided C code and store it as
rollnumber_pc.c (e.g. p20-1234_pc.c). Run both codes, and
comment on the difference between both executions.
Particularly reduce the buffer size to 1 and see if the behavior
is correct.

PROMELA CODE
when I ran the promela code it continuously generate
the items and add them in the buffer and cumer remove them from
the buffer
Producer:
• Continuously generates items and attempts to place them in
the buffer.
• If the buffer is full, the producer process is blocked until
space becomes available.
• Consumer:
• Continuously removes items from the buffer for processing.
• If the buffer is empty, the consumer process is blocked until
an item is added by the producer.
• Synchronization:
• The channel (buffer) inherently provides synchronization:
• If the buffer is full, the producer blocks.
• If the buffer is empty, the consumer blocks.
C CODE
When I ran the c code that I downloaded from geeks for geeks
it simply gave the option and choice to produce consume or exit
the code
Q2.Obtain the automata view of both the producer and
consumer from your promela code. You can get this view from
ispin. Alternatively, you may run the commands: (a) spin -a
p20-1234_pc.pml, (b) gcc pan.c, (c) ./a.out -D, (d) dot -Tps
dot.tmp -o dot.ps. Open the file dot.ps. If you want to convert
it to pdf, then finally use: (e) ps2pdf dot.ps dot.pdf.
To obtain the automata view of the producer and consumer
processes from your Promela code, first, use the spin tool to
generate the verifier files by running spin -a p22-
9117_pc.pml. Then compile the generated pan.c file using
gcc pan.c -o pan. Next, execute the ./pan -D command
to generate the dot.tmp file, which contains the state transition
data for the automata. Use Graphviz to convert this data into a
visual representation by running dot -Tps dot.tmp -o
dot.ps to create a PostScript file. Finally, convert the PostScript
file into a PDF for easier viewing using ps2pdf dot.ps
dot.pdf. Open the resulting PDF file to analyze the automata
representing the behavior of the producer and consumer processes.
Q3.Run spin to verify the code. Show the output and identify if
there are any issues in the code.

The producer generates items and adds them to the buffer.


• The consumer removes items from the buffer and processes
them.
• Synchronization ensures:
• The producer waits if the buffer is full.
• The consumer waits if the buffer is empty.
• Mutual exclusion prevents race conditions on the buffer.
Q4.Run the modified rollnumber_pc.pml (e.g. p20-
1234_pc.pml) code again and notice if there is any
change in behavior compared to its previous version, and
make a comment.

Comment
The modified code introduces robust synchronization mechanisms
using semaphores, addressing the shortcomings of the original
code. This ensures smooth, safe interactions between the producer
and consumer processes, even under extreme conditions such as a
full or empty buffer. The changes make the program deterministic
and eliminate concurrency issues like deadlocks or race
conditions.
Q5.Obtain the automata view of the modified code and present
it in your report
Automata View
Producer
Consumer

After modifying the Promela code to include proper


synchronization mechanisms using semaphores (isFull,
isEmpty, and mutex), I generated the automata view to
visualize the process behavior. The automata show distinct states
for both the producer and consumer processes with their
respective transitions. The automata reveal improved
synchronization, preventing issues such as buffer overflow and
underflow by using semaphore operations (P() and V()). These
changes ensure mutual exclusion and proper interaction between
the processes, demonstrating a significant improvement over the
original code.

Q6.Run spin to verify the code. Show the output and identify if
there are any issues in the code.

Interpreting the Output


• Expected Output:
• If the code is correct:
• No errors or warnings should be produced during the
verification process.
• If there are issues:
• The output will list states and transitions leading to possible
errors such as deadlocks, buffer overflows, or invalid states.
• Warnings may also appear regarding potential issues with the
code structure.

• Issues:
• Deadlocks:
• If the buffer becomes full and the producer attempts to add an
item, Spin may show a state where the producer is blocked
indefinitely.
• Invalid States:
• Buffer underflow situations when the consumer tries to
remove an item from an empty buffer.
• Warnings:
• Potential synchronization issues might be reported (e.g.,
improper semaphore operations).

Q7.Modify the code to have two producers and two consumer


threads, and then verify the code using spin
CODE
#define BUFFER_SIZE 5
chan buffer = [BUFFER_SIZE] of { int };

int isFull = 0; // Filled slots in the buffer


int isEmpty = BUFFER_SIZE; // Empty slots in the buffer
int mutex = 1; // Semaphore for mutual exclusion
// Semaphore operations
inline P(s) { atomic { s > 0 -> s--; } }
inline V(s) { atomic { s < BUFFER_SIZE -> s++; } }

// Producer Process
active proctype Producer() {
int item;
do
:: select(item : 1..100); // Generate a random item between 1
and 100
P(isEmpty); // Wait for an empty slot in the buffer
P(mutex); // Wait for exclusive access to the buffer
buffer!item; // Add item to the buffer
printf("Produced: %d\n", item);
V(mutex); // Release exclusive access
V(isFull); // Signal that a new item is in the buffer
od
}

// Consumer Process
active proctype Consumer() {
int item;
do
:: P(isFull); // Wait for an item to be available in the
buffer
P(mutex); // Wait for exclusive access to the buffer
buffer?item; // Remove an item from the buffer
printf("Consumed: %d\n", item);
V(mutex); // Release exclusive access
V(isEmpty); // Signal that a slot in the buffer is now
empty
od
}

// Launching Two Producers and Two Consumers


init {
run Producer();
run Producer(); // Second Producer
run Consumer();
run Consumer(); // Second Consumer
}
Q8.The conditions used for P(isFull), P(isEmpty), and
P(mutex) are all the same. Modify the code for mutex lock so
that Producer and Consumer takes turns, i.e. they run in lock-
step.
#define BUFFER_SIZE 5
chan buffer = [BUFFER_SIZE] of { int };

int isFull = 0; // Filled slots in the buffer


int isEmpty = BUFFER_SIZE; // Empty slots in the buffer
int turn = 0; // Turn variable: 0 for Producer, 1 for
Consumer
// Semaphore operations
inline P(s) { atomic { s > 0 -> s--; } }
inline V(s) { atomic { s < BUFFER_SIZE -> s++; } }

// Producer Process
active proctype Producer() {
int item;
do
:: atomic {
turn == 0 -> // Wait for Producer's turn
select(item : 1..100); // Generate a random item between 1
and 100
P(isEmpty); // Wait for an empty slot in the buffer
buffer!item; // Add item to the buffer
printf("Produced: %d\n", item);
turn = 1; // Give turn to Consumer
V(isFull); // Signal that a new item is in the buffer
}
od
}

// Consumer Process
active proctype Consumer() {
int item;
do
:: atomic {
turn == 1 -> // Wait for Consumer's turn
P(isFull); // Wait for an item to be available in the
buffer
buffer?item; // Remove an item from the buffer
printf("Consumed: %d\n", item);
turn = 0; // Give turn to Producer
V(isEmpty); // Signal that a slot in the buffer is now
empty
}
od
}
BEHAVIOR
The modified code enforces lock-step synchronization between
the Producer and Consumer using the turn variable. The
Producer generates an item, places it in the buffer, and then sets
turn = 1 to give control to the Consumer. The Consumer
removes the item from the buffer, processes it, and sets turn =
0 to return control to the Producer. This strict alternation ensures
no race conditions or deadlocks. The buffer state is always
consistent, as only one process accesses it at a time. The
verification results confirm that the system operates correctly
without any errors or invalid states. The infinite nature of the
processes leads to unreached end states, which is expected.

You might also like