This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

assertion failure: A_invalidFree, how to log more info

Other Parts Discussed in Thread: SYSBIOS

TI Experts-

For this error:

ti.sysbios.heaps.HeapMem: line 337: assertion failure: A_invalidFree: Invalid free
xdc.runtime.Error.raise: terminating execution

how can we get SYSBIOS to add more info to the log, including PC ?  This is a customer location using server blades, JTAG is not an option.

Here are relevant sections of our .cfg file:

var LoggerSys = xdc.useModule('xdc.runtime.LoggerSys');
var SysMin = xdc.useModule('xdc.runtime.SysMin');

// 1 MB Buffer for Log in SDRAM
SysMin.bufSize = 1048576;
SysMin.sectionName = "SDRAM";

//Sysbios logs will be routed to logSysbiosFunc()
var System = xdc.useModule('xdc.runtime.System');   
System.SupportProxy = SysMin;
SysMin.outputFxn = "&logSysbiosFunc";

Agent.sysbiosTaskLogging = false;
Agent.sysbiosTaskLoggingRuntimeControl = false;
Agent.mainLogging = false;
Agent.mainLoggingRuntimeControl = false;
Load.hwiEnabled = true;
Load.swiEnabled = true;
BIOS.libType = BIOS.LibType_Custom;
BIOS.assertsEnabled = true;
BIOS.logsEnabled = true;
Load.windowInMs = 500;
Load.postUpdate = "&update_cpu_stats";
Task.numPriorities = 1;
Swi.numPriorities = 4;

//var MemoryProtect   = xdc.useModule('ti.sysbios.family.c64p.MemoryProtect');
var Exc = xdc.useModule('ti.sysbios.family.c64p.Exception');
//Exc.enableExternalMPC = true;
Exc.enablePrint = true;
//Exc.externalHook = '&ExceptionHook';

Thanks.

-Jeff
Signalogic

