← All compilation units

Flyology.Execution_Groups

Description

Selects and observes event-loop execution groups for lightweight tasks.

Example:

Flyology.Execution_Groups.Migrate (1);

Automatic_Placement_Policy

type Automatic_Placement_Policy is (Round_Robin);

Automatic assignment policy for tasks without a CPU aspect.

Enumeration literals
Round_Robin

Select successive groups in the configured pool

Configure_Loop_Thread

function Configure_Loop_Thread
  (Group : Group_Id; Kind : Loop_Thread_Placement; Value : Placement_Value := 0)
   return Placement_Configuration_Result

Configure a scheduler thread before Group starts. The same request is idempotent after startup; changing or clearing it then reports Group_Already_Started. Strict_CPU is a Linux OS CPU in the process's allowed set. Advisory_Tag must be positive. No_Placement requires zero.

Parameters
Group

Execution group whose scheduler thread is configured

Kind

Host placement mechanism

Value

Linux logical CPU, Darwin advisory tag, or zero

Return value

Explicit configuration result; this starts no group

Raised exceptions
Group_Error

The runtime returns an unknown result

Configured_Placement

function Configured_Placement return Automatic_Placement_Policy

Return the automatic policy without starting any group.

Return value

Configured placement policy

Raised exceptions
Group_Error

The runtime reports an unknown policy

Configured_Pool_Size

function Configured_Pool_Size return Loop_Pool_Size

Return the automatic pool size without starting any group. The value of FLYOLOGY_LOOP_POOL_SIZE is captured once at process startup, defaults to one when absent, and establishes the initial size before task activation. Runtime growth or reduction may change it later. A lightweight task without a specific CPU is assigned among groups 0 .. Result - 1.

Return value

Configured shared-group pool size

Raised exceptions
Group_Error

The runtime reports an invalid size

Create_Dedicated

function Create_Dedicated return Dedicated_Group_Id

Reserve an empty reusable dedicated group for the calling lightweight task. Migrating out consumes the reservation; call Create_Dedicated again before re-entering a dedicated group. The same id is normally reused.

Return value

Reserved group in 128 .. 255

Raised exceptions
Group_Error

The caller is native or no group can be reserved

Current

function Current return Group_Id

Return the calling lightweight task's current execution group.

Return value

Current group identifier

Raised exceptions
Group_Error

The caller is native or runtime result is invalid

Current_Processor

function Current_Processor return Integer

Return the calling thread's current logical processor where the host provides a stable public query (Linux), otherwise No_Processor.

Return value

Current zero-based logical CPU or No_Processor

Dedicated_Group_Id

subtype Dedicated_Group_Id is Group_Id range 128 .. Group_Id'Last;

Exclusively reserved groups returned by Create_Dedicated.

Default_Group

Default_Group : constant Shared_Group_Id := 0;

First shared group. Ada reserves CPU 0 as Not_A_Specific_CPU, so no CPU aspect names this group; reach it through automatic placement, Migrate, or Topology.Cross_To_Shard.

For_CPU

function For_CPU (CPU : Group_Selecting_CPU) return Shared_Group_Id

Convert an Ada CPU value in 1 .. 127 to its shared Flyology group. Constraint_Error reports a value outside that range, including the reserved Not_A_Specific_CPU, which names no group.

Parameters
CPU

Ada CPU aspect value that names a shared group

Return value

Shared group with the same numeric value

Group_Error

Group_Error     : exception;

Raised when a group query, reservation, or pin operation cannot complete.

Group_Id

type Group_Id is range 0 .. 255;

Identifier of one permanent event-loop execution group.

Group_Selecting_CPU

