p22 9117 Assignment4
p22 9117 Assignment4
22p-9117
Assignment # 4
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.
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
Q6.Run spin to verify the code. Show the output and identify if
there are any issues in the code.
• 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).
// 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
}
// 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.