Skip to content

Instantly share code, notes, and snippets.

@Juddling
Last active May 8, 2016 16:18
Show Gist options
  • Select an option

  • Save Juddling/7def062f4543f0fbf059f0a5ec3928ee to your computer and use it in GitHub Desktop.

Select an option

Save Juddling/7def062f4543f0fbf059f0a5ec3928ee to your computer and use it in GitHub Desktop.
task body Periodic is
Next_Release : Time;
Next_Deadline : Time;
Period : Time_Span := Milliseconds(500);
Deadline : Time_Span := Milliseconds(10);
begin
loop
select
delay until Next_Dealine;
-- deadline miss recovery code here
then abort
-- perform periodic computations here
end select;
-- hold the task until it is ready to be released again
delay until Next_Release;
Next_Release := Next_Release + Period;
Next_Deadline := Next_Release + Deadline;
end loop;
end Periodic;
with Ada.Real_Time; use Ada.Real_time;
with Ada.Execution_Time; use Ada.Execution_Time;
with Ada.Execution_Time.Timers; use Ada.Execution_Time.Timers;
with Ada.Task_Identification; use Ada.Task_Identification;
procedure E_Time is
-- I think all the protected object needs to do is have a Handler with the correct
-- type signature, and an entry which executes on the deadline miss
-- i.e. the Handler releases the entry
protected WCET is
entry FireOnDeadlineMiss;
procedure Handler(T : in out Timer);
private
Missed : Boolean := False;
end WCET;
protected body WCET is
entry FireOnDeadlineMiss when Missed is
begin
Missed := False;
end FireOnDeadlineMiss;
-- the handler is called once the task hits a specified execution time
-- we could do something else here like lowering the task's priority, rather than
-- opening a barrier which will abort the task
procedure Handler(T : in out Timer) is
begin
Missed := True;
end Handler;
end WCET;
-- this is the periodic task that will abort if its execution time
-- exceeds a defined limit
task t;
task body t is
Worst_Limit : Time_Span := Milliseconds(1);
Interval : Time_Span := Milliseconds(10);
Next_Release : Time := Clock; -- initialise to current time
-- Current_Task is a function from the Ada.Task_Identification package
Id : aliased Task_Id := Current_Task;
WCET_Error : Timer(Current_Task'Access); -- execution timer, pass pointer to current task
begin
-- set handler which will be called if the execution time of this task
-- exceeds Worst_Limit
Set_Handler(WCET_Error, Worst_Limit, WCET.Handler'Access);
loop
select
WCET.FireOnDeadlineMiss;
Put_Line("Deadline Missed");
then abort
-- abortable code
-- code to be performed each period
Put_Line("Executing");
end select;
delay until Next_Release;
Next_Release := Clock + Interval;
-- setting the handler again resets the execution time
Set_Handler(WCET_Error, Worst_Limit, WCET.Handler'Access);
end loop;
end t;
begin
null;
end E_Time;
begin
-- do some shit that can throw exceptions
exception
when My_Exception =>
-- tidy up
raise; -- raise exception to parent
When E: others => -- All other exceptions
-- tidy up
Put_Line(Exception_Name(E));
raise; -- raise exception to parent
end My_Example;
with Ada.Text_IO; use Ada.Text_IO;
procedure Majority_Voting is
type Decision is (Yes, No);
type Decisions is array(0..2) of Decision;
protected Voting_Barrier is
entry Wait(Vote : in Decision; Majority : out Decision);
procedure Add_Vote(Vote : in Decision);
private
-- Wait() entry calls are requeued here
-- must have same function signature
entry All_Votes(Vote : in Decision; Majority : out Decision);
Releasing : Boolean := False;
Current_Index : Integer := 0;
Votes : Decisions;
end Voting_Barrier;
protected body Voting_Barrier is
entry Wait(Vote : in Decision; Majority : out Decision)
when True is
begin
Add_Vote(Vote);
-- received vote, now requeue on a private entry
requeue All_Votes;
end Wait;
entry All_Votes(Vote : in Decision; Majority : out Decision)
when All_Votes'count = 3 or Releasing is
begin
if Votes(0) = Votes(1) or Votes(0) = Votes(2) then
Majority := Votes(0);
else
Majority := Votes(1);
end if;
-- once the first task is let in, the queue size will be 2
if All_Votes'Count = 2 then
-- make sure other tasks are released too
Releasing := True;
end if;
end All_Votes;
procedure Add_Vote(Vote : in Decision) is
begin
Votes(Current_Index) := Vote;
Current_Index := Current_Index + 1;
end Add_Vote;
end Voting_Barrier;
-- voting task
task type Voter (D : Decision);
task body Voter is
M : Decision;
begin
Put_Line("sending a vote of: " & Decision'Image(D));
Voting_Barrier.Wait(D, M);
if M = Yes then
Put_Line("majority: Yes");
else
Put_Line("majority: No");
end if;
end Voter;
A : Voter(No);
B : Voter(Yes);
C : Voter(Yes);
begin
null;
end Majority_Voting;
-- spec_paper_3iii
type Control_Register is
record
Sensors : Boolean;
Panic : Boolean;
Panic_Reset : Boolean;
end record;
for Control_Register use
record
Sensors at 0 range 0..0;
Panic at 0 range 6..6;
Panic_Reset at 0 range 7..7;
end record;
-- set attributes
for Control_Register'Size use 16;
for Control_Register'Alignment use 2;
for Control_Register'Bit_Order use Low_Order_First;
-- set address, size and alignment of control register
Control_Addr : constant Address := To_Address(8#150000#);
Control_R : Control_Register;
for Control_R'Address use Control_Addr;
-- can then do:
Control_R.Panic := True;
Control_R.Panic_Reset := True;
-- note clock is a parameterless function
-- suffers from local drift but not cumulative drift
Next_Time := Clock + Interval;
loop
Some_Action;
delay until Next_Time;
Next_time := Next_Time + Interval;
end loop;
declare
use Ada.Real_Time;
Start, Finish : Time;
begin
Start := Clock;
-- some function to measure
Finish := Clock;
-- Duration is Finish-Start
-- Not sure what type this would produce, Time_Span?
end;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment