comp.lang.ada
 help / color / mirror / Atom feed
* gnat/linux:setitimer
@ 2004-01-03 18:52 TIlman Glotzner
  2004-01-05 16:18 ` gnat/linux:setitimer Mark H Johnson
  0 siblings, 1 reply; 3+ messages in thread
From: TIlman Glotzner @ 2004-01-03 18:52 UTC (permalink / raw)


Hello,

below my attempt to connect the linux system timer to an ada program.
1) In the process list, I see the program distributed over 5
processes. Each signal handler is mapped onto one process. One
process is probably needed for the main program. On which part
of the program are the other 2 processes mapped to ?

2) When the timer expires, the timer signal (SIGALRM) is not catched
by the signal handler.  The signal handlers itselves apparrently work as
the handlers react to signals sent by a unix kill command. As
process number I need to give the PID of the appropriate signal
handler. I suspect that the signal is sent to the process that
started the itimer. As the signal signal handlers  run as
separated processes, the SIGALRM signal issued from the itimer does not 
reach the signal handlers. What do I need to do to make it work ?

3) Is there a unix utility that allows me to monitor signals,
 i.e. which program issues which signal, and which program catches it ?

4) I first tried to import the system call "setitimer", and hand over
setitimer's parameters by access types(ITimervalPtrs'address). The
program also compiles if handing over the variables directly (not
references to the variables). Is gnat/ada doing a parameter conversion to
a reference implicitly for me ?

Thank you,

Tilman

--------------------------------------------------------------
-- Filename: timer.ads
--------------------------------------------------------------
with Type_Defs,System.Address_To_Access_Conversions,Ada.Interrupts.Names;
use Type_Defs,Ada.Interrupts, Ada.Interrupts.Names;

package Timer is

   -- Timers run in real time.
   ITIMER_REAL: constant := 0;

   -- Timers run only when the process is executing.
   ITIMER_VIRTUAL: constant := 1;

   --  Timers run when the process is executing and when
   --  the system is executing on behalf of the process.
   ITIMER_PROF: constant := 2;

   type T_Time is new Long_Integer;

   type T_Timeval is record
      Tv_Sec : T_Time;        -- seconds
      Tv_Usec: T_Time;        -- microseconds
   end record;

   type T_Itimerval is record
      It_Interval: T_Timeval;    -- next value
      It_Value:    T_Timeval;    -- current Value
   end record;

   package TimevalPtrs is new System.Address_To_Access_Conversions( 
T_Timeval );
   package ITimervalPtrs is new System.Address_To_Access_Conversions( 
T_Itimerval );


  
   protected SignalHandler is
      -- SIGINT (Control-C) signals will be intercepted by
      -- HandleControlC
      procedure HandleControlPwrFail;
      pragma Attach_Handler( HandleControlPwrFail, SIGPWR );

      -- Signal handler for SIGALARM issued from a timer
      procedure HandleAlarm;
      pragma Attach_Handler( HandleAlarm,  SIGALRM );
   end SignalHandler;

   procedure Setitimer(RC:out  Integer; Which: in Integer ;
                       Value: in out T_Itimerval;
                       Ovalue: in out T_Itimerval);
   pragma Import (C,Setitimer);
  pragma Import_Valued_Procedure(Setitimer);

end Timer;

--------------------------------------------------------------
-- Filename: timer.adb
--------------------------------------------------------------
with Timer, System.Address_To_Access_Conversions,Text_IO;
use Timer,Text_Io;
package body Timer is
   protected body SignalHandler is
      -- This protected type contains all our signal handlers
      procedure HandleAlarm is
         -- Alarm signal handler
      begin
         Put_Line( "HandleAlarm: ALARMSIG catched." );
      end HandleAlarm;

      procedure HandleControlPwrFail is
         -- Power fail signal handler
      begin
         Put_Line( "HandleControlPwrFail activated by catched signal SIGPWR" 
);
      end HandleControlPwrFail;
   end SignalHandler;
end Timer;

--------------------------------------------------------------
-- Filename: timer_test.adb
--------------------------------------------------------------
with Text_Io,Timer,Ada.Interrupts,Ada.Interrupts.Names;
use Text_Io,Timer,Ada.Interrupts,Ada.Interrupts.Names;

procedure Timer_Test_B is
   Handler : Parameterless_Handler;
   Counter: Integer := 0;
   Timer: aliased T_Itimerval := ((0,10000),(0,10000));
   OldTimer:  aliased T_Itimerval := ((0,0),(0,0));
   I: Integer := 20;
begin
   Put_Line("Timer_Test");
   Put_Line("==========");


   Timer.It_Value.Tv_Sec := 0;
   Timer.It_Value.Tv_Usec := 100000;
   Timer.It_Interval.Tv_Sec  := 0;
   Timer.It_Interval.Tv_Usec := 100000;

   if Is_Reserved( SIGALRM ) then
      Put_Line( "The ALARMSIG handler is reserved" );
   else
      Put_Line( "The ALARMSIG handler isn't reserved" );
  end if;

   if Is_Attached( SIGALRM ) then
      Put_Line( "The ALARMSIG handler is attached" );
   else
      Put_Line( "The ALARMSIG handler isn't attached" );
   end if;

   if Is_Reserved( SIGPWR ) then
      Put_Line( "The SIGPWR handler is reserved" );
   else
      Put_Line( "The SIGPWR handler isn't reserved" );
   end if;

   if Is_Attached( SIGPWR ) then
      Put_Line( "The SIGPWR handler is attached" );
   else
      Put_Line( "The SIGPWR handler isn't attached" );
   end if;

   New_Line;
   Put_Line( "Testing SIGALRM handler..." );

   Handler := Current_Handler( SIGALRM );
   -- Current_Handler gives a callback to the handler
   Handler.all;
   Put_Line( "End testing SIGALRM handler..." );


   New_Line;
   Put_Line( "Testing SIGPWR handler..." );
   Handler := Current_Handler( SIGPWR );
   -- Current_Handler gives a callback to the handler
   Handler.all;
   Put_Line( "End testing SIGPWR handler..." );
   New_Line;

   Put_Line("Timer parameters");
   Put_Line("----------------");
   Put_Line("Time.sec = " & Timer.It_Value.Tv_Sec'Img );
   Put_Line("Time.usec= " & Timer.It_Value.Tv_Usec'Img );
   Put_Line("Preset.sec = " & Timer.It_Interval.Tv_Sec'Img );
   Put_Line("Preset.usec= " & Timer.It_Interval.Tv_Usec'Img );

   New_Line;
   Put("Arming timer...");

   Setitimer(I,ITIMER_REAL,Timer,OldTimer);
--                 ITimervalPtrs.To_Address(Timer'Unchecked_access),
--                 ITimervalPtrs.To_Address(OldTimer'Unchecked_Access));


   Put_Line("  Timer armed.");
   New_Line;

   Put_Line("I := " & I'Img);
   while (Counter <=  I) loop
      null;
--         Counter := Counter + 1;

--         delay(1.0);
      end loop;

end Timer_Test_B;

-- 
Tilman Gloetzner
ETAS Korea Ltd, Seoul, Korea



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: gnat/linux:setitimer
  2004-01-03 18:52 gnat/linux:setitimer TIlman Glotzner
@ 2004-01-05 16:18 ` Mark H Johnson
  2004-01-15  3:35   ` gnat/linux:setitimer Tilman Glotzner
  0 siblings, 1 reply; 3+ messages in thread
From: Mark H Johnson @ 2004-01-05 16:18 UTC (permalink / raw)


TIlman Glotzner wrote:
> Hello,
> 
> below my attempt to connect the linux system timer to an ada program.
> 1) In the process list, I see the program distributed over 5
> processes. Each signal handler is mapped onto one process. One
> process is probably needed for the main program. On which part
> of the program are the other 2 processes mapped to ?
> 

The GNAT implementation of tasks on Linux (up until *very* recently) has 
processes for
  - the main program
  - a thread manager
  - a thread per signal being managed
  - a thread per task
and they show up as individual processes in ps, top, etc. We ended up 
writing a small library package that would write a file in /tmp/ that 
had our "task name" so we could correlate between PID's and tasks.

When I mean "very recently", if you are using the new pthread library 
(e.g., Red Hat 9 or later), the rules have changed somewhat and I 
haven't used it enough to comment on it.

> 2) When the timer expires, the timer signal (SIGALRM) is not catched
> by the signal handler.  The signal handlers itselves apparrently work as
> the handlers react to signals sent by a unix kill command. As
> process number I need to give the PID of the appropriate signal
> handler. I suspect that the signal is sent to the process that
> started the itimer. As the signal signal handlers  run as
> separated processes, the SIGALRM signal issued from the itimer does not 
> reach the signal handlers. What do I need to do to make it work ?
> 
What we do instead is to:
  - determine the process group
  - use killpg instead of kill to send the signal to the process group
In this case, the signal is delivered to all the threads and all but one 
thread will ignore it. Only the signal handler will catch it and process it.

> 3) Is there a unix utility that allows me to monitor signals,
>  i.e. which program issues which signal, and which program catches it ?
> 
The latter part can be done with the debugger (gdb). I am not aware of 
any utility to tell you who sent the signal.

> 4) I first tried to import the system call "setitimer", and hand over
> setitimer's parameters by access types(ITimervalPtrs'address). The
> program also compiles if handing over the variables directly (not
> references to the variables). Is gnat/ada doing a parameter conversion to
> a reference implicitly for me ?
> 
Not sure, we have C code that actually calls setitimer in our system 
:-). You should be able to do something like...
   pragma Interface(C, Setitimer);
and use declarations that are compatible with C to call setitimer 
directly from Ada. We do that for a lot of other functions but just not 
that one.

You may also need
   pragma Unreserve_All_Interrupts;
since the run time may also be trapping the specific signals you are 
trying to use.
   --Mark





^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: gnat/linux:setitimer
  2004-01-05 16:18 ` gnat/linux:setitimer Mark H Johnson
