Build original Ada port core, V client, and x86-64 boot milestone
This commit is contained in:
1 parent
9af96aa1e1
commit
fc2bee6f32
28 files changed
+865
-7
No files matched your search
@@ -0,0 +1,116 @@
|
||||
package body Agila_Ports is
|
||||
use type Word;
|
||||
Max_Generation : constant Word := Word'Last / Max_Ports;
|
||||
function Valid (State : Manager; Handle : Word) return Boolean is
|
||||
Slot : constant Natural := Natural (Handle mod Max_Ports);
|
||||
begin
|
||||
return Handle >= Max_Ports
|
||||
and then State.Table (Slot).Active
|
||||
and then State.Table (Slot).Generation = Handle / Max_Ports;
|
||||
end Valid;
|
||||
|
||||
procedure Create (State : in out Manager; Owner : Word;
|
||||
Handle : out Word; Result : out Status) is
|
||||
begin
|
||||
Handle := 0;
|
||||
if Owner = 0 then Result := Invalid_Argument; return; end if;
|
||||
for Slot in State.Table'Range loop
|
||||
if not State.Table (Slot).Active and not State.Table (Slot).Retired then
|
||||
State.Table (Slot).Active := True;
|
||||
State.Table (Slot).Owner := Owner;
|
||||
State.Table (Slot).Allowed_Sender := 0;
|
||||
State.Table (Slot).Head := 0;
|
||||
State.Table (Slot).Count := 0;
|
||||
State.Table (Slot).Queue := [others => (0, 0)];
|
||||
Handle := State.Table (Slot).Generation * Max_Ports + Word (Slot);
|
||||
Result := Ok;
|
||||
return;
|
||||
end if;
|
||||
end loop;
|
||||
Result := Exhausted;
|
||||
end Create;
|
||||
|
||||
procedure Allow_Sender (State : in out Manager; Handle, Owner, Sender : Word;
|
||||
Result : out Status) is
|
||||
Slot : constant Natural := Natural (Handle mod Max_Ports);
|
||||
begin
|
||||
if not Valid (State, Handle) then Result := Invalid_Handle;
|
||||
elsif State.Table (Slot).Owner /= Owner then Result := Permission_Denied;
|
||||
elsif Sender = 0 then Result := Invalid_Argument;
|
||||
else State.Table (Slot).Allowed_Sender := Sender; Result := Ok;
|
||||
end if;
|
||||
end Allow_Sender;
|
||||
|
||||
procedure Revoke_Sender (State : in out Manager; Handle, Owner, Sender : Word;
|
||||
Result : out Status) is
|
||||
Slot : constant Natural := Natural (Handle mod Max_Ports);
|
||||
begin
|
||||
if not Valid (State, Handle) then Result := Invalid_Handle;
|
||||
elsif State.Table (Slot).Owner /= Owner then Result := Permission_Denied;
|
||||
elsif Sender = 0 or else State.Table (Slot).Allowed_Sender /= Sender then
|
||||
Result := Invalid_Argument;
|
||||
else State.Table (Slot).Allowed_Sender := 0; Result := Ok;
|
||||
end if;
|
||||
end Revoke_Sender;
|
||||
|
||||
procedure Send (State : in out Manager; Handle, Caller, Value : Word;
|
||||
Result : out Status) is
|
||||
Slot : constant Natural := Natural (Handle mod Max_Ports);
|
||||
begin
|
||||
if not Valid (State, Handle) then Result := Invalid_Handle; return; end if;
|
||||
declare
|
||||
P : Port renames State.Table (Slot);
|
||||
begin
|
||||
if Caller = 0 or else (Caller /= P.Owner and Caller /= P.Allowed_Sender) then
|
||||
Result := Permission_Denied;
|
||||
elsif P.Count = Queue_Capacity then Result := Full;
|
||||
else
|
||||
P.Queue ((P.Head + P.Count) mod Queue_Capacity) := (Caller, Value);
|
||||
P.Count := P.Count + 1;
|
||||
Result := Ok;
|
||||
end if;
|
||||
end;
|
||||
end Send;
|
||||
|
||||
procedure Receive (State : in out Manager; Handle, Caller : Word;
|
||||
Item : out Message; Result : out Status) is
|
||||
Slot : constant Natural := Natural (Handle mod Max_Ports);
|
||||
begin
|
||||
Item := (0, 0);
|
||||
if not Valid (State, Handle) then Result := Invalid_Handle; return; end if;
|
||||
declare
|
||||
P : Port renames State.Table (Slot);
|
||||
begin
|
||||
if Caller /= P.Owner then Result := Permission_Denied;
|
||||
elsif P.Count = 0 then Result := Empty;
|
||||
else
|
||||
Item := P.Queue (P.Head);
|
||||
P.Queue (P.Head) := (0, 0);
|
||||
P.Head := (P.Head + 1) mod Queue_Capacity;
|
||||
P.Count := P.Count - 1;
|
||||
Result := Ok;
|
||||
end if;
|
||||
end;
|
||||
end Receive;
|
||||
|
||||
procedure Close (State : in out Manager; Handle, Caller : Word;
|
||||
Result : out Status) is
|
||||
Slot : constant Natural := Natural (Handle mod Max_Ports);
|
||||
begin
|
||||
if not Valid (State, Handle) then Result := Invalid_Handle;
|
||||
elsif State.Table (Slot).Owner /= Caller then Result := Permission_Denied;
|
||||
else
|
||||
State.Table (Slot).Active := False;
|
||||
State.Table (Slot).Owner := 0;
|
||||
State.Table (Slot).Allowed_Sender := 0;
|
||||
State.Table (Slot).Count := 0;
|
||||
State.Table (Slot).Queue := [others => (0, 0)];
|
||||
if State.Table (Slot).Generation = Max_Generation then
|
||||
State.Table (Slot).Retired := True;
|
||||
else
|
||||
State.Table (Slot).Generation := State.Table (Slot).Generation + 1;
|
||||
end if;
|
||||
Result := Ok;
|
||||
end if;
|
||||
end Close;
|
||||
end Agila_Ports;
|
||||
@@ -0,0 +1,43 @@
|
||||
with Interfaces;
|
||||
package Agila_Ports is
|
||||
-- Original Open Agila implementation. Host identity values are supplied by
|
||||
-- trusted callers; a future syscall boundary must derive identity itself.
|
||||
subtype Word is Interfaces.Unsigned_32;
|
||||
Max_Ports : constant := 8;
|
||||
Queue_Capacity : constant := 4;
|
||||
type Status is (Ok, Invalid_Handle, Permission_Denied, Full, Empty,
|
||||
Exhausted, Invalid_Argument);
|
||||
type Message is record
|
||||
Sender : Word := 0;
|
||||
Value : Word := 0;
|
||||
end record;
|
||||
type Manager is limited private;
|
||||
procedure Create (State : in out Manager; Owner : Word;
|
||||
Handle : out Word; Result : out Status);
|
||||
procedure Allow_Sender (State : in out Manager; Handle, Owner, Sender : Word;
|
||||
Result : out Status);
|
||||
procedure Revoke_Sender (State : in out Manager; Handle, Owner, Sender : Word;
|
||||
Result : out Status);
|
||||
procedure Send (State : in out Manager; Handle, Caller, Value : Word;
|
||||
Result : out Status);
|
||||
procedure Receive (State : in out Manager; Handle, Caller : Word;
|
||||
Item : out Message; Result : out Status);
|
||||
procedure Close (State : in out Manager; Handle, Caller : Word;
|
||||
Result : out Status);
|
||||
private
|
||||
type Messages is array (Natural range 0 .. Queue_Capacity - 1) of Message;
|
||||
type Port is record
|
||||
Active : Boolean := False;
|
||||
Retired : Boolean := False;
|
||||
Generation : Word := 1;
|
||||
Owner : Word := 0;
|
||||
Allowed_Sender : Word := 0;
|
||||
Head : Natural range 0 .. Queue_Capacity - 1 := 0;
|
||||
Count : Natural range 0 .. Queue_Capacity := 0;
|
||||
Queue : Messages := [others => (0, 0)];
|
||||
end record;
|
||||
type Ports is array (Natural range 0 .. Max_Ports - 1) of Port;
|
||||
type Manager is limited record
|
||||
Table : Ports;
|
||||
end record;
|
||||
end Agila_Ports;
|
||||
Reference in new issue
Block a user