1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 | ------------------------------------------------------------------------------
-- --
-- GPR PROJECT MANAGER --
-- --
-- Copyright (C) 2023, Free Software Foundation, Inc. --
-- --
-- This library is free software; you can redistribute it and/or modify it --
-- under terms of the GNU General Public License as published by the Free --
-- Software Foundation; either version 3, or (at your option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
-- TABILITY 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/>. --
-- --
------------------------------------------------------------------------------
-- This package manages the communication with GNU make jobserver
with Ada.Strings.Hash;
with GPR.Compilation; use GPR.Compilation;
with Ada.Containers.Indefinite_Hashed_Maps;
package GPR.Jobserver is
JS_Initialize_Error : exception;
-- Error exception raised when jobserver's initialization fails
JS_Makeflags_Parsing_Detects_Dry_Run : exception;
-- Exception raised when make was invoked with "-n"
JS_Access_Error : exception;
-- Error exception raised when jobserver's read or write fails
JS_Process_Error : exception;
-- Error exception raised when jobserver's process fails
function Awaiting_Job_Slot return Boolean;
-- Returns whether or not we are waiting for a job slot :
-- Cached_Token_Status = Pending or Unavailable.
function Unavailable_Job_Slot return Boolean;
-- Returns whether or not there is no job slot available
-- When Current_Connection_Method = Named_Pipe :
-- Cached_Token_Status = Pending
-- This is because the token retrivial is blocking
-- When Current_Connection_Method = Simple_Pipe | Windows_Semaphore :
-- Cached_Token_Status = Unavailable
procedure Initialize;
-- Initialize Jobserver communication
procedure Preorder_Token;
-- Preorder a token from GNU make Jobserver
procedure Register_Token_Id (Id : GPR.Compilation.Id);
-- Affiliates the last preordered token to the process Id
procedure Unregister_All_Token_Id;
-- Free all registered tokens
procedure Unregister_Token_Id (Id : GPR.Compilation.Id);
-- Release the token affiliated to the process Id
function Registered_Processes return Boolean;
-- Returns True if there are ongoing processes affiliated with a token,
-- returns False if there are not.
function Pending_Process return Boolean;
-- Returns True if a token have been ordered,
-- returns False if not.
procedure Monitor;
-- Monitor the process status and state.
procedure Finalize;
-- Finalize Jobserver processes
private
package Token_Process_Id is new Ada.Containers.Indefinite_Hashed_Maps
(String, Character, Ada.Strings.Hash, "=");
Source_Id_Token_Map : Token_Process_Id.Map;
type Connection_Type is
(Undefined, Named_Pipe, Simple_Pipe, Windows_Semaphore);
Current_Connection_Method : Connection_Type := Undefined;
type Implemented_Connection_Type is array (Connection_Type) of Boolean;
type Task_Token_Status is (Unknown, Available, Unavailable);
type Task_State is (Idle, Busy, Error);
type Token_Process_State is (Idle, Pending);
Last_Task_State : Task_State := Idle;
Busy_State_Count : Integer := 0;
Max_Busy_State_Count : constant := 10;
protected Task_State_Object is
procedure Set (State : Task_State);
function Get return Task_State;
private
S : Task_State := Idle;
end Task_State_Object;
protected Task_Token_Status_Object is
procedure Set (Status : Task_Token_Status);
function Get return Task_Token_Status;
private
S : Task_Token_Status := Unknown;
end Task_Token_Status_Object;
protected Token_Process_State_Object is
procedure Set (State : Token_Process_State);
function Get return Token_Process_State;
private
S : Token_Process_State := Idle;
end Token_Process_State_Object;
protected Sync_Proc_Task_Object is
procedure Set (Value : Boolean);
function Synced return Boolean;
private
V : Boolean := True;
end Sync_Proc_Task_Object;
protected Preorder_Auth_Object is
procedure Set (Auth : Boolean);
entry Get (Auth : out Boolean);
private
Value : Boolean := False;
Is_Set : Boolean := False;
end Preorder_Auth_Object;
Char : aliased Character := ASCII.NUL;
task type Jobserver_Task is
end Jobserver_Task;
JS_Task : access Jobserver_Task;
function Awaiting_Job_Slot return Boolean is
(Task_State_Object.Get = Busy
or else not Sync_Proc_Task_Object.Synced
or else not (Task_Token_Status_Object.Get = Available));
function Unavailable_Job_Slot return Boolean is
((if Current_Connection_Method = Named_Pipe
then (Task_State_Object.Get = Busy
and then Busy_State_Count >= Max_Busy_State_Count)
else (Task_Token_Status_Object.Get = Unavailable)));
function Pending_Process return Boolean is
(Token_Process_State_Object.Get = Pending);
end GPR.Jobserver;
|