@ 2004-01-15  3:35   ` Tilman Glotzner
  0 siblings, 0 replies; 3+ messages in thread
From: Tilman Glotzner @ 2004-01-15  3:35 UTC (permalink / raw)



1) How do I monitor signals with gdb ? 
I know of the "handle <signal> print" command, and the "handle <signal> 
stop" command. 
I tried to set a breakpoint with "catch signal 14", but gdb tells me, that 
this feature is not yet implemented (My version of gdb is 5.1.1). 
Are there any other ways ?

2) I tried to to export all signal related code to c, and released all 
signals  by using pragma Unreserve_All_Interrupts (see program below). The 
signal is not catched either:
Even though setitimer returns a 0 (=success), I am suspecious if the 
SIG_ALRM signal is really sent.

Or maybe  gnat's runtime library uses that signal even though it should be 
release released by pragma Unreserve_All_Interrupts



--------------------------------------------------------------
-- Filename: timer_test.adb
-- Desc: Test program for timer package
--
-- (c) 2003 Tilman Glotzner, DG2TG
--
-- History:
-- Date       Name         Descrition
-- 2003-12-08 T. Glotzner  Creation
--------------------------------------------------------------
pragma Unreserve_All_Interrupts;

with Text_Io,Ada.Interrupts,Ada.Interrupts.Names;
use Text_Io,Ada.Interrupts,Ada.Interrupts.Names;

procedure Timer_Test_A is
   Counter: Integer := 0;
   I: Integer := 20;

   procedure Settimer;
   pragma Import (C,Settimer);
begin
   New_line;
   Put_Line("Timer_Test_A");
   Put_Line("==========");

   Settimer;
   Put_Line("I := " & I'Img);
   while (Counter <=  I) loop
      null;
         Counter := Counter + 1;


         delay(0.5);
--         Put_Line("Counter = " & Counter'Img);
      end loop;

end Timer_Test_A;

// Filename: setitimer.c

#include<stdlib.h>
#include<stdio.h>
#include<signal.h>
#include<time.h>
#include<unistd.h>
#include<sys/time.h>


void sigalrm_dispatcher(int signal)
{
    printf("sigalarm dispatcher started (%d)\n",signal);
}


int settimer()
{
    int status;
    struct itimerval timer;
    /* initial interval */
    timer.it_value.tv_sec = 2;
    timer.it_value.tv_usec = 100000;
    /* subsequent intervals */
    timer.it_interval.tv_sec = 0;
    timer.it_interval.tv_usec = 500000;

    if (SIG_ERR == signal ( SIGALRM, sigalrm_dispatcher ))
    {
      printf("Installation of signal handler failed.\n");
    }
    else
    {
      printf("Installation of signal handler successful.\n");
    }


    status = setitimer( ITIMER_REAL, &timer, NULL );
    printf("settimer executed (Status=%d).\n",status);
}

Thanks,

Tilman



Mark H Johnson

Mark H Johnson wrote:

> TIlman Glotzner wrote:
>> Hello,
>> 
>> below my attempt to connect the linux system timer to an ada program.
>> 1) In the process list, I see the program distributed over 5
>> processes. Each signal handler is mapped onto one process. One
>> process is probably needed for the main program. On which part
>> of the program are the other 2 processes mapped to ?
>> 
> 
> The GNAT implementation of tasks on Linux (up until *very* recently) has
> processes for
>   - the main program
>   - a thread manager
>   - a thread per signal being managed
>   - a thread per task
> and they show up as individual processes in ps, top, etc. We ended up
> writing a small library package that would write a file in /tmp/ that
> had our "task name" so we could correlate between PID's and tasks.
> 
> When I mean "very recently", if you are using the new pthread library
> (e.g., Red Hat 9 or later), the rules have changed somewhat and I
> haven't used it enough to comment on it.
> 
>> 2) When the timer expires, the timer signal (SIGALRM) is not catched
>> by the signal handler.  The signal handlers itselves apparrently work as
>> the handlers react to signals sent by a unix kill command. As
>> process number I need to give the PID of the appropriate signal
>> handler. I suspect that the signal is sent to the process that
>> started the itimer. As the signal signal handlers  run as
>> separated processes, the SIGALRM signal issued from the itimer does not
>> reach the signal handlers. What do I need to do to make it work ?
>> 
> What we do instead is to:
>   - determine the process group
>   - use killpg instead of kill to send the signal to the process group
> In this case, the signal is delivered to all the threads and all but one
> thread will ignore it. Only the signal handler will catch it and process
> it.
> 
>> 3) Is there a unix utility that allows me to monitor signals,
>>  i.e. which program issues which signal, and which program catches it ?
>> 
> The latter part can be done with the debugger (gdb). I am not aware of
> any utility to tell you who sent the signal.
> 
>> 4) I first tried to import the system call "setitimer", and hand over
>> setitimer's parameters by access types(ITimervalPtrs'address). The
>> program also compiles if handing over the variables directly (not
>> references to the variables). Is gnat/ada doing a parameter conversion to
>> a reference implicitly for me ?
>> 
> Not sure, we have C code that actually calls setitimer in our system
> :-). You should be able to do something like...
>    pragma Interface(C, Setitimer);
> and use declarations that are compatible with C to call setitimer
> directly from Ada. We do that for a lot of other functions but just not
> that one.
> 
> You may also need
>    pragma Unreserve_All_Interrupts;
> since the run time may also be trapping the specific signals you are
> trying to use.
>    --Mark

-- 
Tilman Glotzner
ETAS Ltd, Seoul, Korea



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2004-01-15  3:35 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-01-03 18:52 gnat/linux:setitimer TIlman Glotzner
2004-01-05 16:18 ` gnat/linux:setitimer Mark H Johnson
2004-01-15  3:35   ` gnat/linux:setitimer Tilman Glotzner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox