Commit 3ec54569 by Pierre-Marie de Rodat

[multiple changes]

2017-11-09  Pascal Obry  <obry@adacore.com>

	* libgnarl/s-taprop__mingw.adb: On Windows, initialize the thead handle
	only for foreign threads.  We initialize the thread handle only if not
	yet initialized. This happens in Enter_Task for foreign threads only.
	But for native threads (Ada tasking) we do want to keep the real
	handle (from Create_Task) to be able to free the corresponding
	resources in Finalize_TCB (CloseHandle).

2017-11-09  Yannick Moy  <moy@adacore.com>

	* sem_attr.adb (Analyze_Attribute): Default initialize P_Type,
	P_Base_Type.
	(Error_Attr_P): Fix name in pragma No_Return.
	(Unexpected_Argument): Add pragma No_Return.
	(Placement_Error): Add pragma No_Return.

2017-11-09  Javier Miranda  <miranda@adacore.com>

	* exp_disp.adb (Elab_Flag_Needed): Elaboration flag not needed when the
	dispatch table is statically built.
	(Make_DT): Declare constant the Interface_Table object associated with
	an statically built dispatch table. For this purpose the Offset_To_Top
	value of each interface is computed using the dummy object.
	* exp_ch3.adb (Build_Init_Procedure): Do not generate code initializing
	the Offset_To_Top field of secondary dispatch tables when the dispatch
	table is statically built.
	(Initialize_Tag): Do not generate calls to Register_Interface_Offset
	when the dispatch table is statically built.
	* doc/gnat_rm/standard_and_implementation_defined_restrictions.rst:
	Document the new GNAT restriction Static_Dispatch_Tables.
	* gnat_rm.texi: Regenerate.

2017-11-09  Hristian Kirtchev  <kirtchev@adacore.com>

	* sem_aggr.adb (Resolve_Delta_Record_Aggregate): Reorder declarations
	to avoid a dormant bug.

2017-11-09  Jerome Lambourg  <lambourg@adacore.com>

	* init.c: Define missing __gnat_alternate_stack for QNX. Set it to 0,
	as such capability is not available on the OS.
	* link.c: Make sure linker options for QNX are correct.
	* libgnarl/s-osinte__qnx.ads: Add some missing bindings to pthread.
	* libgnarl/s-taprop__qnx.adb: New, derived from s-taprop__posix.adb. This brings
	in particular a workaround with locks priority ceiling where a higher
	priority task is allowed to lock a lower ceiling priority lock. This
	also fixes the scheduling of FIFO tasks when the priority of a task is
	lowered.
	* libgnat/system-qnx-aarch64.ads: Fix priority ranges.

2017-11-09  Yannick Moy  <moy@adacore.com>

	* erroutc.adb (Output_Error_Msgs): Justify CodePeer false positive
	message.
	* gnatbind.adb (Scan_Bind_Arg): Simplify test to remove always true
	condition.
	* namet.adb (Copy_One_Character): Add assumption for static analysis,
	as knowledge that Hex(2) is in the range 0..255 is too complex for
	CodePeer.
	(Finalize): Add assumption for static analysis, as the fact that there
	are symbols in the table depends on a global invariant at this point in
	the program.
	* set_targ.adb (Check_Spaces): Justify CodePeer false positive message.
	* stylesw.adb (Save_Style_Check_Options): Rewrite to avoid test always
	true.

From-SVN: r254573
parent 6214b83b
2017-11-09 Pascal Obry <obry@adacore.com>
* libgnarl/s-taprop__mingw.adb: On Windows, initialize the thead handle
only for foreign threads. We initialize the thread handle only if not
yet initialized. This happens in Enter_Task for foreign threads only.
But for native threads (Ada tasking) we do want to keep the real
handle (from Create_Task) to be able to free the corresponding
resources in Finalize_TCB (CloseHandle).
2017-11-09 Yannick Moy <moy@adacore.com>
* sem_attr.adb (Analyze_Attribute): Default initialize P_Type,
P_Base_Type.
(Error_Attr_P): Fix name in pragma No_Return.
(Unexpected_Argument): Add pragma No_Return.
(Placement_Error): Add pragma No_Return.
2017-11-09 Javier Miranda <miranda@adacore.com>
* exp_disp.adb (Elab_Flag_Needed): Elaboration flag not needed when the
dispatch table is statically built.
(Make_DT): Declare constant the Interface_Table object associated with
an statically built dispatch table. For this purpose the Offset_To_Top
value of each interface is computed using the dummy object.
* exp_ch3.adb (Build_Init_Procedure): Do not generate code initializing
the Offset_To_Top field of secondary dispatch tables when the dispatch
table is statically built.
(Initialize_Tag): Do not generate calls to Register_Interface_Offset
when the dispatch table is statically built.
* doc/gnat_rm/standard_and_implementation_defined_restrictions.rst:
Document the new GNAT restriction Static_Dispatch_Tables.
* gnat_rm.texi: Regenerate.
2017-11-09 Hristian Kirtchev <kirtchev@adacore.com>
* sem_aggr.adb (Resolve_Delta_Record_Aggregate): Reorder declarations
to avoid a dormant bug.
2017-11-09 Jerome Lambourg <lambourg@adacore.com>
* init.c: Define missing __gnat_alternate_stack for QNX. Set it to 0,
as such capability is not available on the OS.
* link.c: Make sure linker options for QNX are correct.
* libgnarl/s-osinte__qnx.ads: Add some missing bindings to pthread.
* libgnarl/s-taprop__qnx.adb: New, derived from s-taprop__posix.adb. This brings
in particular a workaround with locks priority ceiling where a higher
priority task is allowed to lock a lower ceiling priority lock. This
also fixes the scheduling of FIFO tasks when the priority of a task is
lowered.
* libgnat/system-qnx-aarch64.ads: Fix priority ranges.
2017-11-09 Yannick Moy <moy@adacore.com>
* erroutc.adb (Output_Error_Msgs): Justify CodePeer false positive
message.
* gnatbind.adb (Scan_Bind_Arg): Simplify test to remove always true
condition.
* namet.adb (Copy_One_Character): Add assumption for static analysis,
as knowledge that Hex(2) is in the range 0..255 is too complex for
CodePeer.
(Finalize): Add assumption for static analysis, as the fact that there
are symbols in the table depends on a global invariant at this point in
the program.
* set_targ.adb (Check_Spaces): Justify CodePeer false positive message.
* stylesw.adb (Save_Style_Check_Options): Rewrite to avoid test always
true.
2017-11-09 Javier Miranda <miranda@adacore.com> 2017-11-09 Javier Miranda <miranda@adacore.com>
* libgnat/s-rident.ads (Static_Dispatch_Tables): New restriction name. * libgnat/s-rident.ads (Static_Dispatch_Tables): New restriction name.
......
...@@ -988,6 +988,13 @@ appear, and that no wide or wide wide string or character literals ...@@ -988,6 +988,13 @@ appear, and that no wide or wide wide string or character literals
appear in the program (that is literals representing characters not in appear in the program (that is literals representing characters not in
type ``Character``). type ``Character``).
Static_Dispatch_Tables
----------------------
.. index:: Static_Dispatch_Tables
[GNAT] This restriction ensures at compile time that all the artifacts
associated with dispatch tables can be placed in read-only memory.
SPARK_05 SPARK_05
-------- --------
.. index:: SPARK_05 .. index:: SPARK_05
......
...@@ -512,6 +512,9 @@ package body Erroutc is ...@@ -512,6 +512,9 @@ package body Erroutc is
-- so now we output a tab to match up with the text. -- so now we output a tab to match up with the text.
if Src (P) = ASCII.HT then if Src (P) = ASCII.HT then
pragma Annotate
(CodePeer, False_Positive, "validity check",
"Src(P) is initialized at this point");
Write_Char (ASCII.HT); Write_Char (ASCII.HT);
P := P + 1; P := P + 1;
......
...@@ -2544,6 +2544,7 @@ package body Exp_Ch3 is ...@@ -2544,6 +2544,7 @@ package body Exp_Ch3 is
and then Has_Interfaces (Rec_Type) and then Has_Interfaces (Rec_Type)
then then
declare declare
Elab_List : List_Id := New_List;
Elab_Sec_DT_Stmts_List : constant List_Id := New_List; Elab_Sec_DT_Stmts_List : constant List_Id := New_List;
begin begin
...@@ -2555,24 +2556,30 @@ package body Exp_Ch3 is ...@@ -2555,24 +2556,30 @@ package body Exp_Ch3 is
Fixed_Comps => True, Fixed_Comps => True,
Variable_Comps => False); Variable_Comps => False);
Append_To (Elab_Sec_DT_Stmts_List, Elab_List := New_List (
Make_Assignment_Statement (Loc,
Name =>
New_Occurrence_Of
(Access_Disp_Table_Elab_Flag (Rec_Type), Loc),
Expression =>
New_Occurrence_Of (Standard_False, Loc)));
Prepend_List_To (Body_Stmts, New_List (
Make_If_Statement (Loc, Make_If_Statement (Loc,
Condition => New_Occurrence_Of (Set_Tag, Loc), Condition => New_Occurrence_Of (Set_Tag, Loc),
Then_Statements => Init_Tags_List), Then_Statements => Init_Tags_List));
if Elab_Flag_Needed (Rec_Type) then
Append_To (Elab_Sec_DT_Stmts_List,
Make_Assignment_Statement (Loc,
Name =>
New_Occurrence_Of
(Access_Disp_Table_Elab_Flag (Rec_Type),
Loc),
Expression =>
New_Occurrence_Of (Standard_False, Loc)));
Append_To (Elab_List,
Make_If_Statement (Loc,
Condition =>
New_Occurrence_Of
(Access_Disp_Table_Elab_Flag (Rec_Type), Loc),
Then_Statements => Elab_Sec_DT_Stmts_List));
end if;
Make_If_Statement (Loc, Prepend_List_To (Body_Stmts, Elab_List);
Condition =>
New_Occurrence_Of
(Access_Disp_Table_Elab_Flag (Rec_Type), Loc),
Then_Statements => Elab_Sec_DT_Stmts_List)));
end; end;
else else
Prepend_To (Body_Stmts, Prepend_To (Body_Stmts,
...@@ -8588,7 +8595,9 @@ package body Exp_Ch3 is ...@@ -8588,7 +8595,9 @@ package body Exp_Ch3 is
-- Offset_Value => n, -- Offset_Value => n,
-- Offset_Func => null); -- Offset_Func => null);
if RTE_Available (RE_Register_Interface_Offset) then if not Building_Static_Secondary_DT (Typ)
and then RTE_Available (RE_Register_Interface_Offset)
then
Append_To (Stmts_List, Append_To (Stmts_List,
Make_Procedure_Call_Statement (Loc, Make_Procedure_Call_Statement (Loc,
Name => Name =>
......
...@@ -677,7 +677,8 @@ package body Exp_Disp is ...@@ -677,7 +677,8 @@ package body Exp_Disp is
begin begin
return Ada_Version >= Ada_2005 return Ada_Version >= Ada_2005
and then not Is_Interface (Typ) and then not Is_Interface (Typ)
and then Has_Interfaces (Typ); and then Has_Interfaces (Typ)
and then not Building_Static_DT (Typ);
end Elab_Flag_Needed; end Elab_Flag_Needed;
----------------------------- -----------------------------
...@@ -5513,11 +5514,23 @@ package body Exp_Disp is ...@@ -5513,11 +5514,23 @@ package body Exp_Disp is
else else
declare declare
TSD_Ifaces_List : constant List_Id := New_List; TSD_Ifaces_List : constant List_Id := New_List;
Elmt : Elmt_Id; Elmt : Elmt_Id;
Sec_DT_Tag : Node_Id; Ifaces_List : Elist_Id;
Ifaces_Comp_List : Elist_Id;
Ifaces_Tag_List : Elist_Id;
Offset_To_Top : Node_Id;
Sec_DT_Tag : Node_Id;
begin begin
-- Collect interfaces information if we need to compute the
-- offset to the top using the dummy object.
if Present (Dummy_Object) then
Collect_Interfaces_Info (Typ,
Ifaces_List, Ifaces_Comp_List, Ifaces_Tag_List);
end if;
AI := First_Elmt (Typ_Ifaces); AI := First_Elmt (Typ_Ifaces);
while Present (AI) loop while Present (AI) loop
if Is_Ancestor (Node (AI), Typ, Use_Full_View => True) then if Is_Ancestor (Node (AI), Typ, Use_Full_View => True) then
...@@ -5552,6 +5565,46 @@ package body Exp_Disp is ...@@ -5552,6 +5565,46 @@ package body Exp_Disp is
Loc); Loc);
end if; end if;
-- For static dispatch tables compute Offset_To_Top using
-- the dummy object.
if Present (Dummy_Object) then
declare
Iface : constant Node_Id := Node (AI);
Iface_Comp : Node_Id := Empty;
Iface_Comp_Elmt : Elmt_Id;
Iface_Elmt : Elmt_Id;
begin
Iface_Elmt := First_Elmt (Ifaces_List);
Iface_Comp_Elmt := First_Elmt (Ifaces_Comp_List);
while Present (Iface_Elmt) loop
if Node (Iface_Elmt) = Iface then
Iface_Comp := Node (Iface_Comp_Elmt);
exit;
end if;
Next_Elmt (Iface_Elmt);
Next_Elmt (Iface_Comp_Elmt);
end loop;
pragma Assert (Present (Iface_Comp));
Offset_To_Top :=
Make_Op_Minus (Loc,
Make_Attribute_Reference (Loc,
Prefix =>
Make_Selected_Component (Loc,
Prefix =>
New_Occurrence_Of (Dummy_Object, Loc),
Selector_Name =>
New_Occurrence_Of (Iface_Comp, Loc)),
Attribute_Name => Name_Position));
end;
else
Offset_To_Top := Make_Integer_Literal (Loc, 0);
end if;
Append_To (TSD_Ifaces_List, Append_To (TSD_Ifaces_List,
Make_Aggregate (Loc, Make_Aggregate (Loc,
Expressions => New_List ( Expressions => New_List (
...@@ -5569,7 +5622,7 @@ package body Exp_Disp is ...@@ -5569,7 +5622,7 @@ package body Exp_Disp is
-- Offset_To_Top_Value -- Offset_To_Top_Value
Make_Integer_Literal (Loc, 0), Offset_To_Top,
-- Offset_To_Top_Func -- Offset_To_Top_Func
...@@ -5589,17 +5642,15 @@ package body Exp_Disp is ...@@ -5589,17 +5642,15 @@ package body Exp_Disp is
Set_Is_Statically_Allocated (ITable, Set_Is_Statically_Allocated (ITable,
Is_Library_Level_Tagged_Type (Typ)); Is_Library_Level_Tagged_Type (Typ));
-- The table of interfaces is not constant; its slots are -- The table of interfaces is constant if we are building a
-- filled at run time by the IP routine using attribute -- static dispatch table; otherwise is not constant because
-- 'Position to know the location of the tag components -- its slots are filled at run time by the IP routine.
-- (and this attribute cannot be safely used before the
-- object is initialized).
Append_To (Result, Append_To (Result,
Make_Object_Declaration (Loc, Make_Object_Declaration (Loc,
Defining_Identifier => ITable, Defining_Identifier => ITable,
Aliased_Present => True, Aliased_Present => True,
Constant_Present => False, Constant_Present => Present (Dummy_Object),
Object_Definition => Object_Definition =>
Make_Subtype_Indication (Loc, Make_Subtype_Indication (Loc,
Subtype_Mark => Subtype_Mark =>
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -330,9 +330,7 @@ procedure Gnatbind is ...@@ -330,9 +330,7 @@ procedure Gnatbind is
then then
Output_File_Name_Seen := True; Output_File_Name_Seen := True;
if Argv'Length = 0 if Argv'Length = 0 or else Argv (1) = '-' then
or else (Argv'Length >= 1 and then Argv (1) = '-')
then
Fail ("output File_Name missing after -o"); Fail ("output File_Name missing after -o");
else else
......
...@@ -2568,6 +2568,10 @@ __gnat_error_handler (int sig, siginfo_t *si, void *ucontext) ...@@ -2568,6 +2568,10 @@ __gnat_error_handler (int sig, siginfo_t *si, void *ucontext)
(__sigtramphandler_t *)&__gnat_map_signal); (__sigtramphandler_t *)&__gnat_map_signal);
} }
/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */
/* sigaltstack is currently not supported by QNX7 */
char __gnat_alternate_stack[0];
void void
__gnat_install_handler (void) __gnat_install_handler (void)
{ {
......
...@@ -141,7 +141,7 @@ package System.OS_Interface is ...@@ -141,7 +141,7 @@ package System.OS_Interface is
SIGKILL, SIGSTOP); SIGKILL, SIGSTOP);
-- These two signals actually can't be masked (POSIX won't allow it) -- These two signals actually can't be masked (POSIX won't allow it)
Reserved : constant Signal_Set := (SIGKILL, SIGSTOP, SIGSEGV); Reserved : constant Signal_Set := (SIGABRT, SIGKILL, SIGSTOP, SIGSEGV);
type sigset_t is private; type sigset_t is private;
...@@ -160,18 +160,18 @@ package System.OS_Interface is ...@@ -160,18 +160,18 @@ package System.OS_Interface is
function sigemptyset (set : access sigset_t) return int; function sigemptyset (set : access sigset_t) return int;
pragma Import (C, sigemptyset, "sigemptyset"); pragma Import (C, sigemptyset, "sigemptyset");
type union_type_3 is new String (1 .. 116); type pad7 is array (1 .. 7) of int;
type siginfo_t is record type siginfo_t is record
si_signo : int; si_signo : int;
si_code : int; si_code : int;
si_errno : int; si_errno : int;
X_data : union_type_3; X_data : pad7;
end record; end record;
pragma Convention (C, siginfo_t); pragma Convention (C, siginfo_t);
type struct_sigaction is record type struct_sigaction is record
sa_handler : System.Address; sa_handler : System.Address;
sa_flags : Interfaces.C.int; sa_flags : int;
sa_mask : sigset_t; sa_mask : sigset_t;
end record; end record;
pragma Convention (C, struct_sigaction); pragma Convention (C, struct_sigaction);
...@@ -228,19 +228,13 @@ package System.OS_Interface is ...@@ -228,19 +228,13 @@ package System.OS_Interface is
function To_Timespec (D : Duration) return timespec; function To_Timespec (D : Duration) return timespec;
pragma Inline (To_Timespec); pragma Inline (To_Timespec);
function sysconf (name : int) return long;
pragma Import (C, sysconf);
SC_CLK_TCK : constant := 2;
SC_NPROCESSORS_ONLN : constant := 84;
------------------------- -------------------------
-- Priority Scheduling -- -- Priority Scheduling --
------------------------- -------------------------
SCHED_OTHER : constant := 3;
SCHED_FIFO : constant := 1; SCHED_FIFO : constant := 1;
SCHED_RR : constant := 2; SCHED_RR : constant := 2;
SCHED_OTHER : constant := 3;
function To_Target_Priority function To_Target_Priority
(Prio : System.Any_Priority) return Interfaces.C.int (Prio : System.Any_Priority) return Interfaces.C.int
...@@ -270,12 +264,9 @@ package System.OS_Interface is ...@@ -270,12 +264,9 @@ package System.OS_Interface is
function Thread_Body_Access is new function Thread_Body_Access is new
Ada.Unchecked_Conversion (System.Address, Thread_Body); Ada.Unchecked_Conversion (System.Address, Thread_Body);
type pthread_t is new unsigned_long; type pthread_t is new int;
subtype Thread_Id is pthread_t; subtype Thread_Id is pthread_t;
function To_pthread_t is
new Ada.Unchecked_Conversion (unsigned_long, pthread_t);
type pthread_mutex_t is limited private; type pthread_mutex_t is limited private;
type pthread_cond_t is limited private; type pthread_cond_t is limited private;
type pthread_attr_t is limited private; type pthread_attr_t is limited private;
...@@ -285,8 +276,11 @@ package System.OS_Interface is ...@@ -285,8 +276,11 @@ package System.OS_Interface is
PTHREAD_CREATE_DETACHED : constant := 1; PTHREAD_CREATE_DETACHED : constant := 1;
PTHREAD_SCOPE_PROCESS : constant := 4; PTHREAD_SCOPE_PROCESS : constant := 4;
PTHREAD_SCOPE_SYSTEM : constant := 0; PTHREAD_SCOPE_SYSTEM : constant := 0;
PTHREAD_INHERIT_SCHED : constant := 0;
PTHREAD_EXPLICIT_SCHED : constant := 2;
-- Read/Write lock not supported on Android. -- Read/Write lock not supported on Android.
...@@ -306,15 +300,16 @@ package System.OS_Interface is ...@@ -306,15 +300,16 @@ package System.OS_Interface is
function sigaltstack function sigaltstack
(ss : not null access stack_t; (ss : not null access stack_t;
oss : access stack_t) return int; oss : access stack_t) return int
pragma Import (C, sigaltstack, "sigaltstack"); is (0);
-- Not supported on QNX
Alternate_Stack : aliased System.Address; Alternate_Stack : aliased System.Address;
-- Dummy definition: alternate stack not available due to missing -- Dummy definition: alternate stack not available due to missing
-- sigaltstack -- sigaltstack in QNX
Alternate_Stack_Size : constant := 0; Alternate_Stack_Size : constant := 0;
-- This must be in keeping with init.c:__gnat_alternate_stack -- This must be kept in sync with init.c:__gnat_alternate_stack
Stack_Base_Available : constant Boolean := False; Stack_Base_Available : constant Boolean := False;
-- Indicates whether the stack base is available on this target -- Indicates whether the stack base is available on this target
...@@ -327,10 +322,10 @@ package System.OS_Interface is ...@@ -327,10 +322,10 @@ package System.OS_Interface is
pragma Import (C, Get_Page_Size, "getpagesize"); pragma Import (C, Get_Page_Size, "getpagesize");
-- Returns the size of a page -- Returns the size of a page
PROT_NONE : constant := 0; PROT_NONE : constant := 16#00_00#;
PROT_READ : constant := 1; PROT_READ : constant := 16#01_00#;
PROT_WRITE : constant := 2; PROT_WRITE : constant := 16#02_00#;
PROT_EXEC : constant := 4; PROT_EXEC : constant := 16#04_00#;
PROT_ALL : constant := PROT_READ + PROT_WRITE + PROT_EXEC; PROT_ALL : constant := PROT_READ + PROT_WRITE + PROT_EXEC;
PROT_ON : constant := PROT_READ; PROT_ON : constant := PROT_READ;
PROT_OFF : constant := PROT_ALL; PROT_OFF : constant := PROT_ALL;
...@@ -358,10 +353,7 @@ package System.OS_Interface is ...@@ -358,10 +353,7 @@ package System.OS_Interface is
(how : int; (how : int;
set : access sigset_t; set : access sigset_t;
oset : access sigset_t) return int; oset : access sigset_t) return int;
pragma Import (C, pthread_sigmask, "sigprocmask"); pragma Import (C, pthread_sigmask, "pthread_sigmask");
-- pthread_sigmask maybe be broken due to mismatch between sigset_t and
-- kernel_sigset_t, substitute sigprocmask temporarily. ???
-- pragma Import (C, pthread_sigmask, "pthread_sigmask");
-------------------------- --------------------------
-- POSIX.1c Section 11 -- -- POSIX.1c Section 11 --
...@@ -389,6 +381,12 @@ package System.OS_Interface is ...@@ -389,6 +381,12 @@ package System.OS_Interface is
function pthread_mutex_unlock (mutex : access pthread_mutex_t) return int; function pthread_mutex_unlock (mutex : access pthread_mutex_t) return int;
pragma Import (C, pthread_mutex_unlock, "pthread_mutex_unlock"); pragma Import (C, pthread_mutex_unlock, "pthread_mutex_unlock");
function pthread_mutex_setprioceiling
(mutex : access pthread_mutex_t;
prioceiling : int;
old_ceiling : access int) return int;
pragma Import (C, pthread_mutex_setprioceiling);
function pthread_condattr_init function pthread_condattr_init
(attr : access pthread_condattr_t) return int; (attr : access pthread_condattr_t) return int;
pragma Import (C, pthread_condattr_init, "pthread_condattr_init"); pragma Import (C, pthread_condattr_init, "pthread_condattr_init");
...@@ -432,14 +430,36 @@ package System.OS_Interface is ...@@ -432,14 +430,36 @@ package System.OS_Interface is
function pthread_mutexattr_setprotocol function pthread_mutexattr_setprotocol
(attr : access pthread_mutexattr_t; (attr : access pthread_mutexattr_t;
protocol : int) return int is (0); protocol : int) return int;
pragma Import (C, pthread_mutexattr_setprotocol);
function pthread_mutexattr_getprotocol
(attr : access pthread_mutexattr_t;
protocol : access int) return int;
pragma Import (C, pthread_mutexattr_getprotocol);
function pthread_mutexattr_setprioceiling function pthread_mutexattr_setprioceiling
(attr : access pthread_mutexattr_t; (attr : access pthread_mutexattr_t;
prioceiling : int) return int is (0); prioceiling : int) return int;
pragma Import (C, pthread_mutexattr_setprioceiling);
function pthread_mutexattr_getprioceiling
(attr : access pthread_mutexattr_t;
prioceiling : access int) return int;
pragma Import (C, pthread_mutexattr_getprioceiling);
function pthread_mutex_getprioceiling
(attr : access pthread_mutex_t;
prioceiling : access int) return int;
pragma Import (C, pthread_mutex_getprioceiling);
type pad8 is array (1 .. 8) of int;
pragma Convention (C, pad8);
type struct_sched_param is record type struct_sched_param is record
sched_priority : int; -- scheduling priority sched_priority : int := 0; -- scheduling priority
sched_curpriority : int := 0;
reserved : pad8 := (others => 0);
end record; end record;
pragma Convention (C, struct_sched_param); pragma Convention (C, struct_sched_param);
...@@ -449,6 +469,27 @@ package System.OS_Interface is ...@@ -449,6 +469,27 @@ package System.OS_Interface is
param : access struct_sched_param) return int; param : access struct_sched_param) return int;
pragma Import (C, pthread_setschedparam, "pthread_setschedparam"); pragma Import (C, pthread_setschedparam, "pthread_setschedparam");
function pthread_getschedparam
(thread : pthread_t;
policy : access int;
param : access struct_sched_param) return int;
pragma Import (C, pthread_getschedparam, "pthread_getschedparam");
function pthread_setschedprio
(thread : pthread_t;
priority : int) return int;
pragma Import (C, pthread_setschedprio);
function pthread_attr_setschedparam
(attr : access pthread_attr_t;
param : access struct_sched_param) return int;
pragma Import (C, pthread_attr_setschedparam);
function pthread_attr_setinheritsched
(attr : access pthread_attr_t;
inheritsched : int) return int;
pragma Import (C, pthread_attr_setinheritsched);
function pthread_attr_setscope function pthread_attr_setscope
(attr : access pthread_attr_t; (attr : access pthread_attr_t;
scope : int) return int; scope : int) return int;
...@@ -478,13 +519,12 @@ package System.OS_Interface is ...@@ -478,13 +519,12 @@ package System.OS_Interface is
function pthread_attr_setdetachstate function pthread_attr_setdetachstate
(attr : access pthread_attr_t; (attr : access pthread_attr_t;
detachstate : int) return int; detachstate : int) return int;
pragma Import pragma Import (C, pthread_attr_setdetachstate);
(C, pthread_attr_setdetachstate, "pthread_attr_setdetachstate");
function pthread_attr_setstacksize function pthread_attr_setstacksize
(attr : access pthread_attr_t; (attr : access pthread_attr_t;
stacksize : size_t) return int; stacksize : size_t) return int;
pragma Import (C, pthread_attr_setstacksize, "pthread_attr_setstacksize"); pragma Import (C, pthread_attr_setstacksize);
function pthread_create function pthread_create
(thread : access pthread_t; (thread : access pthread_t;
...@@ -522,53 +562,10 @@ package System.OS_Interface is ...@@ -522,53 +562,10 @@ package System.OS_Interface is
destructor : destructor_pointer) return int; destructor : destructor_pointer) return int;
pragma Import (C, pthread_key_create, "pthread_key_create"); pragma Import (C, pthread_key_create, "pthread_key_create");
CPU_SETSIZE : constant := 1_024;
-- Size of the cpu_set_t mask on most linux systems (SUSE 11 uses 4_096).
-- This is kept for backward compatibility (System.Task_Info uses it), but
-- the run-time library does no longer rely on static masks, using
-- dynamically allocated masks instead.
type bit_field is array (1 .. CPU_SETSIZE) of Boolean;
for bit_field'Size use CPU_SETSIZE;
pragma Pack (bit_field);
pragma Convention (C, bit_field);
type cpu_set_t is record
bits : bit_field;
end record;
pragma Convention (C, cpu_set_t);
type cpu_set_t_ptr is access all cpu_set_t;
-- In the run-time library we use this pointer because the size of type
-- cpu_set_t varies depending on the glibc version. Hence, objects of type
-- cpu_set_t are allocated dynamically using the number of processors
-- available in the target machine (value obtained at execution time).
function CPU_ALLOC (count : size_t) return cpu_set_t_ptr;
pragma Import (C, CPU_ALLOC, "__gnat_cpu_alloc");
-- Wrapper around the CPU_ALLOC C macro
function CPU_ALLOC_SIZE (count : size_t) return size_t;
pragma Import (C, CPU_ALLOC_SIZE, "__gnat_cpu_alloc_size");
-- Wrapper around the CPU_ALLOC_SIZE C macro
procedure CPU_FREE (cpuset : cpu_set_t_ptr);
pragma Import (C, CPU_FREE, "__gnat_cpu_free");
-- Wrapper around the CPU_FREE C macro
procedure CPU_ZERO (count : size_t; cpuset : cpu_set_t_ptr);
pragma Import (C, CPU_ZERO, "__gnat_cpu_zero");
-- Wrapper around the CPU_ZERO_S C macro
procedure CPU_SET (cpu : int; count : size_t; cpuset : cpu_set_t_ptr);
pragma Import (C, CPU_SET, "__gnat_cpu_set");
-- Wrapper around the CPU_SET_S C macro
private private
type sigset_t is new Interfaces.C.unsigned_long; type sigset_t is array (1 .. 2) of Interfaces.Unsigned_32;
pragma Convention (C, sigset_t); pragma Convention (C, sigset_t);
for sigset_t'Alignment use Interfaces.C.unsigned_long'Alignment;
type pid_t is new int; type pid_t is new int;
...@@ -615,6 +612,6 @@ private ...@@ -615,6 +612,6 @@ private
pragma Convention (C, pthread_cond_t); pragma Convention (C, pthread_cond_t);
for pthread_cond_t'Alignment use unsigned_long_long_t'Alignment; for pthread_cond_t'Alignment use unsigned_long_long_t'Alignment;
type pthread_key_t is new unsigned; type pthread_key_t is new int;
end System.OS_Interface; end System.OS_Interface;
...@@ -796,7 +796,17 @@ package body System.Task_Primitives.Operations is ...@@ -796,7 +796,17 @@ package body System.Task_Primitives.Operations is
raise Invalid_CPU_Number; raise Invalid_CPU_Number;
end if; end if;
Self_ID.Common.LL.Thread := GetCurrentThread; -- Initialize the thread here only if not set. This is done for a
-- foreign task but is not needed when a real thread-id is already
-- set in Create_Task. Note that we do want to keep the real thread-id
-- as it is the only way to free the associated resource. Another way
-- to say this is that a pseudo thread-id from a foreign thread won't
-- allow for freeing resources.
if Self_ID.Common.LL.Thread = Null_Thread_Id then
Self_ID.Common.LL.Thread := GetCurrentThread;
end if;
Self_ID.Common.LL.Thread_Id := GetCurrentThreadId; Self_ID.Common.LL.Thread_Id := GetCurrentThreadId;
Get_Stack_Bounds Get_Stack_Bounds
......
------------------------------------------------------------------------------
-- --
-- GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS --
-- --
-- S Y S T E M . T A S K _ P R I M I T I V E S . O P E R A T I O N S --
-- --
-- B o d y --
-- --
-- Copyright (C) 1992-2017, Free Software Foundation, Inc. --
-- --
-- GNARL 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/>. --
-- --
-- GNARL was developed by the GNARL team at Florida State University. --
-- Extensive contributions were provided by Ada Core Technologies, Inc. --
-- --
------------------------------------------------------------------------------
-- This is a POSIX-like version of this package
-- This package contains all the GNULL primitives that interface directly with
-- the underlying OS.
-- Note: this file can only be used for POSIX compliant systems that implement
-- SCHED_FIFO and Ceiling Locking correctly.
-- For configurations where SCHED_FIFO and priority ceiling are not a
-- requirement, this file can also be used (e.g AiX threads)
pragma Polling (Off);
-- Turn off polling, we do not want ATC polling to take place during tasking
-- operations. It causes infinite loops and other problems.
with Ada.Unchecked_Conversion;
with Interfaces.C;
with System.Tasking.Debug;
with System.Interrupt_Management;
with System.OS_Constants;
with System.OS_Primitives;
with System.Task_Info;
with System.Soft_Links;
-- We use System.Soft_Links instead of System.Tasking.Initialization
-- because the later is a higher level package that we shouldn't depend on.
-- For example when using the restricted run time, it is replaced by
-- System.Tasking.Restricted.Stages.
package body System.Task_Primitives.Operations is
package OSC renames System.OS_Constants;
package SSL renames System.Soft_Links;
use System.Tasking.Debug;
use System.Tasking;
use Interfaces.C;
use System.OS_Interface;
use System.Parameters;
use System.OS_Primitives;
----------------
-- Local Data --
----------------
-- The followings are logically constants, but need to be initialized
-- at run time.
Single_RTS_Lock : aliased RTS_Lock;
-- This is a lock to allow only one thread of control in the RTS at
-- a time; it is used to execute in mutual exclusion from all other tasks.
-- Used mainly in Single_Lock mode, but also to protect All_Tasks_List
Environment_Task_Id : Task_Id;
-- A variable to hold Task_Id for the environment task
Locking_Policy : Character;
pragma Import (C, Locking_Policy, "__gl_locking_policy");
-- Value of the pragma Locking_Policy:
-- 'C' for Ceiling_Locking
-- 'I' for Inherit_Locking
-- ' ' for none.
Unblocked_Signal_Mask : aliased sigset_t;
-- The set of signals that should unblocked in all tasks
-- The followings are internal configuration constants needed
Next_Serial_Number : Task_Serial_Number := 100;
-- We start at 100, to reserve some special values for
-- using in error checking.
Time_Slice_Val : Integer;
pragma Import (C, Time_Slice_Val, "__gl_time_slice_val");
Dispatching_Policy : Character;
pragma Import (C, Dispatching_Policy, "__gl_task_dispatching_policy");
Foreign_Task_Elaborated : aliased Boolean := True;
-- Used to identified fake tasks (i.e., non-Ada Threads)
Use_Alternate_Stack : constant Boolean := Alternate_Stack_Size /= 0;
-- Whether to use an alternate signal stack for stack overflows
Abort_Handler_Installed : Boolean := False;
-- True if a handler for the abort signal is installed
type RTS_Lock_Ptr is not null access all RTS_Lock;
function Init_Mutex (L : RTS_Lock_Ptr; Prio : Any_Priority) return int;
-- Initialize the mutex L. If Ceiling_Support is True, then set the ceiling
-- to Prio. Returns 0 for success, or ENOMEM for out-of-memory.
function Get_Policy (Prio : System.Any_Priority) return Character;
pragma Import (C, Get_Policy, "__gnat_get_specific_dispatching");
-- Get priority specific dispatching policy
--------------------
-- Local Packages --
--------------------
package Specific is
procedure Initialize (Environment_Task : Task_Id);
pragma Inline (Initialize);
-- Initialize various data needed by this package
function Is_Valid_Task return Boolean;
pragma Inline (Is_Valid_Task);
-- Does executing thread have a TCB?
procedure Set (Self_Id : Task_Id);
pragma Inline (Set);
-- Set the self id for the current task
function Self return Task_Id;
pragma Inline (Self);
-- Return a pointer to the Ada Task Control Block of the calling task
end Specific;
package body Specific is separate;
-- The body of this package is target specific
package Monotonic is
function Monotonic_Clock return Duration;
pragma Inline (Monotonic_Clock);
-- Returns an absolute time, represented as an offset relative to some
-- unspecified starting point, typically system boot time. This clock
-- is not affected by discontinuous jumps in the system time.
function RT_Resolution return Duration;
pragma Inline (RT_Resolution);
-- Returns resolution of the underlying clock used to implement RT_Clock
procedure Timed_Sleep
(Self_ID : ST.Task_Id;
Time : Duration;
Mode : ST.Delay_Modes;
Reason : System.Tasking.Task_States;
Timedout : out Boolean;
Yielded : out Boolean);
-- Combination of Sleep (above) and Timed_Delay
procedure Timed_Delay
(Self_ID : ST.Task_Id;
Time : Duration;
Mode : ST.Delay_Modes);
-- Implement the semantics of the delay statement.
-- The caller should be abort-deferred and should not hold any locks.
end Monotonic;
package body Monotonic is separate;
----------------------------------
-- ATCB allocation/deallocation --
----------------------------------
package body ATCB_Allocation is separate;
-- The body of this package is shared across several targets
---------------------------------
-- Support for foreign threads --
---------------------------------
function Register_Foreign_Thread
(Thread : Thread_Id;
Sec_Stack_Size : Size_Type := Unspecified_Size) return Task_Id;
-- Allocate and initialize a new ATCB for the current Thread. The size of
-- the secondary stack can be optionally specified.
function Register_Foreign_Thread
(Thread : Thread_Id;
Sec_Stack_Size : Size_Type := Unspecified_Size)
return Task_Id is separate;
-----------------------
-- Local Subprograms --
-----------------------
procedure Abort_Handler (Sig : Signal);
-- Signal handler used to implement asynchronous abort.
-- See also comment before body, below.
function To_Address is
new Ada.Unchecked_Conversion (Task_Id, System.Address);
function GNAT_pthread_condattr_setup
(attr : access pthread_condattr_t) return int;
pragma Import (C,
GNAT_pthread_condattr_setup, "__gnat_pthread_condattr_setup");
-------------------
-- Abort_Handler --
-------------------
-- Target-dependent binding of inter-thread Abort signal to the raising of
-- the Abort_Signal exception.
-- The technical issues and alternatives here are essentially the
-- same as for raising exceptions in response to other signals
-- (e.g. Storage_Error). See code and comments in the package body
-- System.Interrupt_Management.
-- Some implementations may not allow an exception to be propagated out of
-- a handler, and others might leave the signal or interrupt that invoked
-- this handler masked after the exceptional return to the application
-- code.
-- GNAT exceptions are originally implemented using setjmp()/longjmp(). On
-- most UNIX systems, this will allow transfer out of a signal handler,
-- which is usually the only mechanism available for implementing
-- asynchronous handlers of this kind. However, some systems do not
-- restore the signal mask on longjmp(), leaving the abort signal masked.
procedure Abort_Handler (Sig : Signal) is
pragma Unreferenced (Sig);
T : constant Task_Id := Self;
Old_Set : aliased sigset_t;
Result : Interfaces.C.int;
pragma Warnings (Off, Result);
begin
-- It's not safe to raise an exception when using GCC ZCX mechanism.
-- Note that we still need to install a signal handler, since in some
-- cases (e.g. shutdown of the Server_Task in System.Interrupts) we
-- need to send the Abort signal to a task.
if ZCX_By_Default then
return;
end if;
if T.Deferral_Level = 0
and then T.Pending_ATC_Level < T.ATC_Nesting_Level and then
not T.Aborting
then
T.Aborting := True;
-- Make sure signals used for RTS internal purpose are unmasked
Result := pthread_sigmask (SIG_UNBLOCK,
Unblocked_Signal_Mask'Access, Old_Set'Access);
pragma Assert (Result = 0);
raise Standard'Abort_Signal;
end if;
end Abort_Handler;
-----------------
-- Stack_Guard --
-----------------
procedure Stack_Guard (T : ST.Task_Id; On : Boolean) is
Stack_Base : constant Address := Get_Stack_Base (T.Common.LL.Thread);
Page_Size : Address;
Res : Interfaces.C.int;
begin
if Stack_Base_Available then
-- Compute the guard page address
Page_Size := Address (Get_Page_Size);
Res :=
mprotect
(Stack_Base - (Stack_Base mod Page_Size) + Page_Size,
size_t (Page_Size),
prot => (if On then PROT_ON else PROT_OFF));
pragma Assert (Res = 0);
end if;
end Stack_Guard;
--------------------
-- Get_Thread_Id --
--------------------
function Get_Thread_Id (T : ST.Task_Id) return OSI.Thread_Id is
begin
return T.Common.LL.Thread;
end Get_Thread_Id;
----------
-- Self --
----------
function Self return Task_Id renames Specific.Self;
----------------
-- Init_Mutex --
----------------
function Init_Mutex (L : RTS_Lock_Ptr; Prio : Any_Priority) return int
is
Attributes : aliased pthread_mutexattr_t;
Result : int;
Result_2 : aliased int;
begin
Result := pthread_mutexattr_init (Attributes'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result = ENOMEM then
return Result;
end if;
if Locking_Policy = 'C' then
Result := pthread_mutexattr_setprotocol
(Attributes'Access, PTHREAD_PRIO_PROTECT);
pragma Assert (Result = 0);
Result := pthread_mutexattr_getprotocol
(Attributes'Access, Result_2'Access);
if Result_2 /= PTHREAD_PRIO_PROTECT then
raise Program_Error with "setprotocol failed";
end if;
Result := pthread_mutexattr_setprioceiling
(Attributes'Access, To_Target_Priority (Prio));
pragma Assert (Result = 0);
elsif Locking_Policy = 'I' then
Result := pthread_mutexattr_setprotocol
(Attributes'Access, PTHREAD_PRIO_INHERIT);
pragma Assert (Result = 0);
end if;
Result := pthread_mutex_init (L, Attributes'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
Result_2 := pthread_mutexattr_destroy (Attributes'Access);
pragma Assert (Result_2 = 0);
return Result;
end Init_Mutex;
---------------------
-- Initialize_Lock --
---------------------
-- Note: mutexes and cond_variables needed per-task basis are initialized
-- in Initialize_TCB and the Storage_Error is handled. Other mutexes (such
-- as RTS_Lock, Memory_Lock...) used in RTS is initialized before any
-- status change of RTS. Therefore raising Storage_Error in the following
-- routines should be able to be handled safely.
procedure Initialize_Lock
(Prio : System.Any_Priority;
L : not null access Lock)
is
begin
if Init_Mutex (L.WO'Access, Prio) = ENOMEM then
raise Storage_Error with "Failed to allocate a lock";
end if;
end Initialize_Lock;
procedure Initialize_Lock
(L : not null access RTS_Lock; Level : Lock_Level)
is
pragma Unreferenced (Level);
begin
if Init_Mutex (L.all'Access, Any_Priority'Last) = ENOMEM then
raise Storage_Error with "Failed to allocate a lock";
end if;
end Initialize_Lock;
-------------------
-- Finalize_Lock --
-------------------
procedure Finalize_Lock (L : not null access Lock) is
Result : Interfaces.C.int;
begin
Result := pthread_mutex_destroy (L.WO'Access);
pragma Assert (Result = 0);
end Finalize_Lock;
procedure Finalize_Lock (L : not null access RTS_Lock) is
Result : Interfaces.C.int;
begin
Result := pthread_mutex_destroy (L);
pragma Assert (Result = 0);
end Finalize_Lock;
----------------
-- Write_Lock --
----------------
procedure Write_Lock
(L : not null access Lock; Ceiling_Violation : out Boolean)
is
Self : constant pthread_t := pthread_self;
Result : int;
Policy : aliased int;
Ceiling : aliased int;
Sched : aliased struct_sched_param;
begin
Result := pthread_mutex_lock (L.WO'Access);
-- The cause of EINVAL is a priority ceiling violation
Ceiling_Violation := Result = EINVAL;
pragma Assert (Result = 0 or else Ceiling_Violation);
-- Workaround bug in QNX on ceiling locks: tasks with priority higher
-- than the ceiling priority don't receive EINVAL upon trying to lock.
if Result = 0 then
Result := pthread_getschedparam (Self, Policy'Access, Sched'Access);
pragma Assert (Result = 0);
Result := pthread_mutex_getprioceiling (L.WO'Access, Ceiling'Access);
pragma Assert (Result = 0);
-- Ceiling = 0 means no Ceiling Priority policy is set on this mutex
-- Else, Ceiling < current priority means Ceiling violation
-- (otherwise the current priority == ceiling)
if Ceiling > 0 and then Ceiling < Sched.sched_curpriority then
Ceiling_Violation := True;
Result := pthread_mutex_unlock (L.WO'Access);
pragma Assert (Result = 0);
end if;
end if;
end Write_Lock;
procedure Write_Lock
(L : not null access RTS_Lock;
Global_Lock : Boolean := False)
is
Result : Interfaces.C.int;
begin
if not Single_Lock or else Global_Lock then
Result := pthread_mutex_lock (L);
pragma Assert (Result = 0);
end if;
end Write_Lock;
procedure Write_Lock (T : Task_Id) is
Result : Interfaces.C.int;
begin
if not Single_Lock then
Result := pthread_mutex_lock (T.Common.LL.L'Access);
pragma Assert (Result = 0);
end if;
end Write_Lock;
---------------
-- Read_Lock --
---------------
procedure Read_Lock
(L : not null access Lock; Ceiling_Violation : out Boolean) is
begin
Write_Lock (L, Ceiling_Violation);
end Read_Lock;
------------
-- Unlock --
------------
procedure Unlock (L : not null access Lock) is
Result : Interfaces.C.int;
begin
Result := pthread_mutex_unlock (L.WO'Access);
pragma Assert (Result = 0);
end Unlock;
procedure Unlock
(L : not null access RTS_Lock; Global_Lock : Boolean := False)
is
Result : Interfaces.C.int;
begin
if not Single_Lock or else Global_Lock then
Result := pthread_mutex_unlock (L);
pragma Assert (Result = 0);
end if;
end Unlock;
procedure Unlock (T : Task_Id) is
Result : Interfaces.C.int;
begin
if not Single_Lock then
Result := pthread_mutex_unlock (T.Common.LL.L'Access);
pragma Assert (Result = 0);
end if;
end Unlock;
-----------------
-- Set_Ceiling --
-----------------
procedure Set_Ceiling
(L : not null access Lock;
Prio : System.Any_Priority)
is
Result : Interfaces.C.int;
begin
Result := pthread_mutex_setprioceiling
(L.WO'Access, To_Target_Priority (Prio), null);
pragma Assert (Result = 0);
end Set_Ceiling;
-----------
-- Sleep --
-----------
procedure Sleep
(Self_ID : Task_Id;
Reason : System.Tasking.Task_States)
is
pragma Unreferenced (Reason);
Result : Interfaces.C.int;
begin
Result :=
pthread_cond_wait
(cond => Self_ID.Common.LL.CV'Access,
mutex => (if Single_Lock
then Single_RTS_Lock'Access
else Self_ID.Common.LL.L'Access));
-- EINTR is not considered a failure
pragma Assert (Result = 0 or else Result = EINTR);
end Sleep;
-----------------
-- Timed_Sleep --
-----------------
-- This is for use within the run-time system, so abort is
-- assumed to be already deferred, and the caller should be
-- holding its own ATCB lock.
procedure Timed_Sleep
(Self_ID : Task_Id;
Time : Duration;
Mode : ST.Delay_Modes;
Reason : Task_States;
Timedout : out Boolean;
Yielded : out Boolean) renames Monotonic.Timed_Sleep;
-----------------
-- Timed_Delay --
-----------------
-- This is for use in implementing delay statements, so we assume the
-- caller is abort-deferred but is holding no locks.
procedure Timed_Delay
(Self_ID : Task_Id;
Time : Duration;
Mode : ST.Delay_Modes) renames Monotonic.Timed_Delay;
---------------------
-- Monotonic_Clock --
---------------------
function Monotonic_Clock return Duration renames Monotonic.Monotonic_Clock;
-------------------
-- RT_Resolution --
-------------------
function RT_Resolution return Duration renames Monotonic.RT_Resolution;
------------
-- Wakeup --
------------
procedure Wakeup (T : Task_Id; Reason : System.Tasking.Task_States) is
pragma Unreferenced (Reason);
Result : Interfaces.C.int;
begin
Result := pthread_cond_signal (T.Common.LL.CV'Access);
pragma Assert (Result = 0);
end Wakeup;
-----------
-- Yield --
-----------
procedure Yield (Do_Yield : Boolean := True) is
Result : Interfaces.C.int;
pragma Unreferenced (Result);
begin
if Do_Yield then
Result := sched_yield;
end if;
end Yield;
------------------
-- Set_Priority --
------------------
procedure Set_Priority
(T : Task_Id;
Prio : System.Any_Priority;
Loss_Of_Inheritance : Boolean := False)
is
pragma Unreferenced (Loss_Of_Inheritance);
Result : Interfaces.C.int;
Old : constant System.Any_Priority := T.Common.Current_Priority;
begin
T.Common.Current_Priority := Prio;
Result := pthread_setschedprio
(T.Common.LL.Thread, To_Target_Priority (Prio));
pragma Assert (Result = 0);
if T.Common.LL.Thread = Pthread_Self
and then Old > Prio
then
-- When lowering the priority via a pthread_setschedprio, QNX ensures
-- that the running thread remains in the head of the FIFO for tne
-- new priority. Annex D expects the thread to be requeued so let's
-- yield to the other threads of the same priority.
Result := sched_yield;
pragma Assert (Result = 0);
end if;
end Set_Priority;
------------------
-- Get_Priority --
------------------
function Get_Priority (T : Task_Id) return System.Any_Priority is
begin
return T.Common.Current_Priority;
end Get_Priority;
----------------
-- Enter_Task --
----------------
procedure Enter_Task (Self_ID : Task_Id) is
begin
Self_ID.Common.LL.Thread := pthread_self;
Self_ID.Common.LL.LWP := lwp_self;
Specific.Set (Self_ID);
if Use_Alternate_Stack then
declare
Stack : aliased stack_t;
Result : Interfaces.C.int;
begin
Stack.ss_sp := Self_ID.Common.Task_Alternate_Stack;
Stack.ss_size := Alternate_Stack_Size;
Stack.ss_flags := 0;
Result := sigaltstack (Stack'Access, null);
pragma Assert (Result = 0);
end;
end if;
end Enter_Task;
-------------------
-- Is_Valid_Task --
-------------------
function Is_Valid_Task return Boolean renames Specific.Is_Valid_Task;
-----------------------------
-- Register_Foreign_Thread --
-----------------------------
function Register_Foreign_Thread return Task_Id is
begin
if Is_Valid_Task then
return Self;
else
return Register_Foreign_Thread (pthread_self);
end if;
end Register_Foreign_Thread;
--------------------
-- Initialize_TCB --
--------------------
procedure Initialize_TCB (Self_ID : Task_Id; Succeeded : out Boolean)
is
Result : Interfaces.C.int;
Cond_Attr : aliased pthread_condattr_t;
begin
-- Give the task a unique serial number
Self_ID.Serial_Number := Next_Serial_Number;
Next_Serial_Number := Next_Serial_Number + 1;
pragma Assert (Next_Serial_Number /= 0);
if not Single_Lock then
Result := Init_Mutex (Self_ID.Common.LL.L'Access, Any_Priority'Last);
pragma Assert (Result = 0);
if Result /= 0 then
Succeeded := False;
return;
end if;
end if;
Result := pthread_condattr_init (Cond_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result = 0 then
Result := GNAT_pthread_condattr_setup (Cond_Attr'Access);
pragma Assert (Result = 0);
Result :=
pthread_cond_init
(Self_ID.Common.LL.CV'Access, Cond_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
end if;
if Result = 0 then
Succeeded := True;
else
if not Single_Lock then
Result := pthread_mutex_destroy (Self_ID.Common.LL.L'Access);
pragma Assert (Result = 0);
end if;
Succeeded := False;
end if;
Result := pthread_condattr_destroy (Cond_Attr'Access);
pragma Assert (Result = 0);
end Initialize_TCB;
-----------------
-- Create_Task --
-----------------
procedure Create_Task
(T : Task_Id;
Wrapper : System.Address;
Stack_Size : System.Parameters.Size_Type;
Priority : System.Any_Priority;
Succeeded : out Boolean)
is
Attributes : aliased pthread_attr_t;
Adjusted_Stack_Size : Interfaces.C.size_t;
Page_Size : constant Interfaces.C.size_t :=
Interfaces.C.size_t (Get_Page_Size);
Sched_Param : aliased struct_sched_param;
Result : Interfaces.C.int;
Priority_Specific_Policy : constant Character := Get_Policy (Priority);
-- Upper case first character of the policy name corresponding to the
-- task as set by a Priority_Specific_Dispatching pragma.
function Thread_Body_Access is new
Ada.Unchecked_Conversion (System.Address, Thread_Body);
begin
Adjusted_Stack_Size :=
Interfaces.C.size_t (Stack_Size + Alternate_Stack_Size);
if Stack_Base_Available then
-- If Stack Checking is supported then allocate 2 additional pages:
-- In the worst case, stack is allocated at something like
-- N * Get_Page_Size - epsilon, we need to add the size for 2 pages
-- to be sure the effective stack size is greater than what
-- has been asked.
Adjusted_Stack_Size := Adjusted_Stack_Size + 2 * Page_Size;
end if;
-- Round stack size as this is required by some OSes (Darwin)
Adjusted_Stack_Size := Adjusted_Stack_Size + Page_Size - 1;
Adjusted_Stack_Size :=
Adjusted_Stack_Size - Adjusted_Stack_Size mod Page_Size;
Result := pthread_attr_init (Attributes'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result /= 0 then
Succeeded := False;
return;
end if;
Result :=
pthread_attr_setdetachstate
(Attributes'Access, PTHREAD_CREATE_DETACHED);
pragma Assert (Result = 0);
Result :=
pthread_attr_setstacksize
(Attributes'Access, Adjusted_Stack_Size);
pragma Assert (Result = 0);
-- Set thread priority
T.Common.Current_Priority := Priority;
Sched_Param.sched_priority := To_Target_Priority (Priority);
Result := pthread_attr_setinheritsched
(Attributes'Access, PTHREAD_EXPLICIT_SCHED);
pragma Assert (Result = 0);
Result := pthread_attr_setschedparam
(Attributes'Access, Sched_Param'Access);
pragma Assert (Result = 0);
if Time_Slice_Supported
and then (Dispatching_Policy = 'R'
or else Priority_Specific_Policy = 'R'
or else Time_Slice_Val > 0)
then
Result := pthread_attr_setschedpolicy
(Attributes'Access, SCHED_RR);
elsif Dispatching_Policy = 'F'
or else Priority_Specific_Policy = 'F'
or else Time_Slice_Val = 0
then
Result := pthread_attr_setschedpolicy
(Attributes'Access, SCHED_FIFO);
else
Result := pthread_attr_setschedpolicy
(Attributes'Access, SCHED_OTHER);
end if;
pragma Assert (Result = 0);
-- Since the initial signal mask of a thread is inherited from the
-- creator, and the Environment task has all its signals masked, we
-- do not need to manipulate caller's signal mask at this point.
-- All tasks in RTS will have All_Tasks_Mask initially.
-- Note: the use of Unrestricted_Access in the following call is needed
-- because otherwise we have an error of getting a access-to-volatile
-- value which points to a non-volatile object. But in this case it is
-- safe to do this, since we know we have no problems with aliasing and
-- Unrestricted_Access bypasses this check.
Result := pthread_create
(T.Common.LL.Thread'Unrestricted_Access,
Attributes'Access,
Thread_Body_Access (Wrapper),
To_Address (T));
pragma Assert (Result = 0 or else Result = EAGAIN);
Succeeded := Result = 0;
Result := pthread_attr_destroy (Attributes'Access);
pragma Assert (Result = 0);
end Create_Task;
------------------
-- Finalize_TCB --
------------------
procedure Finalize_TCB (T : Task_Id) is
Result : Interfaces.C.int;
begin
if not Single_Lock then
Result := pthread_mutex_destroy (T.Common.LL.L'Access);
pragma Assert (Result = 0);
end if;
Result := pthread_cond_destroy (T.Common.LL.CV'Access);
pragma Assert (Result = 0);
if T.Known_Tasks_Index /= -1 then
Known_Tasks (T.Known_Tasks_Index) := null;
end if;
ATCB_Allocation.Free_ATCB (T);
end Finalize_TCB;
---------------
-- Exit_Task --
---------------
procedure Exit_Task is
begin
-- Mark this task as unknown, so that if Self is called, it won't
-- return a dangling pointer.
Specific.Set (null);
end Exit_Task;
----------------
-- Abort_Task --
----------------
procedure Abort_Task (T : Task_Id) is
Result : Interfaces.C.int;
begin
if Abort_Handler_Installed then
Result :=
pthread_kill
(T.Common.LL.Thread,
Signal (System.Interrupt_Management.Abort_Task_Interrupt));
pragma Assert (Result = 0);
end if;
end Abort_Task;
----------------
-- Initialize --
----------------
procedure Initialize (S : in out Suspension_Object) is
Mutex_Attr : aliased pthread_mutexattr_t;
Cond_Attr : aliased pthread_condattr_t;
Result : Interfaces.C.int;
begin
-- Initialize internal state (always to False (RM D.10 (6)))
S.State := False;
S.Waiting := False;
-- Initialize internal mutex
Result := pthread_mutexattr_init (Mutex_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result = ENOMEM then
raise Storage_Error;
end if;
Result := pthread_mutex_init (S.L'Access, Mutex_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result = ENOMEM then
Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
pragma Assert (Result = 0);
raise Storage_Error;
end if;
Result := pthread_mutexattr_destroy (Mutex_Attr'Access);
pragma Assert (Result = 0);
-- Initialize internal condition variable
Result := pthread_condattr_init (Cond_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result /= 0 then
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
-- Storage_Error is propagated as intended if the allocation of the
-- underlying OS entities fails.
raise Storage_Error;
else
Result := GNAT_pthread_condattr_setup (Cond_Attr'Access);
pragma Assert (Result = 0);
end if;
Result := pthread_cond_init (S.CV'Access, Cond_Attr'Access);
pragma Assert (Result = 0 or else Result = ENOMEM);
if Result /= 0 then
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
Result := pthread_condattr_destroy (Cond_Attr'Access);
pragma Assert (Result = 0);
-- Storage_Error is propagated as intended if the allocation of the
-- underlying OS entities fails.
raise Storage_Error;
end if;
Result := pthread_condattr_destroy (Cond_Attr'Access);
pragma Assert (Result = 0);
end Initialize;
--------------
-- Finalize --
--------------
procedure Finalize (S : in out Suspension_Object) is
Result : Interfaces.C.int;
begin
-- Destroy internal mutex
Result := pthread_mutex_destroy (S.L'Access);
pragma Assert (Result = 0);
-- Destroy internal condition variable
Result := pthread_cond_destroy (S.CV'Access);
pragma Assert (Result = 0);
end Finalize;
-------------------
-- Current_State --
-------------------
function Current_State (S : Suspension_Object) return Boolean is
begin
-- We do not want to use lock on this read operation. State is marked
-- as Atomic so that we ensure that the value retrieved is correct.
return S.State;
end Current_State;
---------------
-- Set_False --
---------------
procedure Set_False (S : in out Suspension_Object) is
Result : Interfaces.C.int;
begin
SSL.Abort_Defer.all;
Result := pthread_mutex_lock (S.L'Access);
pragma Assert (Result = 0);
S.State := False;
Result := pthread_mutex_unlock (S.L'Access);
pragma Assert (Result = 0);
SSL.Abort_Undefer.all;
end Set_False;
--------------
-- Set_True --
--------------
procedure Set_True (S : in out Suspension_Object) is
Result : Interfaces.C.int;
begin
SSL.Abort_Defer.all;
Result := pthread_mutex_lock (S.L'Access);
pragma Assert (Result = 0);
-- If there is already a task waiting on this suspension object then
-- we resume it, leaving the state of the suspension object to False,
-- as it is specified in (RM D.10(9)). Otherwise, it just leaves
-- the state to True.
if S.Waiting then
S.Waiting := False;
S.State := False;
Result := pthread_cond_signal (S.CV'Access);
pragma Assert (Result = 0);
else
S.State := True;
end if;
Result := pthread_mutex_unlock (S.L'Access);
pragma Assert (Result = 0);
SSL.Abort_Undefer.all;
end Set_True;
------------------------
-- Suspend_Until_True --
------------------------
procedure Suspend_Until_True (S : in out Suspension_Object) is
Result : Interfaces.C.int;
begin
SSL.Abort_Defer.all;
Result := pthread_mutex_lock (S.L'Access);
pragma Assert (Result = 0);
if S.Waiting then
-- Program_Error must be raised upon calling Suspend_Until_True
-- if another task is already waiting on that suspension object
-- (RM D.10(10)).
Result := pthread_mutex_unlock (S.L'Access);
pragma Assert (Result = 0);
SSL.Abort_Undefer.all;
raise Program_Error;
else
-- Suspend the task if the state is False. Otherwise, the task
-- continues its execution, and the state of the suspension object
-- is set to False (ARM D.10 par. 9).
if S.State then
S.State := False;
else
S.Waiting := True;
loop
-- Loop in case pthread_cond_wait returns earlier than expected
-- (e.g. in case of EINTR caused by a signal).
Result := pthread_cond_wait (S.CV'Access, S.L'Access);
pragma Assert (Result = 0 or else Result = EINTR);
exit when not S.Waiting;
end loop;
end if;
Result := pthread_mutex_unlock (S.L'Access);
pragma Assert (Result = 0);
SSL.Abort_Undefer.all;
end if;
end Suspend_Until_True;
----------------
-- Check_Exit --
----------------
-- Dummy version
function Check_Exit (Self_ID : ST.Task_Id) return Boolean is
pragma Unreferenced (Self_ID);
begin
return True;
end Check_Exit;
--------------------
-- Check_No_Locks --
--------------------
function Check_No_Locks (Self_ID : ST.Task_Id) return Boolean is
pragma Unreferenced (Self_ID);
begin
return True;
end Check_No_Locks;
----------------------
-- Environment_Task --
----------------------
function Environment_Task return Task_Id is
begin
return Environment_Task_Id;
end Environment_Task;
--------------
-- Lock_RTS --
--------------
procedure Lock_RTS is
begin
Write_Lock (Single_RTS_Lock'Access, Global_Lock => True);
end Lock_RTS;
----------------
-- Unlock_RTS --
----------------
procedure Unlock_RTS is
begin
Unlock (Single_RTS_Lock'Access, Global_Lock => True);
end Unlock_RTS;
------------------
-- Suspend_Task --
------------------
function Suspend_Task
(T : ST.Task_Id;
Thread_Self : Thread_Id) return Boolean
is
pragma Unreferenced (T, Thread_Self);
begin
return False;
end Suspend_Task;
-----------------
-- Resume_Task --
-----------------
function Resume_Task
(T : ST.Task_Id;
Thread_Self : Thread_Id) return Boolean
is
pragma Unreferenced (T, Thread_Self);
begin
return False;
end Resume_Task;
--------------------
-- Stop_All_Tasks --
--------------------
procedure Stop_All_Tasks is
begin
null;
end Stop_All_Tasks;
---------------
-- Stop_Task --
---------------
function Stop_Task (T : ST.Task_Id) return Boolean is
pragma Unreferenced (T);
begin
return False;
end Stop_Task;
-------------------
-- Continue_Task --
-------------------
function Continue_Task (T : ST.Task_Id) return Boolean is
pragma Unreferenced (T);
begin
return False;
end Continue_Task;
----------------
-- Initialize --
----------------
procedure Initialize (Environment_Task : Task_Id) is
act : aliased struct_sigaction;
old_act : aliased struct_sigaction;
Tmp_Set : aliased sigset_t;
Result : Interfaces.C.int;
function State
(Int : System.Interrupt_Management.Interrupt_ID) return Character;
pragma Import (C, State, "__gnat_get_interrupt_state");
-- Get interrupt state. Defined in a-init.c
-- The input argument is the interrupt number,
-- and the result is one of the following:
Default : constant Character := 's';
-- 'n' this interrupt not set by any Interrupt_State pragma
-- 'u' Interrupt_State pragma set state to User
-- 'r' Interrupt_State pragma set state to Runtime
-- 's' Interrupt_State pragma set state to System (use "default"
-- system handler)
begin
Environment_Task_Id := Environment_Task;
Interrupt_Management.Initialize;
-- Prepare the set of signals that should unblocked in all tasks
Result := sigemptyset (Unblocked_Signal_Mask'Access);
pragma Assert (Result = 0);
for J in Interrupt_Management.Interrupt_ID loop
if System.Interrupt_Management.Keep_Unmasked (J) then
Result := sigaddset (Unblocked_Signal_Mask'Access, Signal (J));
pragma Assert (Result = 0);
end if;
end loop;
-- Initialize the lock used to synchronize chain of all ATCBs
Initialize_Lock (Single_RTS_Lock'Access, RTS_Lock_Level);
Specific.Initialize (Environment_Task);
if Use_Alternate_Stack then
Environment_Task.Common.Task_Alternate_Stack :=
Alternate_Stack'Address;
end if;
-- Make environment task known here because it doesn't go through
-- Activate_Tasks, which does it for all other tasks.
Known_Tasks (Known_Tasks'First) := Environment_Task;
Environment_Task.Known_Tasks_Index := Known_Tasks'First;
Enter_Task (Environment_Task);
if State
(System.Interrupt_Management.Abort_Task_Interrupt) /= Default
then
act.sa_flags := 0;
act.sa_handler := Abort_Handler'Address;
Result := sigemptyset (Tmp_Set'Access);
pragma Assert (Result = 0);
act.sa_mask := Tmp_Set;
Result :=
sigaction
(Signal (System.Interrupt_Management.Abort_Task_Interrupt),
act'Unchecked_Access,
old_act'Unchecked_Access);
pragma Assert (Result = 0);
Abort_Handler_Installed := True;
end if;
end Initialize;
-----------------------
-- Set_Task_Affinity --
-----------------------
procedure Set_Task_Affinity (T : ST.Task_Id) is
pragma Unreferenced (T);
begin
-- Setting task affinity is not supported by the underlying system
null;
end Set_Task_Affinity;
end System.Task_Primitives.Operations;
...@@ -95,20 +95,22 @@ package System is ...@@ -95,20 +95,22 @@ package System is
-- Priority-related Declarations (RM D.1) -- Priority-related Declarations (RM D.1)
-- System priority is Ada priority + 1, so lies in the range 1 .. 63.
--
-- If the scheduling policy is SCHED_FIFO or SCHED_RR the runtime makes use -- If the scheduling policy is SCHED_FIFO or SCHED_RR the runtime makes use
-- of the entire range provided by the system. -- of the entire range provided by the system.
-- --
-- If the scheduling policy is SCHED_OTHER the only valid system priority -- If the scheduling policy is SCHED_OTHER the only valid system priority
-- is 1 and other values are simply ignored. -- is 1 and other values are simply ignored.
Max_Priority : constant Positive := 62; Max_Priority : constant Positive := 61;
Max_Interrupt_Priority : constant Positive := 63; Max_Interrupt_Priority : constant Positive := 62;
subtype Any_Priority is Integer range 0 .. 63; subtype Any_Priority is Integer range 0 .. 62;
subtype Priority is Any_Priority range 0 .. 62; subtype Priority is Any_Priority range 0 .. 61;
subtype Interrupt_Priority is Any_Priority range 63 .. 63; subtype Interrupt_Priority is Any_Priority range 62 .. 62;
Default_Priority : constant Priority := 31; Default_Priority : constant Priority := 30;
private private
......
...@@ -105,6 +105,7 @@ const char *__gnat_default_libgcc_subdir = "lib"; ...@@ -105,6 +105,7 @@ const char *__gnat_default_libgcc_subdir = "lib";
#elif defined (__FreeBSD__) || defined (__DragonFly__) \ #elif defined (__FreeBSD__) || defined (__DragonFly__) \
|| defined (__NetBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) || defined (__OpenBSD__)
|| defined (__QNX__)
const char *__gnat_object_file_option = "-Wl,@"; const char *__gnat_object_file_option = "-Wl,@";
const char *__gnat_run_path_option = "-Wl,-rpath,"; const char *__gnat_run_path_option = "-Wl,-rpath,";
char __gnat_shared_libgnat_default = STATIC; char __gnat_shared_libgnat_default = STATIC;
......
...@@ -258,7 +258,13 @@ package body Namet is ...@@ -258,7 +258,13 @@ package body Namet is
-- simply use their normal representation. -- simply use their normal representation.
else else
Insert_Character (Character'Val (Hex (2))); declare
W2 : constant Word := Hex (2);
begin
pragma Assume (W2 <= 255);
-- Add assumption to facilitate static analysis
Insert_Character (Character'Val (W2));
end;
end if; end if;
-- WW (wide wide character insertion) -- WW (wide wide character insertion)
...@@ -753,6 +759,9 @@ package body Namet is ...@@ -753,6 +759,9 @@ package body Namet is
Write_Eol; Write_Eol;
Write_Str ("Average number of probes for lookup = "); Write_Str ("Average number of probes for lookup = ");
pragma Assume (Nsyms /= 0);
-- Add assumption to facilitate static analysis. Here Nsyms cannot be
-- zero because many symbols are added to the table by default.
Probes := Probes / Nsyms; Probes := Probes / Nsyms;
Write_Int (Probes / 200); Write_Int (Probes / 200);
Write_Char ('.'); Write_Char ('.');
......
...@@ -2877,7 +2877,14 @@ package body Sem_Aggr is ...@@ -2877,7 +2877,14 @@ package body Sem_Aggr is
-- Resolve_Delta_Record_Aggregate -- -- Resolve_Delta_Record_Aggregate --
------------------------------------ ------------------------------------
procedure Resolve_Delta_Record_Aggregate (N : Node_Id; Typ : Entity_Id) is procedure Resolve_Delta_Record_Aggregate (N : Node_Id; Typ : Entity_Id) is
-- Variables used to verify that discriminant-dependent components
-- appear in the same variant.
Comp_Ref : Entity_Id;
Variant : Node_Id;
procedure Check_Variant (Id : Entity_Id); procedure Check_Variant (Id : Entity_Id);
-- If a given component of the delta aggregate appears in a variant -- If a given component of the delta aggregate appears in a variant
-- part, verify that it is within the same variant as that of previous -- part, verify that it is within the same variant as that of previous
...@@ -2900,17 +2907,13 @@ package body Sem_Aggr is ...@@ -2900,17 +2907,13 @@ package body Sem_Aggr is
procedure Check_Variant (Id : Entity_Id) is procedure Check_Variant (Id : Entity_Id) is
Comp : Entity_Id; Comp : Entity_Id;
Comp_Ref : Entity_Id;
Comp_Variant : Node_Id; Comp_Variant : Node_Id;
Variant : Node_Id;
begin begin
if not Has_Discriminants (Typ) then if not Has_Discriminants (Typ) then
return; return;
end if; end if;
Variant := Empty;
Comp := First_Entity (Typ); Comp := First_Entity (Typ);
while Present (Comp) loop while Present (Comp) loop
exit when Chars (Comp) = Chars (Id); exit when Chars (Comp) = Chars (Id);
...@@ -3027,6 +3030,8 @@ package body Sem_Aggr is ...@@ -3027,6 +3030,8 @@ package body Sem_Aggr is
-- Start of processing for Resolve_Delta_Record_Aggregate -- Start of processing for Resolve_Delta_Record_Aggregate
begin begin
Variant := Empty;
Assoc := First (Deltas); Assoc := First (Deltas);
while Present (Assoc) loop while Present (Assoc) loop
Choice := First (Choice_List (Assoc)); Choice := First (Choice_List (Assoc));
......
...@@ -231,10 +231,10 @@ package body Sem_Attr is ...@@ -231,10 +231,10 @@ package body Sem_Attr is
E1 : Node_Id; E1 : Node_Id;
E2 : Node_Id; E2 : Node_Id;
P_Type : Entity_Id; P_Type : Entity_Id := Empty;
-- Type of prefix after analysis -- Type of prefix after analysis
P_Base_Type : Entity_Id; P_Base_Type : Entity_Id := Empty;
-- Base type of prefix after analysis -- Base type of prefix after analysis
----------------------- -----------------------
...@@ -419,7 +419,7 @@ package body Sem_Attr is ...@@ -419,7 +419,7 @@ package body Sem_Attr is
-- required error messages. -- required error messages.
procedure Error_Attr_P (Msg : String); procedure Error_Attr_P (Msg : String);
pragma No_Return (Error_Attr); pragma No_Return (Error_Attr_P);
-- Like Error_Attr, but error is posted at the start of the prefix -- Like Error_Attr, but error is posted at the start of the prefix
procedure Legal_Formal_Attribute; procedure Legal_Formal_Attribute;
...@@ -446,7 +446,9 @@ package body Sem_Attr is ...@@ -446,7 +446,9 @@ package body Sem_Attr is
-- node in the aspect case). -- node in the aspect case).
procedure Unexpected_Argument (En : Node_Id); procedure Unexpected_Argument (En : Node_Id);
-- Signal unexpected attribute argument (En is the argument) pragma No_Return (Unexpected_Argument);
-- Signal unexpected attribute argument (En is the argument), and then
-- raises Bad_Attribute to avoid any further semantic processing.
procedure Validate_Non_Static_Attribute_Function_Call; procedure Validate_Non_Static_Attribute_Function_Call;
-- Called when processing an attribute that is a function call to a -- Called when processing an attribute that is a function call to a
...@@ -1108,8 +1110,10 @@ package body Sem_Attr is ...@@ -1108,8 +1110,10 @@ package body Sem_Attr is
-- node Nod is within enclosing node Encl_Nod. -- node Nod is within enclosing node Encl_Nod.
procedure Placement_Error; procedure Placement_Error;
pragma No_Return (Placement_Error);
-- Emit a general error when the attributes does not appear in a -- Emit a general error when the attributes does not appear in a
-- postcondition-like aspect or pragma. -- postcondition-like aspect or pragma, and then raises Bad_Attribute
-- to avoid any further semantic processing.
------------------------------ ------------------------------
-- Check_Placement_In_Check -- -- Check_Placement_In_Check --
......
...@@ -604,6 +604,10 @@ package body Set_Targ is ...@@ -604,6 +604,10 @@ package body Set_Targ is
procedure Check_Spaces is procedure Check_Spaces is
begin begin
if N > Buflen or else Buffer (N) /= ' ' then if N > Buflen or else Buffer (N) /= ' ' then
pragma Annotate
(CodePeer, False_Positive, "condition predetermined",
"N may be less than Buflen when calling Check_Spaces");
FailN ("missing space for"); FailN ("missing space for");
end if; end if;
......
...@@ -161,7 +161,8 @@ package body Stylesw is ...@@ -161,7 +161,8 @@ package body Stylesw is
if Style_Check_Comments then if Style_Check_Comments then
if Style_Check_Comments_Spacing = 2 then if Style_Check_Comments_Spacing = 2 then
Add ('c', Style_Check_Comments); Add ('c', Style_Check_Comments);
elsif Style_Check_Comments_Spacing = 1 then else
pragma Assert (Style_Check_Comments_Spacing = 1);
Add ('C', Style_Check_Comments); Add ('C', Style_Check_Comments);
end if; end if;
end if; end if;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment