* Memory Leak
@ 2006-01-03 16:15 markp
2006-01-03 18:06 ` Jeffrey R. Carter
0 siblings, 1 reply; 7+ messages in thread
From: markp @ 2006-01-03 16:15 UTC (permalink / raw)
We are experiencing a memory leak in out GNAT Ada program that we
cannot explain. We've narrowed it down to our generic queue package as
the culprit. However, all the memory in the package is allocated at
instantiation. I've attached the source code and if anybody can see
something, it would be greatly appreciated! The data types passed in
during the instantiation are variant records. Lastly, does GNAT provide
any queuing sevices?
Thank you.
generic
-------------------------------------------------------------------------
--
-- Generic Formal Parameters
--
-------------------------------------------------------------------------
-- The data type for the Message Queue
type Data_Type is private;
-- The number of entries in the Message Queue
Message_Queue_Depth : in Integer;
Queue_Name : string;
package Generic_Message_Queues is
-----------------------------------------------------------------------
--
-- Type Definitions
--
-----------------------------------------------------------------------
-- Specifies the Priority Urgency of a message when
-- a message is put into a Message Queue.
type Priority_Urgency_Type is (Normal, Urgent);
-- Indeces into both a high and low priority queue
type Item_Count is new integer range 0 .. Message_Queue_Depth;
type Item_Index is new integer range 1 .. Message_Queue_Depth;
type Item_Array is array (Item_Index) of Data_Type;
type Priority_Item_Count is new integer range 0 .. 10;
type Priority_Item_Index is new integer range 1 .. 10;
type Priority_Item_Array is array (Priority_Item_Index) of
Data_Type;
protected type Queue_Type is
-- put a data element into the buffer
entry Send(Elem : in Data_Type);
-- put a data element into the High Priority Queue
entry High_Priority_Send(Elem : in Data_Type);
-- retrieve a data element from the buffer
entry Receive(Elem: out Data_Type);
-- return Count of number of items
function Count return Integer;
-- Clear queue
procedure Flush;
private
Queue_Count : Item_Count := 0;
Out_Index : Item_Index := 1;
In_Index : Item_Index := 1;
Data : Item_Array;
Priority_Queue_Count : Priority_Item_Count := 0;
Priority_Out_Index : Priority_Item_Index := 1;
Priority_In_Index : Priority_Item_Index := 1;
Priority_Data : Priority_Item_Array;
end Queue_Type;
-- Clear queue
procedure Flush;
-- put a data element into the buffer
procedure Put(
Data : in Data_Type;
Priority_Urgency : in Priority_Urgency_Type := Normal);
-- retrieve a data element from the buffer
procedure Get(
Data : out Data_Type);
-- return Count of number of items
function Count return Integer;
end Generic_Message_Queues;
package body Generic_Message_Queues is
protected body Queue_Type is
-- put a data element into the buffer
entry Send(Elem: in Data_Type) when integer(Queue_Count) <
Message_Queue_Depth is
-- block until there is room in the Queue
begin
Data(In_Index) := Elem;
In_Index := In_Index mod Item_Index(Message_Queue_Depth) + 1;
Queue_Count := Queue_Count + 1;
end Send;
-- put a data element into the High Priority Queue
entry High_Priority_Send(Elem: Data_Type) when
integer(Priority_Queue_Count) < 10 is
-- block until there is room in the Queue
begin
Priority_Data(Priority_In_Index) := Elem;
Priority_In_Index := Priority_In_Index mod 10 + 1;
Priority_Queue_Count := Priority_Queue_Count + 1;
end High_Priority_Send;
-- retrieve a data element from the buffer
entry Receive(Elem: out Data_Type) when Queue_Count > 0 or else
Priority_Queue_Count > 0 is
-- block until there is something in the Queue
begin
if Priority_Queue_Count > 0 then
Elem := Priority_Data(Priority_Out_Index);
Priority_Out_Index := Priority_Out_Index mod 10 + 1;
Priority_Queue_Count := Priority_Queue_Count - 1;
else
Elem := Data(Out_Index);
Out_Index := Out_Index mod Item_Index(Message_Queue_Depth)
+ 1;
Queue_Count := Queue_Count - 1;
end if;
end Receive;
-- Clear queue
procedure Flush is
begin
Queue_Count := 0;
Out_Index := 1;
In_Index := 1;
Priority_Queue_Count := 0;
Priority_Out_Index := 1;
Priority_In_Index := 1;
end Flush;
-- return Count of number of items
function Count return Integer is
begin
return(integer(Queue_Count));
end Count;
end Queue_Type;
Queue : Queue_Type;
-- Clear queue
procedure Flush is
begin
Queue.Flush;
end Flush;
-- put a data element into the buffer
procedure Put(
Data : in Data_Type;
Priority_Urgency : in Priority_Urgency_Type := Normal) is
begin
if Priority_Urgency = Urgent then
Queue.High_Priority_Send(
Elem => Data);
else
Queue.Send(
Elem => Data);
end if;
end Put;
-- retrieve a data element from the buffer
procedure Get(
Data : out Data_Type) is
begin
Queue.Receive(Elem => Data);
end Get;
-- return Count of number of items
function Count return Integer is
begin
Return(Queue.Count);
end Count;
end Generic_Message_Queues;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Memory Leak
2006-01-03 16:15 Memory Leak markp
@ 2006-01-03 18:06 ` Jeffrey R. Carter
2006-01-03 18:57 ` markp
0 siblings, 1 reply; 7+ messages in thread
From: Jeffrey R. Carter @ 2006-01-03 18:06 UTC (permalink / raw)
markp wrote:
> We are experiencing a memory leak in out GNAT Ada program that we
> cannot explain. We've narrowed it down to our generic queue package as
> the culprit. However, all the memory in the package is allocated at
> instantiation. I've attached the source code and if anybody can see
> something, it would be greatly appreciated! The data types passed in
> during the instantiation are variant records. Lastly, does GNAT provide
> any queuing sevices?
This is a curious monster; it can't decide if it wants to be an ADT or an ASM,
and queues with negative depths seem to be meaningful. However, there is nothing
about it that would seem likely to cause a memory leak. It might have something
to do with where and how it is instantiated, or perhaps the types used to
instantiate it.
GNAT has GNAT.Bounded_Buffers, or you could use something from one of the many
fine libraries of Ada components available, like
PragmARC.Queue_Bounded_Blocking. They have more coherent designs and a better
grasp of the issues involved in Ada concurrency.
--
Jeff Carter
"Nobody expects the Spanish Inquisition!"
Monty Python's Flying Circus
22
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Memory Leak
2006-01-03 18:06 ` Jeffrey R. Carter
@ 2006-01-03 18:57 ` markp
2006-01-03 19:03 ` Martin Dowie
2006-01-03 19:05 ` markp
0 siblings, 2 replies; 7+ messages in thread
From: markp @ 2006-01-03 18:57 UTC (permalink / raw)
Jeff,
Thanks for the help. I tried the GNAT.Bounded_Buffers. It has the exact
same effect. I am not familiar with PragmARC.Queue_Bounded_Blocking.
How can I get my hands on the spec for that?
Thanks,
Mark
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Memory Leak
2006-01-03 18:57 ` markp
@ 2006-01-03 19:03 ` Martin Dowie
2006-01-03 19:05 ` markp
1 sibling, 0 replies; 7+ messages in thread
From: Martin Dowie @ 2006-01-03 19:03 UTC (permalink / raw)
markp wrote:
> Jeff,
>
> Thanks for the help. I tried the GNAT.Bounded_Buffers. It has the exact
> same effect. I am not familiar with PragmARC.Queue_Bounded_Blocking.
> How can I get my hands on the spec for that?
www.google.com
http://home.earthlink.net/~jrcarter010/pragmarc.htm
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Memory Leak
2006-01-03 18:57 ` markp
2006-01-03 19:03 ` Martin Dowie
@ 2006-01-03 19:05 ` markp
2006-01-04 4:46 ` Jeffrey R. Carter
2006-01-05 21:12 ` Ludovic Brenta
1 sibling, 2 replies; 7+ messages in thread
From: markp @ 2006-01-03 19:05 UTC (permalink / raw)
A couple of more things I should mention: I am running this under
Windows, not Linux. Also, I instantiate this queue package in a package
body that contains a task body. Here's how it's instantiated/used:
with Generic_Message_Queues; pragma Elaborate (Generic_Message_Queues);
with text_io;
with Ada.Exceptions;
package body Process_Data is
type Queue_Messages_Type is (
Small_Msg,
Large_Msg);
type Queue_Msg(Msg : Queue_Messages_Type := Small_Msg) is
record
case Msg is
when Small_Msg =>
Small_Msg_Data : Interface_Types.Small_Msg_Type;
when Large_Msg =>
Large_Msg_Data : Interface_Types.Large_Msg_Type;
end case;
end record;
-- Queue definition
package My_Queue is new Generic_Message_Queues(
Data_Type => Queue_Msg,
Message_Queue_Depth => 100,
Queue_Name => "Process Task Queue");
task Processing_Task is
entry Start;
pragma storage_size(12_048_000);
pragma priority(15);
end Processing_Task;
task body Processing_Task is
Queue_Data : Queue_Msg;
Small_Msg_Data : Interface_Types.Small_Msg_Type;
Large_Msg_Data : Interface_Types.Large_Msg_Type;
begin
loop
Accept Start;
loop
-- Pend for data on queue - this is a blocking call
My_Queue.Get(
Data => Queue_Data);
case Queue_Data.Msg is
when Small_Msg =>
Small_Msg_Data := Queue_Data.Small_Msg_Data;
text_io.put_line("Received Small Msg");
when Large_Msg =>
Large_Msg_Data := Queue_Data.Large_Msg_Data;
text_io.put_line("Received Large Msg");
end case;
end loop;
end loop;
exception
when Current_Exception : others =>
text_io.put_line("Unhandled
"&Ada.Exceptions.exception_information(
Current_Exception));
end Processing_Task;
procedure Start is
begin
Processing_Task.Start;
end Start;
procedure Process_Small_Msg(
Msg : in Interface_Types.Small_Msg_Type) is
begin
My_Queue.Put(
Data => (
Msg => Small_Msg,
Small_Msg_Data => Msg),
Priority_Urgency => My_Queue.Normal);
end Process_Small_Msg;
procedure Process_Large_Msg(
Msg : in Interface_Types.Large_Msg_Type) is
begin
My_Queue.Put(
Data => (
Msg => Large_Msg,
Large_Msg_Data => Msg),
Priority_Urgency => My_Queue.Normal);
end Process_Large_Msg;
end Process_Data;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Memory Leak
2006-01-03 19:05 ` markp
@ 2006-01-04 4:46 ` Jeffrey R. Carter
2006-01-05 21:12 ` Ludovic Brenta
1 sibling, 0 replies; 7+ messages in thread
From: Jeffrey R. Carter @ 2006-01-04 4:46 UTC (permalink / raw)
I see that Dowie beat me to telling you where to find the PragmAda Reusable
Components.
markp wrote:
> type Queue_Messages_Type is (
> Small_Msg,
> Large_Msg);
>
> type Queue_Msg(Msg : Queue_Messages_Type := Small_Msg) is
> record
> case Msg is
> when Small_Msg =>
> Small_Msg_Data : Interface_Types.Small_Msg_Type;
> when Large_Msg =>
> Large_Msg_Data : Interface_Types.Large_Msg_Type;
> end case;
> end record;
Still nothing obvious. What are the definitions of (Small|Large)_Msg_Type,
including all definitions they depend on?
--
Jeff Carter
"C's solution to this [variable-sized arrays] has real problems,
and people who are complaining about safety definitely have a point."
Dennis Ritchie
25
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Memory Leak
2006-01-03 19:05 ` markp
2006-01-04 4:46 ` Jeffrey R. Carter
@ 2006-01-05 21:12 ` Ludovic Brenta
1 sibling, 0 replies; 7+ messages in thread
From: Ludovic Brenta @ 2006-01-05 21:12 UTC (permalink / raw)
"markp" <markwork66@yahoo.com> writes:
> A couple of more things I should mention: I am running this under
> Windows, not Linux.
I like it when people start assuming Linux is the rule and Windows the
exception :)
Sorry, I have no advice to offer. Just chuckling.
--
Ludovic Brenta.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2006-01-05 21:12 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-01-03 16:15 Memory Leak markp
2006-01-03 18:06 ` Jeffrey R. Carter
2006-01-03 18:57 ` markp
2006-01-03 19:03 ` Martin Dowie
2006-01-03 19:05 ` markp
2006-01-04 4:46 ` Jeffrey R. Carter
2006-01-05 21:12 ` Ludovic Brenta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox