comp.lang.ada
 help / color / mirror / Atom feed
* Bug in GNAT? - Max_size_in_storage_elements insufficient
@ 2016-10-18 11:17 Vratislav Podzimek
  2016-10-18 12:35 ` Dmitry A. Kazakov
  2016-10-19 13:34 ` Egil H H
  0 siblings, 2 replies; 10+ messages in thread
From: Vratislav Podzimek @ 2016-10-18 11:17 UTC (permalink / raw)


When trying to set Storage_Size for tasks or records I'm getting a crash 
indicating that the Max_size_in_storage_elements attribute doesn't seem 
to provide the correct value. Here are the simple reproducers:

1) task type

with Ada.Text_Io; use Ada.Text_Io;

procedure Task_Storage_Size is
   task type My_Task (Id : Natural);    --  works just fine without the 
discriminant
   task body My_Task is
      X : Natural := Id;
   begin
      X := X ** 10;

      Put_Line ("ID : " & Natural'Image (Id));
   end;

   type My_Task_Access is access My_Task
     with Storage_Size => 4 * My_Task'Max_size_in_storage_elements; --  
Crashes
--     with Storage_Size => 6 * My_Task'Max_size_in_storage_elements; -- 
Doesn't crash.

   type My_Task_Array is array (Natural range <>) of My_Task_Access;
   Tasks : My_Task_Array (1..4);
begin
   --  raises STORAGE_ERROR : s-poosiz.adb:259 explicit raise
   for I in Tasks'Range loop
      Tasks (I) := new My_Task (I);
   end loop;
end;


2) record type:

procedure Record_Storage_Size is
   type My_Record is
      record
         X : Natural := 0;
      end record;

   type My_Record_Access is access My_Record
     with Storage_Size => 4 * My_Record'Max_size_in_storage_elements; -- 
crashes
     -- with Storage_Size => 8 * My_Record'Max_size_in_storage_elements; 
-- doesn't crash

   type My_Record_Array is array (Natural range <>) of My_Record_Access;
   Records : My_Record_Array (1..4);
begin
   --  raises STORAGE_ERROR : s-poosiz.adb:108 explicit raise
   for I in Records'Range loop
      Records (I) := new My_Record;
   end loop;
end;


To safe us from a potential discussion that has already happened on IRC, 
here's the related chunk from the RM:
"If Storage_Size is specified for an access type, then the Storage_Size 
of this pool is at least that requested, and the storage for the pool is 
reclaimed when the master containing the declaration of the access type 
is left"

So Storage_Size specification for an access type specifies the amount of 
space for the allocated objects of the accessed type. However, it can 
also be used for a task type (not access to a task type) to specify the 
amount of space for a task's stack.

Or am I missing something?


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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 11:17 Bug in GNAT? - Max_size_in_storage_elements insufficient Vratislav Podzimek
@ 2016-10-18 12:35 ` Dmitry A. Kazakov
  2016-10-18 15:26   ` Vratislav Podzimek
  2016-10-19 13:34 ` Egil H H
  1 sibling, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2016-10-18 12:35 UTC (permalink / raw)


On 18/10/2016 13:17, Vratislav Podzimek wrote:

> Or am I missing something?

A storage pool requires additional space to organize its structure and 
maintain its state. Depending on the method it is usually impossible to 
estimate the exact number of object  the pool may hold. It depends on 
the individual sizes of the objects, the history of object's allocation 
and deallocation, the history of claiming the memory for the parts of 
the pool from the OS (a pool can be segmented).

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 12:35 ` Dmitry A. Kazakov
@ 2016-10-18 15:26   ` Vratislav Podzimek
  2016-10-18 16:03     ` Dmitry A. Kazakov
                       ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Vratislav Podzimek @ 2016-10-18 15:26 UTC (permalink / raw)


On Tue, 18 Oct 2016 14:35:15 +0200, Dmitry A. Kazakov wrote:

