Hi all,

  Over on the cygwin-improvements branch(*) I've got a fairly nifty fully
POSIX-based port of Ada, but there's one FAIL on the gnat testsuite that I'm
trying to debug.  It could be a bug in the port, or the testcase might have
stressed an underlying bug in Cygwin's pthread functions.  I'm hoping to get
some pointers to help me understand the architecture of the tasking control in
GNAT.

  The failing case is gnat.dg/task_stack_align.adb, which fails like so:

> $ ./task_stack_align.exe
> 
> raised TASKING_ERROR : Failure during activation
> 
> $

  Debugging it suggests that the problem arises in Activate_Tasks
(s-tassta.adb), here:

>       if Self_ID.Common.Activation_Failed then
>          Self_ID.Common.Activation_Failed := False;
>          raise Tasking_Error with "Failure during activation";
>       end if;

which I think is triggering as a consequence of this sequence in
Vulnerable_Complete_Activation (also s-tassta.adb):

>       --  The activator raises a Tasking_Error if any task it is activating
>       --  is completed before the activation is done. However, if the reason
>       --  for the task completion is an abort, we do not raise an exception.
>       --  See RM 9.2(5).
> 
>       if not Self_ID.Callable and then Self_ID.Pending_ATC_Level /= 0 then
>          Activator.Common.Activation_Failed := True;
>       end if;

  If I take a look at the state of the tasks when the exception is raised,
they claim to all have terminated:

> Breakpoint 1, 0x004183ca in <__gnat_raise_exception> (e=0x42c38c,
>     message=0x4316e3) at a-exexda.adb:244
> 244        procedure Append_Info_Character
> (gdb) call list_tasks
> tasks(50): TERMINATED, parent: main_task, prio: 0, not callable, abort 
> deferred
> tasks(49): TERMINATED, parent: main_task, prio: 0, not callable, abort 
> deferred
> tasks(48): TERMINATED, parent: main_task, prio: 0, not callable, abort 
> deferred
    [ ...  snip similar entries  ... ]
> tasks(31): TERMINATED, parent: main_task, prio: 0, not callable, abort 
> deferred
> tasks(30): TERMINATED, parent: main_task, prio: 0, not callable, abort 
> deferred
> tasks(29): TERMINATED, parent: main_task, prio: 0, not callable, abort 
> deferred
> tasks(28): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
[  I'm not sure if there's any significance in the way the priority fields
change from 0 to 15 at this point yet.  ]
> tasks(27): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
> tasks(26): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
    [ ...  snip similar entries  ... ]
> tasks(4): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
> tasks(3): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
> tasks(2): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
> tasks(1): TERMINATED, parent: main_task, prio: 15, not callable, abort 
> deferred
> main_task: RUNNABLE, parent: <none>, prio: 15
> (gdb) call print_current_task
> main_task: RUNNABLE, parent: <none>, prio: 15
> (gdb)

  So, if I've understood what I'm seeing, there's this object called an
activator, and it has a whole bunch of threads (ada tasks) that it wants to
start up in parallel, but it doesn't want them to all just start running
straight away; it wants them all to be created at once before any of them have
a chance to finish their work.

  That makes me think that it must be trying to create them in some suspended
state, or gate their progress past a mutex or semaphore of some kind, so that
it can create them all and then wake them all at once when it's done.  Is this
right?  If so, can anyone point me at the mechanism that is supposed to hold
the threads back but appears to be failing in this case?  If not, can someone
tell me how the task activation is supposed to work in this test?

    cheers,
      DaveK

Reply via email to