subtype Group_Selecting_CPU is
  System.Multiprocessors.CPU_Range range 1 .. System.Multiprocessors.CPU_Range (Shared_Group_Id'Last);

Ada CPU aspect values that name a shared execution group. The reserved value 0 is excluded because Ada defines it as Not_A_Specific_CPU, which requests automatic placement rather than Default_Group.

Grow_Configured_Pool

procedure Grow_Configured_Pool (Minimum_Size : Loop_Pool_Size)

Ensure the automatic pool contains at least Minimum_Size shared groups. Concurrent calls converge on the largest requested value. A request at or below the current size is an idempotent no-op. Growth is rejected while a reduction is still draining. Existing tasks remain on their current groups, while future automatic placements use the enlarged pool. Newly included groups remain lazy. Growing changes the modulus used by Topology.Shard_For_Hash.

Parameters
Minimum_Size

Minimum automatic pool size after the call

Raised exceptions
Group_Error

The runtime lifecycle does not permit growth

In_Configured_Pool

function In_Configured_Pool (Group : Group_Id) return Boolean

Test membership in the automatic pool without starting a group.

Parameters
Group

Group to test

Return value

True when Group is below Configured_Pool_Size

Raised exceptions
Group_Error

The runtime reports an invalid pool size

Is_Dedicated

function Is_Dedicated (Group : Group_Id) return Boolean

Test the numeric group class; this starts no group.

Parameters
Group

Group identifier to classify

Return value

True for groups 128 .. 255

Is_Thread_Pinned

function Is_Thread_Pinned return Boolean

Report whether the caller is pinned. Native tasks always report True.

Return value

True for a native task or a lightweight task with a live pin

Loop_Pool_Size

subtype Loop_Pool_Size is Positive range 1 .. 128;

Number of shared groups participating in automatic placement.

Loop_Thread_Placement

type Loop_Thread_Placement is (No_Placement, Strict_CPU, Advisory_Tag);

Optional placement of an execution group's scheduler thread. This is independent from an Ada CPU aspect, which selects an execution group.

Enumeration literals
No_Placement

Do not request host placement

Strict_CPU

Bind to one Linux logical CPU; unsupported on Darwin

Advisory_Tag

Apply a Darwin cache-locality tag, not a CPU number

Loop_Thread_Status

function Loop_Thread_Status (Group : Group_Id) return Placement_Status

Observe Group's placement request without starting it.

Parameters
Group

Execution group to inspect

Return value

Current placement status

Raised exceptions
Group_Error

The runtime query or returned encoding is invalid

Migrate

procedure Migrate (Group : Group_Id)

Migrate the calling lightweight task at this cooperative safe point and return on Group's scheduler thread. A live Thread_Pin prevents movement to another group. Native tasks cannot migrate because GNARL owns their stacks and threads. Leaving a dedicated group consumes its reservation. Migrate is a potentially blocking operation and must not be called inside a protected action: the protected object's lock belongs to the source event-loop thread and cannot follow the task. The call is not syntactically visible to GNAT's check on protected bodies, so a lightweight caller inside a protected action raises Program_Error before any movement, whatever Group names, and the normal unwinding releases the lock on the thread that holds it. A native caller inside a protected action keeps raising Migration_Error.

Parameters
Group

Destination execution group

Raised exceptions
Migration_Error

Caller is native, pinned, or cannot enter Group

Program_Error

Lightweight caller is inside a protected action

Migration_Error

Migration_Error : exception;

Raised when the calling task cannot migrate to the requested group.

No_Processor

No_Processor : constant Integer := -1;

Current_Processor result when no supported stable query exists.

Pin_To_Current_Thread

function Pin_To_Current_Thread return Thread_Pin

Acquire one pin level for a lightweight caller, or a no-op for a native caller.

Return value

Guard that releases the lightweight pin or finalizes the native no-op

Raised exceptions
Group_Error

The runtime cannot pin the caller

Placement_Configuration_Result

type Placement_Configuration_Result is
  (Configured, Unchanged, Unsupported, Invalid_Value, Group_Already_Started, Runtime_Unavailable);

Result of a loop-thread configuration request.

Enumeration literals
Configured

New configuration was recorded before startup

Unchanged

The identical configuration was already recorded

Unsupported

The host does not implement this placement kind

Invalid_Value

Value is invalid for Kind or unavailable to process

Group_Already_Started

Group entered lazy startup before this change

Runtime_Unavailable

Runtime lifecycle does not permit configuration

Placement_State

type Placement_State is (Not_Requested, Pending_Startup, Applied, Failed, Unavailable);

Observed application state of a placement request.

Enumeration literals
Not_Requested

No placement was configured

Pending_Startup

The request is stored for lazy group startup

Applied

The group thread applied the request

Failed

The host call failed; inspect Error_Code

Unavailable

The requested mechanism is unavailable

Placement_Status

type Placement_Status is record
   Kind       : Loop_Thread_Placement := No_Placement;
   Value      : Placement_Value := 0;
   State      : Placement_State := Not_Requested;
   Error_Code : Integer := 0;
end record;

Current loop-thread placement status.

Record fields
Kind

Requested host placement mechanism

Value

Requested CPU or advisory tag

State

Request lifecycle state

Error_Code

Host error for Failed, otherwise zero

Placement_Supported

function Placement_Supported (Kind : Loop_Thread_Placement) return Boolean

Test whether the host supports Kind without starting a group.

Parameters
Kind

Placement mechanism to test

Return value

True when the current host supports Kind

Placement_Value

subtype Placement_Value is Natural range 0 .. 2_147_483_647;

Host placement value: zero-based Linux CPU or positive Darwin tag.

Placement_Value_Available

function Placement_Value_Available (Kind : Loop_Thread_Placement; Value : Placement_Value) return Boolean

Test a placement value without starting a group. On Linux this may lazily snapshot the process's inherited affinity allowance.

Parameters
Kind

Placement mechanism

Value

Candidate CPU or advisory tag

Return value

True when the host can accept the value

Pool_Reduction

function Pool_Reduction return Pool_Reduction_Status

Return a momentary reduction-progress snapshot without waiting. Calling this function also recognizes completion after the final task or pre-cutover placement claim drains.

Return value

Current reduction lifecycle, target, and blocker counts

Raised exceptions
Group_Error

The runtime cannot provide a valid snapshot

Pool_Reduction_Phase

type Pool_Reduction_Phase is (No_Reduction, Draining, Drained);

Lifecycle of the most recent automatic-pool reduction.

Enumeration literals
No_Reduction

No reduction is active or retained for observation

Draining

New placement uses Target_Size while eligible tasks move

Drained

No automatically managed task remains above Target_Size

Pool_Reduction_Request_Result

type Pool_Reduction_Request_Result is (Reduction_Started, Already_At_Or_Below, Reduction_In_Progress);

Result of a request to lower the automatic-placement ceiling.

Enumeration literals
Reduction_Started

New automatic placements now use Target_Size and eligible existing tasks will drain cooperatively

Already_At_Or_Below

The current ceiling already satisfies the request

Reduction_In_Progress

A previous reduction must finish first

Pool_Reduction_Status

type Pool_Reduction_Status is record
   Phase                   : Pool_Reduction_Phase := No_Reduction;
   Target_Size             : Loop_Pool_Size := Loop_Pool_Size'First;
   Automatic_Tasks         : Natural := 0;
   Pinned_Automatic_Tasks  : Natural := 0;
   Waiting_Automatic_Tasks : Natural := 0;
   Explicit_Tasks          : Natural := 0;
   Placement_Claims        : Natural := 0;
end record;

Progress and blockers for an automatic-pool reduction. Explicit_Tasks reports tasks outside Target_Size that are not managed by the automatic pool; they do not prevent Drained. Counts are a momentary snapshot.

Record fields
Phase

Current reduction lifecycle

Target_Size

Current automatic-placement ceiling

Automatic_Tasks

Automatically managed tasks still above target

Pinned_Automatic_Tasks

Such tasks currently pinned to a thread

Waiting_Automatic_Tasks

Such tasks suspended until another event

Explicit_Tasks

Explicitly placed tasks above the target

Placement_Claims

Creations that selected an above-target group before the reduction cutover and have not registered yet

Request_Pool_Reduction

function Request_Pool_Reduction (Maximum_Size : Loop_Pool_Size) return Pool_Reduction_Request_Result

Lower the ceiling used by future automatic placements immediately. Automatically managed tasks in removed groups migrate to Default_Group when they next become ready at an unpinned cooperative safe point. Waiting, pinned, or CPU-bound tasks may delay completion indefinitely. Tasks created with a CPU aspect or moved explicitly with Migrate remain where the caller put them and are reported as Explicit_Tasks. If migration is required, this call may synchronously start Default_Group as its drainage destination and wait for that startup. An already-drained request starts no group. The call does not wait for drainage and does not reclaim threads. Use Pool_Reduction to observe drainage with an application deadline.

Parameters
Maximum_Size

New automatic-placement ceiling

Return value

Whether reduction started, was already satisfied, or is busy

Raised exceptions
Group_Error

The runtime lifecycle rejects the request

Shared_Group_Id

subtype Shared_Group_Id is Group_Id range 0 .. 127;

Shared groups selected by CPU aspects and automatic placement.

Thread_Pin

type Thread_Pin is limited private;

Task-owned scope guard that keeps a lightweight task on its current scheduler thread. Pins nest and each object releases one level. Declare, use, and finalize a lightweight-acquired guard in its acquiring task; do not transfer it. Finalization of that guard by another task raises Program_Error in that task and does not release the acquiring task's pin level. Native tasks accept pins as no-ops because their thread is permanent; native-acquired guards also finalize as no-ops, even in another task. @field Active Whether this guard still needs finalization @field Owner Runtime identity of the acquiring lightweight task, or null for a native-acquired no-op