4

Thanks in advance for any help. I am currently doing some beginner work on ada programming and I have installed GNAT Programming Studio (GPS) from http://libre.adacore.com/download/configurations# I have Windows 10 64-bits. I was given the following code at school:

pragma Task_Dispatching_Policy(FIFO_Within_Priorities);

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Real_Time; use Ada.Real_Time;

procedure PeriodicTasks is

    Start : Time;

    package Duration_IO is new Ada.Text_IO.Fixed_IO(Duration);
    package Int_IO is new Ada.Text_IO.Integer_IO(Integer);

    task type T(Id: Integer; Period : Integer) is
        pragma Priority(Id);
    end;

    task body T is
        Next : Time;
        X : Integer;
    begin
        Next := Start;
        loop
            Next := Next + Milliseconds(Period);
            -- Some dummy function
            X := 0;
            for Index in 1..5000000 loop
                X := X + Index;
            end loop;
            Duration_IO.Put(To_Duration(Clock - Start), 3, 3);
            Put(" : ");
            Int_IO.Put(Id, 2);
            Put_Line("");
            delay until Next;
        end loop;
    end T;

    -- Example Task
    Task_P10 : T(10, 250);
    Task_P12 : T(12, 500);
    Task_P14 : T(14, 500);
    Task_P16 : T(16, 250);
    Task_P18 : T(18, 500);
    Task_P20 : T(20, 250);
begin
    Start := Clock;
    null;
end PeriodicTasks;

I opened the file in GPS, built it (no errors) and ran it but it doesn't show any printed output. I have heard that sometimes you get issues with multicore CPUs, so everytime the gps.exe is opened, the CPU affinity is set to only one CPU and it is always "Run as Administrator". However, this did not work either, I get no output. I decided to use Oracle Virtual Box and set up an Ubuntu OS (32 bits) with only one processor. Installed the GNAT tools, compiled with gnatmake, ran with ./periodictasks, and guess what, the program did what it is supposed to do and printed out the info.

After all this long story, does anybody know why this is happening? Could it be a 64 bit vs 32 bit situation?

Thank you very much!

2 Answers2

2

Until recently, GNAT didn't check for integer overflow by default. It did check for constraint errors, e.g. assigning 0 to a Positive.

Many of us thought this was a strange choice by the compiler developers, because it led to many questions whose root cause was failure to handle integer overflow. The recent change leads us to suppose that the developers now agree!

Your problem arises because of the statement

for Index in 1..5000000 loop
   X := X + Index;
end loop;

which would end up with X ~ 10^13, which doesn’t fit in a 32-bit integer (it would fit in a 64-bit integer, but that would be a Long_Long_Integer on most if not all GNAT platforms).

It’s likely that your Windows compiler is GNAT GPL 2016, which shows the new behaviour, while the Ubuntu compiler is an older FSF GCC.

You can tell your Windows compiler to use the old behaviour using the compiler switch -gnato0.

You can tell your Ubuntu compiler to use the new behaviour using the compiler switch -gnato.

To get an exception message on unhandled exceptions in tasks (which otherwise die silently), you can add

GNAT.Exception_Traces.Trace_On (GNAT.Exception_Traces.Unhandled_Raise);

at the beginning of your main program.

Simon Wright
  • 25,108
  • 2
  • 35
  • 62
  • 1
    It is worth noting that the old behavior is not correct for an Ada compiler. Until recently GNAT was only an Ada compiler if you passed it the "-gnato" parameter. – Jacob Sparre Andersen Sep 17 '16 at 17:43
  • 1
    See also [*§8.4 Overflow Check Handling in GNAT*](https://gcc.gnu.org/onlinedocs/gcc-6.2.0/gnat_ugn/Overflow-Check-Handling-in-GNAT.html#Overflow-Check-Handling-in-GNAT) – trashgod Sep 18 '16 at 03:09
  • Thank you very much!!!!! I modified the Project -> Build properties, added the -gnato0 switch and its working! Thanks A LOT! – Alejandro Martinez Sep 18 '16 at 07:17
  • I am having a slightly different problem now. (should I post another question?) Whether I add the -gnato0 or I change the Integer to Long_Long_Integer, whenever I run the program INSIDE the GPS environment it hangs. If I "Run in an external terminal" (which is what I had from the beginning) the program runs, HOWEVER, at the beginning of the execution there is garbage printed and the only tasks that print information are Task_P20 & Task_P18. In Ubuntu ALL tasks print out information at least once! Thanks again! – Alejandro Martinez Sep 18 '16 at 11:28
  • @AlejandroMartinez: I've addressed part of your revised question [here](http://stackoverflow.com/a/39559827/230513); you should edit this question accordingly; pose a new question for any remaining problems. – trashgod Sep 18 '16 at 16:18
2

at the beginning of the execution, there is garbage printed and the only tasks that print information are Task_P20 & Task_P18.

As discussed in §9.2 Task Execution - Task Activation, the tasks are activated together before the first statement of PeriodicTasks executes. Although all tasks are running, no, some or all tasks may try to produce output before Start is initialized. At a minimum, initialize Start as close to its declaration as possible,

Start : Time := Clock;

and leave the body empty,

begin
    null;
end PeriodicTasks;

Moreover, a task that fails to activate becomes a completed task, producing no output.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thank you very much! The only thing I still don't understand is why this happens only in windows and not in the Ubuntu virtual machine. What can I do to the windows environment to make it behave like the Ubuntu VM or the other way around. I'll post another question. Thanks again! – Alejandro Martinez Sep 19 '16 at 06:18
  • An [erroneous](http://www.adaic.org/resources/add_content/docs/95style/html/sec_5/5-9.html) program may behave inconsistently across platforms; I'd expect the corrected program to execute consistently. – trashgod Sep 19 '16 at 07:08