> On 18/10/2016 13:17, Vratislav Podzimek wrote:
> 
>> Or am I missing something?
> 
> A storage pool requires additional space to organize its structure and
> maintain its state. Depending on the method it is usually impossible to
> estimate the exact number of object  the pool may hold. It depends on
> the individual sizes of the objects, the history of object's allocation
> and deallocation, the history of claiming the memory for the parts of
> the pool from the OS (a pool can be segmented).

Well, then it's at least a bug in [Barnes] because there's an example 
like the above ones just with a simpler type. But I still think the idea 
here is/was to provide enough space for N items of some type. That's what 
the 'Max_size_in_storage_elements' attribute should be good for. And 
there's no fragmentation nor history of allocation/deallocation in my 
case. If I specify I want space for 4 records, I should get space for 4 
records. Not slightly less due to some hidden, unpredictable overhead.

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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 15:26   ` Vratislav Podzimek
@ 2016-10-18 16:03     ` Dmitry A. Kazakov
  2016-10-19  1:39       ` Luke A. Guest
  2016-10-19 15:45     ` Eryndlia Mavourneen
  2016-10-19 15:53     ` Eryndlia Mavourneen
  2 siblings, 1 reply; 10+ messages in thread
From: Dmitry A. Kazakov @ 2016-10-18 16:03 UTC (permalink / raw)


On 2016-10-18 17:26, Vratislav Podzimek wrote:
> On Tue, 18 Oct 2016 14:35:15 +0200, Dmitry A. Kazakov wrote:
>
>> On 18/10/2016 13:17, Vratislav Podzimek wrote:
>>
>>> Or am I missing something?
>>
>> A storage pool requires additional space to organize its structure and
>> maintain its state. Depending on the method it is usually impossible to
>> estimate the exact number of object  the pool may hold. It depends on
>> the individual sizes of the objects, the history of object's allocation
>> and deallocation, the history of claiming the memory for the parts of
>> the pool from the OS (a pool can be segmented).
>
> Well, then it's at least a bug in [Barnes] because there's an example
> like the above ones just with a simpler type. But I still think the idea
> here is/was to provide enough space for N items of some type.

I am not sure if that were technically possible. Considering an 
implementation of, for example, a marked-margins pool, the penalty to 
have a guarantee would be extremely high.

> That's what
> the 'Max_size_in_storage_elements' attribute should be good for. And
> there's no fragmentation nor history of allocation/deallocation in my
> case.

You don't know the implementation of. A segmented pool may request 
system memory on demand adapting the size of segments to the allocation 
requests: Max (Chunk size, Requested size).

> If I specify I want space for 4 records, I should get space for 4
> records. Not slightly less due to some hidden, unpredictable overhead.

If you know the pool size in advance and the objects in it, why don't 
you use a custom pool backed by an array? An arena pool would be exactly 
for this and trivial to implement in Ada.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 16:03     ` Dmitry A. Kazakov
@ 2016-10-19  1:39       ` Luke A. Guest
  2016-10-19  7:33         ` Dmitry A. Kazakov
  2016-10-20  0:59         ` Randy Brukardt
  0 siblings, 2 replies; 10+ messages in thread
From: Luke A. Guest @ 2016-10-19  1:39 UTC (permalink / raw)


Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:

>> Well, then it's at least a bug in [Barnes] because there's an example
>> like the above ones just with a simpler type. But I still think the idea
>> here is/was to provide enough space for N items of some type.
> 
> I am not sure if that were technically possible. Considering an 
> implementation of, for example, a marked-margins pool, the penalty to 
> have a guarantee would be extremely high.

Surely that's what a static language can supply, the actual amount of space
required?



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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-19  1:39       ` Luke A. Guest
@ 2016-10-19  7:33         ` Dmitry A. Kazakov
  2016-10-20  0:59         ` Randy Brukardt
  1 sibling, 0 replies; 10+ messages in thread
From: Dmitry A. Kazakov @ 2016-10-19  7:33 UTC (permalink / raw)


On 19/10/2016 03:39, Luke A. Guest wrote:
> Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>
>>> Well, then it's at least a bug in [Barnes] because there's an example
>>> like the above ones just with a simpler type. But I still think the idea
>>> here is/was to provide enough space for N items of some type.
>>
>> I am not sure if that were technically possible. Considering an
>> implementation of, for example, a marked-margins pool, the penalty to
>> have a guarantee would be extremely high.
>
> Surely that's what a static language can supply, the actual amount of space
> required?

