• No se han encontrado resultados

4 Add selected agent to charge list

5 Manage Timers

6 Update kernel state

7 Context switch to selected agent

Agent context

1 Start of loop 0 Kernel initialisation

Find next agent to run

Find next timer 3 Select next agent to run

2 ♦ Run reason:

♦ Pending scheduler operation?

Select scheduling op ◉ Agent request ◉ External interrupt ◉ Oak timer ◉ No ◉ Yes Figure 26

The Oak Run-Loop control flow. Oak.Core

context switch was voluntary (as part of an agent service request) or because an interrupt was raised (from an external or timer interrupt). Furthermore, if an agent had voluntarily yielded the processor, the kernel agent records the location of the agent’s Oak Message and copies the message into its stack.13 During the context switch to the kernel agent, the context switching routines provide a reason for the kernel agent running:

▶ An agent voluntarily yielded to Oak ▶ An external interrupt requires handling ▶ An Oak Timer requires handling

The latter two situations causes a running agent to involuntarily yield the pro- cessor to the kernel, which Oak notes in the agent’s Agent_Interrupted property to enable correct restoration of the interrupted agent’s context.

Once noted, this stage responds to the reason for run.

An agent voluntarily yields to the kernel agent to request a state change or an Oak provided services. As part of the yield, the agent provides an Oak Message containing the desired request (Listing 50 on page 110).

Here the kernel agent acts on the agent’s request, with the agent ending in the requested state or passing through the requested state to another. For example, an agent requesting the Sleeping state will end up in that state if the supplied wake time lies in the future. Otherwise, the agent will remain in a Running or

Runnable state, since the wake time has passed.

Handling an agent’s request may result in the agent’s scheduler requiring no- tification of changes to the agent’s scheduling properties, or may see an agent added or removed from a scheduler agent. In these cases, the kernel agent pushes the required scheduling operations onto its Scheduler_Ops stack. Later in the run-loop, the kernel agent will dispatch these operations.

Here the kernel agent finds the interrupt agent responsible for handling the ex- ternal interrupt by matching the priority of the interrupt to the corresponding agent located in the kernel agent’s Interrupt Agent Table. It then transfers the

external interrupt details to the interrupt agent’s object and notes the interrupt agent as active within the kernel agent’s Interrupt_States bit-field.

Oak handles three kinds of Oak Timers: scheduler, cycle and timing event tim- ers. The handling of a scheduler timer depends on the state of the timer’s associ- ated scheduler agent. If active and not time for a nested scheduler to deactivate, the kernel agent will push a Selecting_Next_Agent scheduler operation onto its Scheduler_Ops stack: allowing the scheduler agent to manage its queues. If it is time to deactivate a nested scheduler agent (since the agent exhausted its

13. Since agents pass the address of their Oak Message as part of the voluntary context switch.

2

Run Reason

agent request

external interrupt

oak timer

115 ACTON A REAL-TIME EXECUTIVE FOR ADA

budget or passed its deadline), the kernel agent removes the nested scheduler agent from its parent and arranges its next reactivation. Reactivation occurs when the nested scheduler agent’s timer fires while it is inactive, causing the nested scheduler agent added back to its parent.

The handling of a cycle timer, on the other hand, depends on the Timer_Action

property of the timer (which uses Cyclic Task Specification’s Event_Response

type). Since Oak only supports the No_Response and Handler responses, Oak treats the Abort_Cycle and Abort_Task options as No_Response, which the

Run-Loop ignores. When responding with a handler, Oak follows a process

similar to handling external interrupts: activating the corresponding interrupt agent and recording the handler to execute. Timing event timers use the same process. In all cases, the fired timer is deactivated.

Once the run-loop has handled the reason for run, attention turns to selecting

the next agent to dispatch. First, the kernel agent checks for scheduler oper- ations on its Scheduler_Ops stack. If an operation is found, the kernel agent will pop the operation off its stack and select the associated scheduler agent as the next agent to run. The kernel agent copies the scheduling operation into the scheduler agent’s Oak Message store and sets the priority of the system to maximum. The Run-Loop then progresses to the next stage.

If the Scheduler_Ops stack is empty, the kernel searches for the next agent to dispatch. First, the kernel agent consults its active interrupt agent and protected broker lists, choosing the agent or broker with the highest priority: selecting the broker if they have the same priority or the No_Agent if the kernel has no active interrupt agents or protected brokers. The kernel agent then selects the highest priority agent from its top-level schedulers if the agent has a priority greater than the currently selected agent or broker. The top-level scheduler query executes by reading the top-level scheduler agents’ Agent_To_Run component. At this point the kernel agent will have selected an agent or a broker, with the selected item’s priority becoming the system priority. However, the kernel agent does not dispatch selected protected brokers or nested scheduler agents. Instead, if the kernel agent has selected a protected broker, it now elects to dis- patch the task from the protected broker’s Tasks_Within component: allowing

the task inside a protected object to run. Similarly, if a nested scheduler agent has been selected, the kernel agent will select its Agent_To_Run in its place. At this point, the kernel agent will have an agent to dispatch, even if it is the

No_Agent (meaning no other agent was found). Since the No_Agent doubles as the sleep agent, the No_Agent is a valid selection: putting the processor to sleep when dispatched.

A kernel agent maintains a budgets to charge list: a list of agents who will have

their execution budgets consumed by the selected agent. At this step, the kernel agent adds the selected agent to the charge list so it consumes its own budget. This only occurs if the agent’s execution budget is not Time_Span_Last.

3 Select Next Agent to Run

Documento similar