C6678, SYSBIOS 6.34.04.22, CGT 7.4.2

  • Hi Jeff,

    Are you just interested in finding how to change the output, or are you really concerned with this particular assertion?

    The assertion itself is coming from HeapMem_free() (in C:\ti\bios_6_34_04_22\packages\ti\sysbios\heaps\HeapMem.c):

    /*
    * Make sure the entire buffer is in the range of the heap.
    * Note the obj->head.size never changes
    */
    Assert_isTrue((((UArg)newHeader >= (UArg)(obj->buf)) &&
    ((UArg)newHeader + size <=
    (UArg)(obj->buf) + obj->head.size)),
    HeapMem_A_invalidFree)

    It is checking to make sure that the buffer being freed is completely within the boundaries of the memory managed by the heap. It may be good to double-check that the function is passed a valid address that was actually allocated from that heap.

    Best regards,
    Vincent
  • Vincent-

    Thanks for your reply.  Yes we found more or less where in our code we're making this call to HeapMem_free().

    I notice that HeapMem_free() (in HeapMem.c), does this:

      key = Gate_enterModule();

    and we have:

      HeapMem.common$.gate = GateSwi.create();

    in our .cfg file.  SYSBIOS is using the "Heap" section, and so is RTS malloc/free.  We have this task structure:

     Hwi
      |
    Clock function Swi (1 msec)
      |
      |__high priority Swi (posted each time)
      |
      |__low priority Swi (posted every 5 msec)

    We're calling HeapMem_alloc() and HeapMem_free() only in the high priority Swi, and we call RTS functions from all Swi's.  Is this ok ?  Is there a possibility that HeapMem_xx functions could be pre-empted and change the heap pointer list ?

    Also I'm thinking about adding some of the HeapMem.c source to our code, before we call HeapMem_free, so we can (i) know about the problem before raising the assertion, and (ii) poke around in mem and see if there is a corrupted area and if so what data got written there.

    Does that sound like a valid approach ?

    -Jeff

  • Hi Jeff,

    According the HeapMem documentation:

    "A HeapMem instance will use the HeapMem module Gate to protect any accesses to its list of free memory blocks. The HeapMem instance will enter and leave the module Gate when allocating blocks, freeing blocks, and retrieving statistics about the HeapMem. By default, the Gate is of type GateMutex. A different Gate can be specified using the common$.gate parameter. For example, to use a GateTask to protect HeapMem: HeapMem.common$.gate = GateTask.create(); To save on overhead, HeapMem does not create additional Gate instances on a per-instance basis; there is only one Gate instance shared across all of the HeapMem instances. Therefore, the HeapMem.common$.gateParams parameter (used for configuring per-instance Gates) is ignored. The type of Gate used should be chosen based on the type of threads (Hwi, Swi, Task, etc.) using the heap. It should also consider the non-deterministic nature of the HeapMem. A call to alloc or free will traverse a list of free blocks, so a GateHwi, for example, is likely an inappropriate Gate for HeapMem."

    So if you are calling HeapMem_* only from Swi's and Tasks, then using GateSwi is indeed be the correct setting to ensure different calls do not modify the free list at the same time.

    You can certainly try to add the HeapMem.c source to your code to instrument it, but maybe an easier way would be to use 'custom' build by switching it on in your .cfg file as described in this FAQ:

    During custom build, the SYSBIOS source files necessary for your application are automatically rebuilt when you build your application. So you can make your changes directly to <BIOS_INSTALL_DIR>\packages\ti\sysbios\heaps\HeapMem.c (after making a backup copy of the original of course).

    Best regards,

    Vincent

  • Vincent-

    Thanks for your reply and advice.  The custom build option sounds like an effective way to go.  We'll try that.

    -Jeff

  • Vincent-

    That does work, we are able to see the problem before the assertion is raised and log debug info.

    A couple of questions.

    1) Which HeapMem.c function creates the head of the buffer list ? If we print out &obj->xx values (e.g. &obj->buf, &obj->head), these are in onchip heap, so there must be a malloc happening, but whatever function is used that eventually maps into a malloc or Memory_alloc() is not clear.

    2) I've looked through HeapMem.c source but not deep into it. Can you say if the structure of the heap is something like

    head -> object -> buffers -> object

    or

    head -> object -> object -> buffers

    i.e. is the object list separate from the buffers ? We're trying to understand what might happen if code wrote past its buffers, if it might affect other buffers (that it doesn't own) or it might completely destroy the heap integrity.

    Thanks.

    -Jeff
  • Hi Jeff,

    Sorry for the delayed response while I was out of the office. Not sure if you have figured this out yet, so here are the answers:

    1. When a HeapMem object is created via HeapMem_create(), the HeapMem_Instance_init() function is called internally to initialize the object. That is where obj->head, obj->buf etc are initialized. The memory allocation of the object structure itself is performed by the XDC runtime prior to calling HeapMem_Instance_init(). Note that by default, BIOS creates a default heap (HeapMem) for you, so the HeapMem_create() call may have been implicitly made during BIOS initialization. Section 6.7 in the BIOS User Guide has more details on dynamic memory allocation.

    2. obj->head.next is initialized to obj->buf in HeapMem_restore() at the end of HeapMem_Instance_init(). As you can see in HeapMem_restore(), the first header, begHeader, is placed inside obj->buf, so the list itself (or the headers that the list consists of) 'lives' inside the heap buffer. So if the code wrote past its allocated buffers, it is certainly possible to inadvertently destroy the list and potentially overwrite other buffers that are located further down the heap (and also whatever comes after the heap).

    Best regards,
    Vincent
  • Vincent-

    Thanks for your reply. Yes this info was helpful, and contributed to a suite of internal memory diagnostics we used to finally figure out the underlying root cause -- a very low error rate / intermittent DDR3 mem problem on the board. The error rate is so low, the hardware manufacturer's stress test program could not detect the problem.

    -Jeff