In the mentioned above method you allocate a "margin" in front and in 
the end of each block. The margin contains an indicator if the block is 
free and the block size. When a block is freed the margins of adjacent 
blocks are inspected and the block is merged with its free neighbors. 
The memory overhead depends on the number of blocks, which in turn 
depends on the number of allocated objects and on how their blocks are 
distributed. In the worst case scenario you have a gap between each two 
allocated blocks. Which gives 2 * (2*N - 1) - 2 margins to keep in the pool.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 11:17 Bug in GNAT? - Max_size_in_storage_elements insufficient Vratislav Podzimek
  2016-10-18 12:35 ` Dmitry A. Kazakov
@ 2016-10-19 13:34 ` Egil H H
  1 sibling, 0 replies; 10+ messages in thread
From: Egil H H @ 2016-10-19 13:34 UTC (permalink / raw)


Using Max_Size_In_Storage_Elements in this way is asking for trouble, and not at all portable, as the actual storage needed may depend on Alignment and fragmentation.
However, looking at GNAT's implementation (GNATPro 7.4.1), there are a couple quirks;

First off, the storage pool used by GNAT in this case ends up in a buffer on the stack. Unallocated parts of the buffer is implemented as a kind of overlayed linked list of chunks. This list always needs at least one root node, with a size field and pointer to the next node (on my 64 bit machine, the node is a total of 16 storage_elements), so that's several bytes worth of extra space needed, which 'Max_Size_In_Storage_Elements does not (and can not) take into account. I'll leave it up to AdaCore to answer whether this is the intended behaviour.

Secondly, when allocating an object in the pool, there is a search for a large enough chunk. This search checks if the chunk size is less than (not less than or equal to) the requested size + alignment. So the actual chunk selected must be at least one byte larger than requested, which must be a bug...

