blob: b8ca67e85b2fec4ac801c823b68a6d6738b5145a [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S Y S T E M . A U X _ D E C --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2012, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. --
-- --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception, --
-- version 3.1, as published by the Free Software Foundation. --
-- --
-- You should have received a copy of the GNU General Public License and --
-- a copy of the GCC Runtime Library Exception along with this program; --
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
-- <http://www.gnu.org/licenses/>. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
-- This is the Itanium/VMS version.
-- The Add,Clear_Interlocked subprograms are dubiously implmented due to
-- the lack of a single bit sync_lock_test_and_set builtin.
-- The "Retry" parameter is ignored due to the lack of retry builtins making
-- the subprograms identical to the non-retry versions.
pragma Style_Checks (All_Checks);
-- Turn off alpha ordering check on subprograms, this unit is laid
-- out to correspond to the declarations in the DEC 83 System unit.
with Interfaces;
package body System.Aux_DEC is
use type Interfaces.Unsigned_8;
------------------------
-- Fetch_From_Address --
------------------------
function Fetch_From_Address (A : Address) return Target is
type T_Ptr is access all Target;
function To_T_Ptr is new Ada.Unchecked_Conversion (Address, T_Ptr);
Ptr : constant T_Ptr := To_T_Ptr (A);
begin
return Ptr.all;
end Fetch_From_Address;
-----------------------
-- Assign_To_Address --
-----------------------
procedure Assign_To_Address (A : Address; T : Target) is
type T_Ptr is access all Target;
function To_T_Ptr is new Ada.Unchecked_Conversion (Address, T_Ptr);
Ptr : constant T_Ptr := To_T_Ptr (A);
begin
Ptr.all := T;
end Assign_To_Address;
-----------------------
-- Clear_Interlocked --
-----------------------
procedure Clear_Interlocked
(Bit : in out Boolean;
Old_Value : out Boolean)
is
Clr_Bit : Boolean := Bit;
Old_Uns : Interfaces.Unsigned_8;
function Sync_Lock_Test_And_Set
(Ptr : Address;
Value : Interfaces.Unsigned_8) return Interfaces.Unsigned_8;
pragma Import (Intrinsic, Sync_Lock_Test_And_Set,
"__sync_lock_test_and_set_1");
begin
Old_Uns := Sync_Lock_Test_And_Set (Clr_Bit'Address, 0);
Bit := Clr_Bit;
Old_Value := Old_Uns /= 0;
end Clear_Interlocked;
procedure Clear_Interlocked
(Bit : in out Boolean;
Old_Value : out Boolean;
Retry_Count : Natural;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
Clr_Bit : Boolean := Bit;
Old_Uns : Interfaces.Unsigned_8;
function Sync_Lock_Test_And_Set
(Ptr : Address;
Value : Interfaces.Unsigned_8) return Interfaces.Unsigned_8;
pragma Import (Intrinsic, Sync_Lock_Test_And_Set,
"__sync_lock_test_and_set_1");
begin
Old_Uns := Sync_Lock_Test_And_Set (Clr_Bit'Address, 0);
Bit := Clr_Bit;
Old_Value := Old_Uns /= 0;
Success_Flag := True;
end Clear_Interlocked;
---------------------
-- Set_Interlocked --
---------------------
procedure Set_Interlocked
(Bit : in out Boolean;
Old_Value : out Boolean)
is
Set_Bit : Boolean := Bit;
Old_Uns : Interfaces.Unsigned_8;
function Sync_Lock_Test_And_Set
(Ptr : Address;
Value : Interfaces.Unsigned_8) return Interfaces.Unsigned_8;
pragma Import (Intrinsic, Sync_Lock_Test_And_Set,
"__sync_lock_test_and_set_1");
begin
Old_Uns := Sync_Lock_Test_And_Set (Set_Bit'Address, 1);
Bit := Set_Bit;
Old_Value := Old_Uns /= 0;
end Set_Interlocked;
procedure Set_Interlocked
(Bit : in out Boolean;
Old_Value : out Boolean;
Retry_Count : Natural;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
Set_Bit : Boolean := Bit;
Old_Uns : Interfaces.Unsigned_8;
function Sync_Lock_Test_And_Set
(Ptr : Address;
Value : Interfaces.Unsigned_8) return Interfaces.Unsigned_8;
pragma Import (Intrinsic, Sync_Lock_Test_And_Set,
"__sync_lock_test_and_set_1");
begin
Old_Uns := Sync_Lock_Test_And_Set (Set_Bit'Address, 1);
Bit := Set_Bit;
Old_Value := Old_Uns /= 0;
Success_Flag := True;
end Set_Interlocked;
---------------------
-- Add_Interlocked --
---------------------
procedure Add_Interlocked
(Addend : Short_Integer;
Augend : in out Aligned_Word;
Sign : out Integer)
is
Overflowed : Boolean := False;
Former : Aligned_Word;
function Sync_Fetch_And_Add
(Ptr : Address;
Value : Short_Integer) return Short_Integer;
pragma Import (Intrinsic, Sync_Fetch_And_Add, "__sync_fetch_and_add_2");
begin
Former.Value := Sync_Fetch_And_Add (Augend.Value'Address, Addend);
if Augend.Value < 0 then
Sign := -1;
elsif Augend.Value > 0 then
Sign := 1;
else
Sign := 0;
end if;
if Former.Value > 0 and then Augend.Value <= 0 then
Overflowed := True;
end if;
if Overflowed then
raise Constraint_Error;
end if;
end Add_Interlocked;
----------------
-- Add_Atomic --
----------------
procedure Add_Atomic
(To : in out Aligned_Integer;
Amount : Integer)
is
procedure Sync_Add_And_Fetch
(Ptr : Address;
Value : Integer);
pragma Import (Intrinsic, Sync_Add_And_Fetch, "__sync_add_and_fetch_4");
begin
Sync_Add_And_Fetch (To.Value'Address, Amount);
end Add_Atomic;
procedure Add_Atomic
(To : in out Aligned_Integer;
Amount : Integer;
Retry_Count : Natural;
Old_Value : out Integer;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
function Sync_Fetch_And_Add
(Ptr : Address;
Value : Integer) return Integer;
pragma Import (Intrinsic, Sync_Fetch_And_Add, "__sync_fetch_and_add_4");
begin
Old_Value := Sync_Fetch_And_Add (To.Value'Address, Amount);
Success_Flag := True;
end Add_Atomic;
procedure Add_Atomic
(To : in out Aligned_Long_Integer;
Amount : Long_Integer)
is
procedure Sync_Add_And_Fetch
(Ptr : Address;
Value : Long_Integer);
pragma Import (Intrinsic, Sync_Add_And_Fetch, "__sync_add_and_fetch_8");
begin
Sync_Add_And_Fetch (To.Value'Address, Amount);
end Add_Atomic;
procedure Add_Atomic
(To : in out Aligned_Long_Integer;
Amount : Long_Integer;
Retry_Count : Natural;
Old_Value : out Long_Integer;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
function Sync_Fetch_And_Add
(Ptr : Address;
Value : Long_Integer) return Long_Integer;
pragma Import (Intrinsic, Sync_Fetch_And_Add, "__sync_fetch_and_add_8");
-- Why do we keep importing this over and over again???
begin
Old_Value := Sync_Fetch_And_Add (To.Value'Address, Amount);
Success_Flag := True;
end Add_Atomic;
----------------
-- And_Atomic --
----------------
procedure And_Atomic
(To : in out Aligned_Integer;
From : Integer)
is
procedure Sync_And_And_Fetch
(Ptr : Address;
Value : Integer);
pragma Import (Intrinsic, Sync_And_And_Fetch, "__sync_and_and_fetch_4");
begin
Sync_And_And_Fetch (To.Value'Address, From);
end And_Atomic;
procedure And_Atomic
(To : in out Aligned_Integer;
From : Integer;
Retry_Count : Natural;
Old_Value : out Integer;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
function Sync_Fetch_And_And
(Ptr : Address;
Value : Integer) return Integer;
pragma Import (Intrinsic, Sync_Fetch_And_And, "__sync_fetch_and_and_4");
begin
Old_Value := Sync_Fetch_And_And (To.Value'Address, From);
Success_Flag := True;
end And_Atomic;
procedure And_Atomic
(To : in out Aligned_Long_Integer;
From : Long_Integer)
is
procedure Sync_And_And_Fetch
(Ptr : Address;
Value : Long_Integer);
pragma Import (Intrinsic, Sync_And_And_Fetch, "__sync_and_and_fetch_8");
begin
Sync_And_And_Fetch (To.Value'Address, From);
end And_Atomic;
procedure And_Atomic
(To : in out Aligned_Long_Integer;
From : Long_Integer;
Retry_Count : Natural;
Old_Value : out Long_Integer;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
function Sync_Fetch_And_And
(Ptr : Address;
Value : Long_Integer) return Long_Integer;
pragma Import (Intrinsic, Sync_Fetch_And_And, "__sync_fetch_and_and_8");
begin
Old_Value := Sync_Fetch_And_And (To.Value'Address, From);
Success_Flag := True;
end And_Atomic;
---------------
-- Or_Atomic --
---------------
procedure Or_Atomic
(To : in out Aligned_Integer;
From : Integer)
is
procedure Sync_Or_And_Fetch
(Ptr : Address;
Value : Integer);
pragma Import (Intrinsic, Sync_Or_And_Fetch, "__sync_or_and_fetch_4");
begin
Sync_Or_And_Fetch (To.Value'Address, From);
end Or_Atomic;
procedure Or_Atomic
(To : in out Aligned_Integer;
From : Integer;
Retry_Count : Natural;
Old_Value : out Integer;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
function Sync_Fetch_And_Or
(Ptr : Address;
Value : Integer) return Integer;
pragma Import (Intrinsic, Sync_Fetch_And_Or, "__sync_fetch_and_or_4");
begin
Old_Value := Sync_Fetch_And_Or (To.Value'Address, From);
Success_Flag := True;
end Or_Atomic;
procedure Or_Atomic
(To : in out Aligned_Long_Integer;
From : Long_Integer)
is
procedure Sync_Or_And_Fetch
(Ptr : Address;
Value : Long_Integer);
pragma Import (Intrinsic, Sync_Or_And_Fetch, "__sync_or_and_fetch_8");
begin
Sync_Or_And_Fetch (To.Value'Address, From);
end Or_Atomic;
procedure Or_Atomic
(To : in out Aligned_Long_Integer;
From : Long_Integer;
Retry_Count : Natural;
Old_Value : out Long_Integer;
Success_Flag : out Boolean)
is
pragma Unreferenced (Retry_Count);
function Sync_Fetch_And_Or
(Ptr : Address;
Value : Long_Integer) return Long_Integer;
pragma Import (Intrinsic, Sync_Fetch_And_Or, "__sync_fetch_and_or_8");
begin
Old_Value := Sync_Fetch_And_Or (To.Value'Address, From);
Success_Flag := True;
end Or_Atomic;
------------
-- Insqhi --
------------
procedure Insqhi
(Item : Address;
Header : Address;
Status : out Insq_Status) is
procedure SYS_PAL_INSQHIL
(STATUS : out Integer; Header : Address; ITEM : Address);
pragma Import (External, SYS_PAL_INSQHIL);
pragma Import_Valued_Procedure (SYS_PAL_INSQHIL, "SYS$PAL_INSQHIL",
(Integer, Address, Address),
(Value, Value, Value));
Istat : Integer;
begin
SYS_PAL_INSQHIL (Istat, Header, Item);
if Istat = 0 then
Status := OK_Not_First;
elsif Istat = 1 then
Status := OK_First;
else
-- This status is never returned on IVMS
Status := Fail_No_Lock;
end if;
end Insqhi;
------------
-- Remqhi --
------------
procedure Remqhi
(Header : Address;
Item : out Address;
Status : out Remq_Status)
is
-- The removed item is returned in the second function return register,
-- R9 on IVMS. The VMS ABI calls for "small" records to be returned in
-- these registers, so inventing this odd looking record type makes that
-- all work.
type Remq is record
Status : Long_Integer;
Item : Address;
end record;
procedure SYS_PAL_REMQHIL
(Remret : out Remq; Header : Address);
pragma Import (External, SYS_PAL_REMQHIL);
pragma Import_Valued_Procedure
(SYS_PAL_REMQHIL, "SYS$PAL_REMQHIL",
(Remq, Address),
(Value, Value));
-- Following variables need documentation???
Rstat : Long_Integer;
Remret : Remq;
begin
SYS_PAL_REMQHIL (Remret, Header);
Rstat := Remret.Status;
Item := Remret.Item;
if Rstat = 0 then
Status := Fail_Was_Empty;
elsif Rstat = 1 then
Status := OK_Not_Empty;
elsif Rstat = 2 then
Status := OK_Empty;
else
-- This status is never returned on IVMS
Status := Fail_No_Lock;
end if;
end Remqhi;
------------
-- Insqti --
------------
procedure Insqti
(Item : Address;
Header : Address;
Status : out Insq_Status) is
procedure SYS_PAL_INSQTIL
(STATUS : out Integer; Header : Address; ITEM : Address);
pragma Import (External, SYS_PAL_INSQTIL);
pragma Import_Valued_Procedure (SYS_PAL_INSQTIL, "SYS$PAL_INSQTIL",
(Integer, Address, Address),
(Value, Value, Value));
Istat : Integer;
begin
SYS_PAL_INSQTIL (Istat, Header, Item);
if Istat = 0 then
Status := OK_Not_First;
elsif Istat = 1 then
Status := OK_First;
else
-- This status is never returned on IVMS
Status := Fail_No_Lock;
end if;
end Insqti;
------------
-- Remqti --
------------
procedure Remqti
(Header : Address;
Item : out Address;
Status : out Remq_Status)
is
-- The removed item is returned in the second function return register,
-- R9 on IVMS. The VMS ABI calls for "small" records to be returned in
-- these registers, so inventing (where is rest of this comment???)
type Remq is record
Status : Long_Integer;
Item : Address;
end record;
procedure SYS_PAL_REMQTIL
(Remret : out Remq; Header : Address);
pragma Import (External, SYS_PAL_REMQTIL);
pragma Import_Valued_Procedure (SYS_PAL_REMQTIL, "SYS$PAL_REMQTIL",
(Remq, Address),
(Value, Value));
Rstat : Long_Integer;
Remret : Remq;
begin
SYS_PAL_REMQTIL (Remret, Header);
Rstat := Remret.Status;
Item := Remret.Item;
-- Wouldn't case be nicer here, and in previous similar cases ???
if Rstat = 0 then
Status := Fail_Was_Empty;
elsif Rstat = 1 then
Status := OK_Not_Empty;
elsif Rstat = 2 then
Status := OK_Empty;
else
-- This status is never returned on IVMS
Status := Fail_No_Lock;
end if;
end Remqti;
end System.Aux_DEC;