---
tags: Real-Time
title: Group stuff
author: PH Chou, YA Chen, YW Tung.
---
# Meeting Link:
## Google meet: [Link](https://meet.google.com/vjk-ikpa-ofj)
vjk-ikpa-ofj
## Overleaf
### Assignment 4: [Link](https://www.overleaf.com/9278639295qjwnkypmkvwj)
#
### Problem #4 in Assignment #1 (Submit)
[@StackOverFlow](https://stackoverflow.com/questions/68315025/how-to-implement-multi-producer-multi-consumer-single-buffer-model)
# Assignment #1 (Incomplete)
## Problem-3
```=
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Calendar;
use Ada.Calendar;
with Ada.Numerics.Discrete_Random;
procedure comm1 is
Message: constant String := "Process communication";
Flag_accept : Boolean := False;
Queue_counter : Integer := 0;
task buffer is
-- add your task entries for communication
entry Put(X:in Integer);
entry Get(X:out Integer);
entry Stop;
end buffer;
task producer is
-- add your task entries for communication
entry Stop;
end producer;
task consumer is
-- add your task entries for communication
end consumer;
task body buffer is
Message: constant String := "buffer executing";
-- change/add your local declarations here
front : Integer := -1;
rear : Integer := -1;
--buffer size setting:
size : Integer := 20;
queue : array (0..size) of integer;
total_queue : integer := 0;
Buffer_Flag : Boolean := False;
begin
Put_Line(Message);
loop
-- add your task code inside this loop
select
accept Put(X:Integer) do
--design buffer is a circular buffer.
if (front = 0 and rear = (size-1)) or
(rear = (front-1) rem (size-1)) then
Put_line("Queue is Full.");
--Set flag false
Flag_accept := False;
elsif (front = -1) then --first time input
--clear the array first
for index in queue'Range loop
queue(index) := 0;
end loop;
front := 0;
rear := 0;
queue(rear) := X;
total_queue := total_queue + queue(rear);
--C++
Queue_counter := Queue_counter + 1;
--set flag if is not empty
Flag_accept := True;
elsif (rear = (size-1) and front /= 0) then
rear := 0;
queue(rear) := X;
total_queue := total_queue + queue(rear);
--C++
Queue_counter := Queue_counter + 1;
--set flag if is not empty
Flag_accept := True;
else
rear := rear + 1;
queue(rear) := X;
total_queue := total_queue + queue(rear);
--C++
Queue_counter := Queue_counter + 1;
--set flag if is not empty
Flag_accept := True;
end if;
--display queue for debug
for index in queue'Range loop
Put(queue(index)'Img);
null;
end loop;
New_line;
if total_queue>0 then
Buffer_Flag:=True;
end if;
end;
or
accept Get(X:out Integer) do
--check whether the Queue is empty
if front = -1 then
--set flag to prevent the deadlock
Flag_accept := False;
Put_Line("Queue is Empty");
X := -1;
else
X := queue(front);
--clear array value
queue(front) := 0;
--Clear the memory and move the front
if front = rear then
front := -1;
rear := -1;
--C--
Queue_counter := Queue_counter - 1;
elsif (front = (size-1)) then
front := 0;
--C--
Queue_counter := Queue_counter - 1;
else
front := front +1;
--C--
Queue_counter := Queue_counter - 1;
end if;
end if;
end;
or
accept Stop;
Put_line("Buffer stop!");
exit;
end select;
end loop;
end buffer;
task body producer is
Message: constant String := "producer executing";
-- change/add your local declarations here
--random number
subtype Random_Number is Integer range 0 .. 20; --the range of the Integer
package R_N is new
Ada.Numerics.Discrete_Random (Random_Number);
use R_N;
G : R_N.Generator;
X : Random_Number;
--random time
Random_Duration : Duration;
type Random_Time is range 0..5000;
package R_T is new
Ada.Numerics.Discrete_Random (Random_Time);
use R_T;
G_T : R_T.Generator;
X_T : Random_Time;
period : Time := Clock;
begin
Put_Line(Message);
loop
-- add your task code inside this loop
select
accept Stop;
Put_line("Producer is terminate!");
exit;
else
Reset (G);
X := Random (G);
--Put
if Queue_counter <= 20 then
Buffer.Put(X);
Put_line("Producer Put: " & Integer'Image(X));
Put_Line("Queue counter is: " & Integer'Image(Queue_counter));
end if;
Reset(G_T);
X_T := Random (G_T);
-- Convert Num to a Duration value from 0.5 to 3.0
Random_Duration := Duration(X_T) / 1000.0;
delay Random_Duration;
end select;
end loop;
end producer;
task body consumer is
Message: constant String := "consumer executing";
-- change/add your local declarations here
get_number : Integer := 0;
consume_total : Integer := 0;
--random time
Random_Duration : Duration;
type Random_Time is range 0..5000;
package R_T is new
Ada.Numerics.Discrete_Random (Random_Time);
use R_T;
G_T : R_T.Generator;
X_T : Random_Time;
period : Time := Clock;
begin
Put_Line(Message);
Main_Cycle:
loop
-- add your task code inside this loop
Reset(G_T);
X_T := Random (G_T);
-- Convert Num to a Duration value from 1.0 to 3.0
Random_Duration := Duration(X_T) / 1000.0;
delay Random_Duration;
--get the buffer number by FIFO
if Flag_accept = True then
Buffer.Get(get_number);
if get_number <= 20 and get_number >= 0 then
Put_line("----------------------------");
Put_line("Consumer Get: " & Integer'Image(get_number));
consume_total := consume_total + get_number;
Put_line("Consumer Total Get: " & Integer'Image(consume_total));
Put_line("----------------------------");
end if;
end if;
--when sum > 100, exit main_cycle
if consume_total >= 100 then
Put_Line("The Consumer has more than 100.");
exit Main_Cycle;
end if;
end loop Main_Cycle;
-- add your code to stop executions of other tasks
producer.Stop;
buffer.Stop;
exception
when TASKING_ERROR =>
Put_Line("Buffer finished before producer");
Put_Line("Ending the consumer");
end consumer;
begin
Put_Line(Message);
end comm1;
```
### An
```=
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Calendar;
use Ada.Calendar;
with Ada.Numerics.Discrete_Random;
procedure comm1 is
Message: constant String := "Process communication";
Flag_accept : Boolean := False;
task buffer is
-- add your task entries for communication
entry Put(X:in Integer);
entry Get(X:out Integer);
entry Stop;
end buffer;
task producer is
-- add your task entries for communication
entry Stop;
end producer;
task consumer is
-- add your task entries for communication
end consumer;
task body buffer is
Message: constant String := "buffer executing";
-- change/add your local declarations here
front : Integer := -1;
rear : Integer := -1;
--buffer size setting:
size : Integer := 20;
queue : array (0..(size-1)) of integer;
total_queue : integer := 0;
Buffer_Flag : Boolean := False;
begin
Put_Line(Message);
loop
-- add your task code inside this loop
select
when not((front = 0 and rear = (size-1)) or (rear = (front-1) rem (size-1)))=>
accept Put(X:Integer) do
--design buffer is a circular buffer.
if (front = 0 and rear = (size-1)) or
(rear = (front-1) rem (size-1)) then
Put_line("Queue is Full.");
elsif (front = -1) then --first time input
--clear the array first
for index in queue'Range loop
queue(index) := 0;
end loop;
front := 0;
rear := 0;
queue(rear) := X;
total_queue := total_queue + queue(rear);
elsif (rear = (size-1) and front /= 0) then
rear := 0;
queue(rear) := X;
total_queue := total_queue + queue(rear);
else
rear := rear + 1;
queue(rear) := X;
total_queue := total_queue + queue(rear);
end if;
--display queue for debug
for index in queue'Range loop
--Put(queue(index)'Img);
null;
end loop;
--New_line;
if total_queue>0 then
Buffer_Flag:=True;
end if;
--set flag if is not empty
Flag_accept := True;
end;
or
when front /= -1 =>
accept Get(X:out Integer) do
--check whether the Queue is empty
if front = -1 then
--set flag to prevent the deadlock
Flag_accept := False;
Put_Line("Queue is Empty");
X := -1;
else
X := queue(front);
--clear array value
queue(front) := 0;
--Clear the memory and move the front
if front = rear then
front := -1;
rear := -1;
elsif (front = (size-1)) then
front := 0;
else
front := front +1;
end if;
end if;
end;
or
accept Stop;
Put_line("Buffer stop!");
exit;
end select;
end loop;
end buffer;
task body producer is
Message: constant String := "producer executing";
-- change/add your local declarations here
--random number
subtype Random_Number is Integer range 0 .. 20; --the range of the Integer
package R_N is new
Ada.Numerics.Discrete_Random (Random_Number);
use R_N;
G : R_N.Generator;
X : Random_Number;
--random time
Random_Duration : Duration;
type Random_Time is range 0..5000;
package R_T is new
Ada.Numerics.Discrete_Random (Random_Time);
use R_T;
G_T : R_T.Generator;
X_T : Random_Time;
period : Time := Clock;
begin
Put_Line(Message);
loop
-- add your task code inside this loop
select
accept Stop;
Put_line("Producer is terminate!");
exit;
else
Reset (G);
X := Random (G);
Buffer.Put(X);
Put_line("Producer Put: " & Integer'Image(X));
Reset(G_T);
X_T := Random (G_T);
-- Convert Num to a Duration value from 0.5 to 3.0
Random_Duration := Duration(X_T) / 1000.0;
delay Random_Duration;
end select;
end loop;
end producer;
task body consumer is
Message: constant String := "consumer executing";
-- change/add your local declarations here
get_number : Integer := 0;
consume_total : Integer := 0;
--random time
Random_Duration : Duration;
type Random_Time is range 0..5000;
package R_T is new
Ada.Numerics.Discrete_Random (Random_Time);
use R_T;
G_T : R_T.Generator;
X_T : Random_Time;
period : Time := Clock;
begin
Put_Line(Message);
Main_Cycle:
loop
-- add your task code inside this loop
Reset(G_T);
X_T := Random (G_T);
-- Convert Num to a Duration value from 1.0 to 3.0
Random_Duration := Duration(X_T) / 1000.0;
delay Random_Duration;
--get the buffer number by FIFO
Buffer.Get(get_number);
if get_number <= 20 and get_number >= 0 then
Put_line("----------------------------");
Put_line("Consumer Get: " & Integer'Image(get_number));
consume_total := consume_total + get_number;
Put_line("Consumer Total Get: " & Integer'Image(consume_total));
Put_line("----------------------------");
end if;
--when sum > 100, exit main_cycle
if consume_total >= 100 then
Put_Line("The Consumer has more than 100.");
exit Main_Cycle;
end if;
end loop Main_Cycle;
-- add your code to stop executions of other tasks
producer.Stop;
buffer.Stop;
exception
when TASKING_ERROR =>
Put_Line("Buffer finished before producer");
Put_Line("Ending the consumer");
end consumer;
begin
Put_Line(Message);
end comm1;
```
# Assignment #2 (Complete!!)
[Difference between Interrupt and Polling](https://www.geeksforgeeks.org/difference-between-interrupt-and-polling/)
## LSD sensor number
LSD 1: left, LSD 2: middle, LSD 3: right.
If sensor number := 800, is on the white area, and if sensor number is := 200-300 is on the black line.
# Assignment #3
## Part 1
### 1-1
```=c++
```
### 1-2
```=c++
```
### 1-3
```=c++
```
### 1-4
```=c++
```
### 1-5
```=c++
```
### 1-6
```=c++
```
### 1-7
```=c++
system Example {
declarations {
tasks t1, t2, t3;
indexed T,C,R,D,U;
priority P;
}
initialise {
! Periods
T[t1] = 10;
T[t2] = 15;
T[t3] = 35;
! WCETs
C[t1] = 2;
C[t2] = 4;
C[t3] = 10;
! Deadlines (not used)
D[t1] = 10;
D[t2] = 15;
D[t3] = 35;
! Priorities
P[t1] = 1;
P[t2] = 2;
P[t3] = 3;
}
formulas {
! Calculate the response-time for each task
R[i] = C[i] + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
! Calculate the utilization in the system
! U must be indexed since lside and rside must be the same.
U[i] = sigma(all, C[j]/T[j]);
}
}
```

## Part 2
## 2-1
DM
```=c++
system Example
{
declarations
{
tasks t1, t2, t3, t4;
indexed T,C,R,D,U;
priority P;
}
initialise
{
! Periods
T[t1] = 20;
T[t2] = 7;
T[t3] = 14;
T[t4] = 100;
! WCETs
C[t1] = 2;
C[t2] = 3;
C[t3] = 5;
C[t4] = 4;
! Deadlines (not used)
D[t1] = 6;
D[t2] = 7;
D[t3] = 13;
D[t4] = 60;
! Priorities
P[t1] = 1;
P[t2] = 2;
P[t3] = 3;
P[t4] = 4;
}
formulas
{
R[i] = C[i] + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
U[i] = sigma(all, C[j]/T[j]);
}
}
```

RM
```=c++
system Example
{
declarations
{
tasks t1, t2, t3, t4;
indexed T,C,R,D,U;
priority P;
}
initialise
{
T[t1] = 20;
T[t2] = 7;
T[t3] = 14;
T[t4] = 100;
C[t1] = 2;
C[t2] = 3;
C[t3] = 5;
C[t4] = 4;
D[t1] = 6;
D[t2] = 7;
D[t3] = 13;
D[t4] = 60;
P[t1] = 3;
P[t2] = 1;
P[t3] = 2;
P[t4] = 4;
}
formulas
{
R[i] = C[i] + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
U[i] = sigma(all, C[j]/T[j]);
}
}
```

## 2-2
Short Ci high priority
```=c++
system Example
{
declarations
{
tasks t1, t2, t3, t4;
indexed T,C,R,D,U;
priority P;
}
initialise
{
T[t1] = 20;
T[t2] = 7;
T[t3] = 14;
T[t4] = 100;
C[t1] = 2;
C[t2] = 3;
C[t3] = 5;
C[t4] = 4;
D[t1] = 6;
D[t2] = 7;
D[t3] = 13;
D[t4] = 60;
P[t1] = 1;
P[t2] = 2;
P[t3] = 4;
P[t4] = 3;
}
formulas
{
R[i] = C[i] + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
U[i] = sigma(all, C[j]/T[j]);
}
}
```

met case
```=c++
system Example
{
declarations
{
tasks t1, t2, t3, t4;
indexed T,C,R,D,U;
priority P;
}
initialise
{
T[t1] = 20;
T[t2] = 7;
T[t3] = 14;
T[t4] = 100;
C[t1] = 2;
C[t2] = 3;
C[t3] = 5;
C[t4] = 4;
D[t1] = 6;
D[t2] = 7;
D[t3] = 13;
D[t4] = 60;
P[t1] = 2;
P[t2] = 1;
P[t3] = 3;
P[t4] = 4;
}
formulas
{
R[i] = C[i] + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
U[i] = sigma(all, C[j]/T[j]);
}
}
```

Revised: high to low -> T2, T1, T3, T4.
### 2-3
```=c++
system Example
{
declarations
{
tasks t1, t2, t3, t4;
indexed T,C,R,D,U;
priority P;
}
initialise
{
T[t1] = 20;
T[t2] = 7;
T[t3] = 14;
T[t4] = 100;
C[t1] = 2;
C[t2] = 3;
C[t3] = 5;
C[t4] = 4;
D[t1] = 6;
D[t2] = 7;
D[t3] = 13;
D[t4] = 60;
P[t1] = 1;
P[t2] = 2;
P[t3] = 2;
P[t4] = 3;
}
formulas
{
R[i] = sigma(ep,C[j]) + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
U[i] = sigma(all, C[j]/T[j]);
}
}
```
## Part 3
### 3-1
```=c++
system Example
{
declarations
{
tasks t1, t2, t3, t4;
indexed T,C,R,D,U;
priority P;
}
initialise
{
T[t1] = 10;
T[t2] = 20;
T[t3] = 40;
T[t4] = 100;
C[t1] = 2;
C[t2] = 3;
C[t3] = 10;
C[t4] = 4;
D[t1] = 5;
D[t2] = 12;
D[t3] = 40;
D[t4] = 50;
P[t1] = 1;
P[t2] = 2;
P[t3] = 3;
P[t4] = 4;
}
formulas
{
R[i] = C[i] + sigma(hp, ceiling((R[i])/T[j]) * C[j]);
U[i] = sigma(all, C[j]/T[j]);
}
}
```

### 3-2
#### Comment: About 3.2, based on the question you should use a critical instant scheme to answer it (“by doing a critical instant scheme”). You should add a corresponding diagram to your report.
```= c++
scalar GlobalVar;
system testing
{
declarations
{
indexed Period, Deadline, CompTime, RespTime;
blocking Blockvar;
priority Priovar;
tasks T1, T2, T3, T4;
}
semaphores
{
semaphore(S1,T2,1);
semaphore(S1,T4,2);
}
initialise
{
Period[T1]=10;
Period[T2]=20;
Period[T3]=40;
Period[T4]=100;
Deadline[T1]=5;
Deadline[T2]=12;
Deadline[T3]=40;
Deadline[T4]=50;
Priovar[T1]=1;
Priovar[T2]=2;
Priovar[T3]=4;
Priovar[T4]=3;
CompTime[T1]=2;
CompTime[T2]=3;
CompTime[T3]=10;
CompTime[T4]=4;
}
formulas
{
RespTime[i]=CompTime[i]+Blockvar[i]+sigma(hp,ceiling(RespTime[i]/Period[j])*CompTime[j]);
GlobalVar=CompTime[T1]+CompTime[T2]*CompTime[T3];
}
}
```

### 3-3
#### Comment: About 3.3, similar to 3.2, You should add a corresponding diagram to your report.
```= c++
scalar GlobalVar;
system testing
{
declarations
{
indexed Period, Deadline, CompTime, RespTime;
blocking Blockvar;
priority Priovar;
tasks T1, T2, T3, T4;
}
semaphores
{
semaphore(S1,T2,1);
semaphore(S1,T4,2);
semaphore(S2,T2,1);
semaphore(S2,T3,5);
}
initialise
{
Period[T1]=10;
Period[T2]=20;
Period[T3]=40;
Period[T4]=100;
Deadline[T1]=5;
Deadline[T2]=12;
Deadline[T3]=40;
Deadline[T4]=50;
Priovar[T1]=2;
Priovar[T2]=3;
Priovar[T3]=4;
Priovar[T4]=1;
CompTime[T1]=2;
CompTime[T2]=3;
CompTime[T3]=10;
CompTime[T4]=4;
}
formulas
{
RespTime[i]=CompTime[i]+Blockvar[i]+sigma(hp,ceiling(RespTime[i]/Period[j])*CompTime[j]);
GlobalVar=CompTime[T1]+CompTime[T2]*CompTime[T3];
}
}
```

### 3-4
#### Comment: about 3.4, You should cover all parts of the question: “What are the blocking times for the tasks in Figure 6 using the priority inheritance protocol?” and “What are the response times for the tasks when using the priority inheritance protocol?” You should report blocking time for all the tasks (for example in table) and then apply the worst-case response time analysis test using these.
### 3-5
#### Comment: about 3.5, “What are the blocking times for the tasks in Figure 6 using the immediate inheritance protocol?” and “Will all tasks complete before their deadlines?” I couldn’t find anything about these parts of the question in your report. You should cover all parts of the question. You should provide a table with blocking time for each task and apply the worst-case response-time analysis test to check schedulability of the task set.
## Part 4
#### Commnet: Ex4: - 4.2 and 4.3: It's better to state clearly the value of jitter instead of pointing to the figure. The second part of the question specifically ask for the jitter
### 4-4
```= c++
scalar GlobalVar;
system testing
{
declarations
{
indexed Period, Deadline, CompTime, RespTime,W;
tasks T1, T2;
priority Priority;
}
initialise
{
Period[T1]=20;
Period[T2]=50;
Deadline[T1]=10;
Deadline[T2]=50;
CompTime[T1]=5;
CompTime[T2]=30;
Priority[T1]=1;
Priority[T2]=2;
}
formulas
{
W[i]=CompTime[i]+sigma(hp,ceiling(W[i]/Period[j])*CompTime[j]);
!W[i]=CompTime[i]+sigma(hp,ceiling(1+((W[i]-Period[j])/Period[j]))*CompTime[j]);
RespTime[i]=W[i];
GlobalVar=CompTime[T1]+CompTime[T2];
}
}
```

### 4-5
#### 4.5 and 4.6: the calculated values are correct, but your figures 13, 14 are wrong. First, this is not the worst case scenario that give the maximum response time for the tasks. Second, your drawing about jitter is not correct. Jitter is counted from the arrival time of the task until the time the task can start its execution, but still can be blocked by higher priority task, the time when the task is blocked by higher priority task is not counted as jitter (Yeah I know this is a little bit confusing with the first 4.1, 4.2, 4.3 exercises)
```= c++
scalar GlobalVar;
system testing
{
declarations
{
indexed Period, Deadline, CompTime, RespTime,W,jitter;
priority Priority;
tasks T1, T2;
}
initialise
{
Period[T1]=20;
Period[T2]=50;
Deadline[T1]=10;
Deadline[T2]=50;
Priority[T1]=1;
Priority[T2]=2;
CompTime[T1]=5;
CompTime[T2]=30;
jitter[T1]=5;
jitter[T2]=10;
}
formulas
{
W[i]=CompTime[i]+sigma(hp,ceiling((W[i]+jitter[j])/Period[j])*CompTime[j]);
RespTime[i]=W[i]+jitter[i];
!W[i]=CompTime[i]+sigmng(1+((W[i]-(Period[j]-jitter[j]))/Period[j]))*CompTime[j]);
!RespTime[i]=W[i]+jitter[i];
}
}
```

### 4-6
```= c++
scalar GlobalVar;
system testing
{
declarations
{
indexed Period, Deadline, CompTime, RespTime,W,jitter;
priority Priority;
tasks T1, T2;
}
initialise
{
Period[T1]=20;
Period[T2]=50;
Deadline[T1]=10;
Deadline[T2]=50;
Priority[T1]=2;
Priority[T2]=1;
CompTime[T1]=5;
CompTime[T2]=30;
jitter[T1]=5;
jitter[T2]=10;
}
formulas
{
W[i]=CompTime[i]+sigma(hp,ceiling((W[i]+jitter[j])/Period[j])*CompTime[j]);
RespTime[i]=W[i]+jitter[i];
!W[i]=CompTime[i]+sigmng(1+((W[i]-(Period[j]-jitter[j]))/Period[j]))*CompTime[j]);
!RespTime[i]=W[i]+jitter[i];
}
}
```

# Assignment 4
verifier
```
E<> done_counter == 5
```
then click "get trace"
# References
* [1] Ada Learning source: [Introduction to Ada](https://learn.adacore.com/courses/intro-to-ada/index.html)
* [2] Matplotlib arrow: [Annotations](https://matplotlib.org/stable/tutorials/text/annotations.html)
* [3] Drawing the arrow with Matplotlib: [Drawing arrows in Matplotlib](https://www.skytowner.com/explore/drawing_arrows_in_matplotlib)