Knowing this, I got your code code working on my machine by doing
Storage_Size => (Num_Tasks * My_Task'Max_Size_In_Storage_Elements) + 17
This is of course not at all portable across compilers, not even across GNAT versions... And certainly not portable across machine architectures. 

So, one oddity and a likely bug... You may as well report it...

-- 
~egilhh

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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 15:26   ` Vratislav Podzimek
  2016-10-18 16:03     ` Dmitry A. Kazakov
@ 2016-10-19 15:45     ` Eryndlia Mavourneen
  2016-10-19 15:53     ` Eryndlia Mavourneen
  2 siblings, 0 replies; 10+ messages in thread
From: Eryndlia Mavourneen @ 2016-10-19 15:45 UTC (permalink / raw)


On Tuesday, October 18, 2016 at 10:26:28 AM UTC-5, Vratislav Podzimek wrote:
> Well, then it's at least a bug in [Barnes] because there's an example 
> like the above ones just with a simpler type. But I still think the idea 
> here is/was to provide enough space for N items of some type. That's what 
> the 'Max_size_in_storage_elements' attribute should be good for. And 
> there's no fragmentation nor history of allocation/deallocation in my 
> case. If I specify I want space for 4 records, I should get space for 4 
> records. Not slightly less due to some hidden, unpredictable overhead.

There is another use for the attribute Max_Size_In_Storage_Elements.  That is to allow a dynamic allocation on the stack for an object whose size and subtype you may not know until run-time.  This can occur when receiving messages over a communications link or when reading from a loosely-defined file.  This type of thing, otherwise, is not good design and is questionable even in this case.

-- Eryndlia

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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-18 15:26   ` Vratislav Podzimek
  2016-10-18 16:03     ` Dmitry A. Kazakov
  2016-10-19 15:45     ` Eryndlia Mavourneen
@ 2016-10-19 15:53     ` Eryndlia Mavourneen
  2 siblings, 0 replies; 10+ messages in thread
From: Eryndlia Mavourneen @ 2016-10-19 15:53 UTC (permalink / raw)


On Tuesday, October 18, 2016 at 10:26:28 AM UTC-5, Vratislav Podzimek wrote:
> Well, then it's at least a bug in [Barnes] because there's an example 
> like the above ones just with a simpler type. But I still think the idea 
> here is/was to provide enough space for N items of some type. That's what 
> the 'Max_size_in_storage_elements' attribute should be good for. And 
> there's no fragmentation nor history of allocation/deallocation in my 
> case. If I specify I want space for 4 records, I should get space for 4 
> records. Not slightly less due to some hidden, unpredictable overhead.

There is another use for the attribute Max_Size_In_Storage_Elements.  That is to allow a dynamic allocation on the stack for an object whose size and subtype you may not know until run-time and for mapping using along with using the 'Address attribute for mapping these subtypes.  This can occur when receiving messages over a communications link or when reading from a loosely-defined file.  This type of thing, otherwise, is not good design and is questionable even in this case. 

-- Eryndlia

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

* Re: Bug in GNAT? - Max_size_in_storage_elements insufficient
  2016-10-19  1:39       ` Luke A. Guest
  2016-10-19  7:33         ` Dmitry A. Kazakov
@ 2016-10-20  0:59         ` Randy Brukardt
  1 sibling, 0 replies; 10+ messages in thread
From: Randy Brukardt @ 2016-10-20  0:59 UTC (permalink / raw)


"Luke A. Guest" <laguest@archeia.com> wrote in message 
news:647636100.498533813.258228.laguest-archeia.com@nntp.aioe.org...
> Dmitry A. Kazakov <mailbox@dmitry-kazakov.de> wrote:
>
>>> Well, then it's at least a bug in [Barnes] because there's an example
>>> like the above ones just with a simpler type. But I still think the idea
>>> here is/was to provide enough space for N items of some type.
>>
>> I am not sure if that were technically possible. Considering an
>> implementation of, for example, a marked-margins pool, the penalty to
>> have a guarantee would be extremely high.
>
> Surely that's what a static language can supply, the actual amount of 
> space
> required?

Depends on the implementation of the storage pool, of course. The amount of 
memory used by objects can be figured out at compile-time (assuming that the 
subtype is definite and there aren't any discriminant-dependent components - 
it's possible to declare such objects non-contiguously), but the pool will 
have some overhead.

Besides, that's irrelevant. S'Max_Storage_Size_in_Elements is not a static 
attribute and thus doesn't have to be calculatable at compile-time. The OP's 
example is legal because the value of Storage_Size doesn't have to be 
static, either. Of course, that means that whatever the OP is trying to do 
probably isn't going to happen here.

Turning to the OP's question:

I would never expect to be able say anything useful about the size of a task 
object - it's going to have to be allocated in pieces all over the memory 
map (there's limits on where the stack can be allocated, for instance). No 
attribute (Size, Object_Size, Max_Storage_Size_in_Elements) can have 
anything useful to say about non-contiguous objects.

Note: I've always interpreted Max_Storage_Size_in_Elements to apply to a 
single call to Allocate; there might be multiple calls to Allocate to 
allocate a single object (Janus/Ada works this way; there is a separate call 
to Allocate for each contiguous part of an object). Indeed, I wrote the 
definition of the attribute with this model in mind. Whether any other Ada 
lawyers would agree with me is unclear. :-)

                          Randy.





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

end of thread, other threads:[~2016-10-20  0:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-18 11:17 Bug in GNAT? - Max_size_in_storage_elements insufficient Vratislav Podzimek
2016-10-18 12:35 ` Dmitry A. Kazakov
2016-10-18 15:26   ` Vratislav Podzimek
2016-10-18 16:03     ` Dmitry A. Kazakov
2016-10-19  1:39       ` Luke A. Guest
2016-10-19  7:33         ` Dmitry A. Kazakov
2016-10-20  0:59         ` Randy Brukardt
2016-10-19 15:45     ` Eryndlia Mavourneen
2016-10-19 15:53     ` Eryndlia Mavourneen
2016-10-19 13:34 ` Egil H H

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