Interrupt_Access_Hold : Interrupt_Task_Access;
-- Variable for allocating an Interrupt_Server_Task
- Default_Handler : array (HW_Interrupt) of Interfaces.VxWorks.VOIDFUNCPTR;
- -- Vectored interrupt handlers installed prior to program startup.
- -- These are saved only when the umbrella handler is installed for
- -- a given interrupt number.
+ Handler_Installed : array (HW_Interrupt) of Boolean := (others => False);
+ -- True if Notify_Interrupt was connected to the interrupt. Handlers
+ -- can be connected but disconnection is not possible on VxWorks.
+ -- Therefore we ensure Notify_Installed is connected at most once.
-----------------------
-- Local Subprograms --
procedure Notify_Interrupt (Param : System.Address);
-- Umbrella handler for vectored interrupts (not signals)
- procedure Install_Default_Action (Interrupt : HW_Interrupt);
- -- Restore a handler that was in place prior to program execution
-
procedure Install_Umbrella_Handler
(Interrupt : HW_Interrupt;
Handler : Interfaces.VxWorks.VOIDFUNCPTR);
Unimplemented ("Ignore_Interrupt");
end Ignore_Interrupt;
- ----------------------------
- -- Install_Default_Action --
- ----------------------------
-
- procedure Install_Default_Action (Interrupt : HW_Interrupt) is
- begin
- -- Restore original interrupt handler
-
- Interfaces.VxWorks.intVecSet
- (Interfaces.VxWorks.INUM_TO_IVEC (Integer (Interrupt)),
- Default_Handler (Interrupt));
- Default_Handler (Interrupt) := null;
- end Install_Default_Action;
-
----------------------
-- Install_Handlers --
----------------------
end loop;
end Install_Handlers;
+ ---------------------------------
+ -- Install_Restricted_Handlers --
+ ---------------------------------
+
+ procedure Install_Restricted_Handlers (Handlers : New_Handler_Array) is
+ begin
+ for N in Handlers'Range loop
+ Attach_Handler (Handlers (N).Handler, Handlers (N).Interrupt, True);
+ end loop;
+ end Install_Restricted_Handlers;
+
------------------------------
-- Install_Umbrella_Handler --
------------------------------
Vec : constant Interrupt_Vector :=
INUM_TO_IVEC (Interfaces.VxWorks.int (Interrupt));
- Old_Handler : constant VOIDFUNCPTR :=
- intVecGet
- (INUM_TO_IVEC (Interfaces.VxWorks.int (Interrupt)));
-
Stat : Interfaces.VxWorks.STATUS;
pragma Unreferenced (Stat);
-- ??? shouldn't we test Stat at least in a pragma Assert?
-- when an interrupt occurs, so the umbrella handler has a different
-- wrapper generated by intConnect for each interrupt number.
- if Default_Handler (Interrupt) = null then
- Stat :=
- intConnect (Vec, Handler, System.Address (Interrupt));
- Default_Handler (Interrupt) := Old_Handler;
+ if not Handler_Installed (Interrupt) then
+ Stat := intConnect (Vec, Handler, System.Address (Interrupt));
+ Handler_Installed (Interrupt) := True;
end if;
end Install_Umbrella_Handler;
-- Umbrella handler for vectored hardware interrupts (as opposed to
-- signals and exceptions). As opposed to the signal implementation,
- -- this handler is only installed in the vector table while there is
- -- an active association of an Ada handler to the interrupt.
+ -- this handler is installed in the vector table when the first Ada
+ -- handler is attached to the interrupt. However because VxWorks don't
+ -- support disconnecting handlers, this subprogram always test wether
+ -- or not an Ada handler is effectively attached.
-- Otherwise, the handler that existed prior to program startup is
-- in the vector table. This ensures that handlers installed by
procedure Notify_Interrupt (Param : System.Address) is
Interrupt : constant Interrupt_ID := Interrupt_ID (Param);
+ Id : constant SEM_ID := Semaphore_ID_Map (Interrupt);
+
Discard_Result : STATUS;
pragma Unreferenced (Discard_Result);
begin
- Discard_Result := semGive (Semaphore_ID_Map (Interrupt));
+ if Id /= 0 then
+ Discard_Result := semGive (Id);
+ end if;
end Notify_Interrupt;
---------------
use type STATUS;
begin
- -- Hardware interrupt
-
- Install_Default_Action (HW_Interrupt (Interrupt));
-- Flush server task off semaphore, allowing it to terminate
POP.Write_Lock (Self_Id);
+ -- Unassociate the interrupt handler.
+
+ Semaphore_ID_Map (Interrupt) := 0;
+
-- Delete the associated semaphore
S := semDelete (Int_Sema);
-- Set status for the Interrupt_Manager
- Semaphore_ID_Map (Interrupt) := 0;
Server_ID (Interrupt) := Null_Task;
POP.Unlock (Self_Id);
end loop;
end Install_Handlers;
+ ---------------------------------
+ -- Install_Restricted_Handlers --
+ ---------------------------------
+
+ procedure Install_Restricted_Handlers (Handlers : New_Handler_Array) is
+ begin
+ for N in Handlers'Range loop
+ Attach_Handler (Handlers (N).Handler, Handlers (N).Interrupt, True);
+ end loop;
+ end Install_Restricted_Handlers;
+
----------------
-- Is_Blocked --
----------------
-- Abort_Task_Interrupt is one of the Interrupt unmasked
-- in all tasks. We mask the Interrupt in this particular task
- -- so that "sigwait" is possible to catch an explicitely sent
+ -- so that "sigwait" is possible to catch an explicitly sent
-- Abort_Task_Interrupt from the Server_Tasks.
-- This sigwaiting is needed so that we make sure a Server_Task is
-- Abort_Task_Interrupt is one of the Interrupt unmasked in all tasks.
-- We mask the Interrupt in this particular task so that "sigwait" is
- -- possible to catch an explicitely sent Abort_Task_Interrupt from the
+ -- possible to catch an explicitly sent Abort_Task_Interrupt from the
-- Interrupt_Manager.
-- There are two Interrupt interrupts that this task catch through
end if;
-- Undefer abort here to allow a window for this task to be aborted
- -- at the time of system shutdown. We also explicitely test for
+ -- at the time of system shutdown. We also explicitly test for
-- Pending_Action in case System.Parameters.No_Abort is True.
end loop;