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.

Bug in the TivaWare implementation of sys_arch.c for LwIP??

Other Parts Discussed in Thread: TM4C129ENCPDT

While working on an implementation of FreeRTOS with LwIP on a TI TM4C129ENCPDT processor, I've come across the sys_sem_new() and sys_sem_free() functions that are implemented by TI in the sys_arch.c file used in LwIP as part of TivaWare. These two functions are basically used for creating and destroying semaphores, but there seems to be a bug in the implementation so that semaphores are not actually cleared when calling sys_sem_free().

Consider the following code copied and pasted from TI's implementation of sys_arch.c <TivaWare>\third_party\lwip-1.4.1\ports\tiva-tm4c129\sys_arch.c


/* An array to hold the memory for the available semaphores. */ static sem_t sems[SYS_SEM_MAX]; /** * Initializes the system architecture layer. * */ void sys_init(void) { u32_t i; /* Clear out the semaphores. */ for(i = 0; i < SYS_SEM_MAX; i++) { sems[i].queue = 0; } } /** * Creates a new semaphore. * * @param count is non-zero if the semaphore should be acquired initially. * @return the handle of the created semaphore. */ err_t sys_sem_new(sys_sem_t *sem, u8_t count) { void *temp; u32_t i; /* Find a semaphore that is not in use. */ for(i = 0; i < SYS_SEM_MAX; i++) { if(*(*int)sems[i].queue == 0) { break; } } if(i == SYS_SEM_MAX) { #if SYS_STATS STATS_INC(sys.sem.err); #endif /* SYS_STATS */ return ERR_MEM; } /* Create a single-entry queue to act as a semaphore. */ #if RTOS_FREERTOS sem->queue = xQueueCreate(1, sizeof(void *)); if(sem->queue == NULL) { #endif /* RTOS_FREERTOS */ #if SYS_STATS STATS_INC(sys.sem.err); #endif /* SYS_STATS */ return ERR_MEM; } /* Acquired the semaphore if necessary. */ if(count == 0) { temp = 0; xQueueSend(sem->queue, &temp, 0); } /* Update the semaphore statistics. */ #if SYS_STATS STATS_INC(sys.sem.used); #if LWIP_STATS if(lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) { lwip_stats.sys.sem.max = lwip_stats.sys.sem.used; } #endif #endif /* SYS_STATS */ /* Save the queue handle. */ sems[i].queue = sem->queue; /* Return this semaphore. */ return (ERR_OK); } /** * Destroys a semaphore. * * @param sem is the semaphore to be destroyed. */ void sys_sem_free(sys_sem_t *sem) { /* Clear the queue handle. */ sem->queue = 0; /* Update the semaphore statistics. */ #if SYS_STATS STATS_DEC(sys.sem.used); #endif /* SYS_STATS */ }

It appears to me that the code in sys_sem_free() does nothing to clear the value set in the global sems array that is being checked and set when creating a new semaphore with sys_sem_new().

In my project, this quickly results in a condition where the sys_sem_new() function returns ERR_MEM because SYS_SEM_MAX has been reached, and no new semaphores can be allocated.

Please note that even if I set SYS_SEM_MAX to a very high number, I am still unable to clear semaphores, and will eventually be unable to create new semaphores.

It seems that the same create and destroy functionality is used for mailboxes in the same file, and so I would expect a similar problem here, but have not yet experienced it myself.

Is this a bug in TI's implementation of the sys_arc.c file, or am I missing something??

FYI: I'm using TivaWare version 2.1.0.12573 which includes the newest version of LwIP (version 1.4.1).

  • Hello Simon

    Sai from TI just posted the patch on this thread...

    http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/374100.aspx

    Regards

    Amit

  • I think the referenced thread deals with netif.c, not sys_arch.c. Sys_arch is still wrong.

    Please read the sys_arch.txt for needed implementation and roll your own. I just started to implement freertos/lwip for TM4C and quick look at sys_arch.c tells me that it can not be used. The implementation is rather interesting. Deleting the mailbox/semaphore is clear bug, dealing with stack task while creating a task is also a bit strange, I must say...

    For deleting sems/mbox:
    https://code.google.com/p/stream-radio-v3/source/browse/trunk/TCPv3/lwip-1.4.0/port/FreeRTOS/arch/sys_arch.c?r=5

    But dont copy it otherwise. It has some other interesting features.

    So take the tiva-tmc129.c from the suggested thread and roll your own sys_arch.c (and check freertos examples from freertos package, they might have better solution, I will check it too) and skip anything else related to lwip from tivaware. It is a bit same thing than with stellarisware, usable for small howto example, but has to be rewritten for more serious stuff.

    BR, Madis
  • Hello Madis,

    I have asked Sai to look into this as well. All further updates will come from him

    Regards
    Amit
  • Hi,

    I have a same problem now.

    As the semaphore reaches the "SYS_SEM_MAX", fail to create netconn.

    So I added vQueueDelete(sem->queue) in sys_sem_free() but it still gives me a same error.

    How could you solve this?

    Jin

  • Hi, Simon,
    i have find the same problem when ebable LWIP_SOCKET . after my analysis, the cause lies in the sys_sem_free and sys_sem_new.
    after the sys_sem_new() allocate a new queue, we use sys_sem_free to deallocate it, the problem comes out, the sems[SYS_SEM_MAX ] is global, but the sys_sem_free() won't do anything about this global variable sems[SYS_SEM_MAX ], so it won't be freed, even we add "sem->queue = 0".
    so any time we use a sem, the sems[SYS_SEM_MAX ] will consume once, when we reached SYS_SEM_MAX , we will never able to use semaphore again.
    i don't familiar with freertos, so, are we wrong about it?
  • Hi Rubin, it seem's that you have stumbled upon the same bug that I mentioned in my original post.

    I worked around the problem by using the lwIP sysarch implementation found in this .zip file attached to this post on the FreeRTOS Community Contributions forum in stead of the standard implementation found in TivaWare.

    Regards,
    Simon

  • HI Simon,

    I have asked LWIP forum, FreeRTOS, and TI but I have not got any proper responses yet.

    My application communicates with Unix using socket every 1sec and reaches to SYS_SEM_MAX without freeing the semaphore.

    I added index into sem_t and mobx_t to make sure the global sems[] is erased, but it didn't seem to work.

    I need to take a look at it,but I hope it resolve the problems!!

    Thank you for letting me know the source!

    Jin

  • HI Simon,

    Unlike sys_arch.c in TM4C1294, the sys_arch in the zip file does not use SYS_SEM_MAX and SYS_MBOX_MAX. It does not use arrays to hold them globally.

    I wonder do you keep the global arrays or just use single entry?

    Jin
  • Hi Jin,

    Since the implementation that I am using does not limit the number of semaphores in use (at least not by software), I'm not using any global arrays to keep track of my semaphores. This means I don't need the constants SYS_SEM_MAX and SYS_MBOX_MAX defined in the TivaWare implementation.

    Regards,
    Simon

  • Hi Simon,

    What I changed is sys_arch.c and sys_arch.n which were implemented in .zip.  The example codes just use a single entry semaphore rather than put it into a global array, so definitely it is not confined by any size of arrays. It runs ok for 1~2 minutes,but it stops working since sys_sem_new() is unable to create a new semaphore by calling vSemaphoreCreateBinary() which keeps increasing the address of memory every time it is called. If the address of semaphore is reused after calling sys_sem_free(), it could run forever. But vSemaphoreCreateBinary() just keeps increasing the address so it eventually hits the max of the allowable memory.

    Have you encountered this problem?

  • Hi Simon
    i think i have solved the problem, by modify the sys_arch.c(function sys_mbox_free() and sys_sem_free()). after several day's test, it works well.
    the root cause is these 2 function, i add some code to it. as below.
    in the code that add, i check and free the correspond global semaphore and mbox, it seems to be ok now.

    /**
    * Destroys a semaphore.
    *
    * @param sem is the semaphore to be destroyed.
    */
    void
    sys_sem_free(sys_sem_t *sem)
    {
    // add by lihuibin
    u32_t i;
    /* Find a semaphore that is not in use. */
    for(i = 0; i < SYS_SEM_MAX; i++) {
    if(sems[i].queue == sem->queue) {
    sems[i].queue = 0;
    break;
    }
    }
    vQueueDelete(sem->queue);
    if(i == SYS_SEM_MAX) {
    return ;
    }
    // end

    /* Clear the queue handle. */
    sem->queue = 0;

    /* Update the semaphore statistics. */
    #if SYS_STATS
    STATS_DEC(sys.sem.used);
    #endif /* SYS_STATS */
    }

    void
    sys_mbox_free(sys_mbox_t *mbox)
    {
    u32_t i;
    /* There should not be any messages waiting (if there are it is a bug). If
    any are waiting, increment the mailbox error count. */
    #if RTOS_FREERTOS
    if(uxQueueMessagesWaiting(mbox->queue) != 0) {
    #endif /* RTOS_FREERTOS */

    #if SYS_STATS
    STATS_INC(sys.mbox.err);
    #endif /* SYS_STATS */
    }

    // add by lihuibin
    /* Find a mailbox that is not in use. */
    for(i = 0; i < SYS_MBOX_MAX; i++) {
    if(mboxes[i].queue == mbox->queue) {
    mboxes[i].queue = 0;
    break;
    }
    }
    vQueueDelete(mbox->queue);
    if(i == SYS_MBOX_MAX) {
    return ;
    }
    // end

    /* Clear the queue handle. */
    mbox->queue = 0;

    /* Update the mailbox statistics. */
    #if SYS_STATS
    STATS_DEC(sys.mbox.used);
    #endif /* SYS_STATS */
    }
  • Hi Rubin,

    I have tested but it eventually stop working due to running out of heap I guess. Actually this happens in the example codes linked by Simon as well.

    What I tried in a task running at every second is:

    while(1)

    {

    1. lwip_socket--> calls sys_sem_new() and sys_mbox_new()

    2. lwip_bind

    3. lwip_sendto ( To server)

    4. lwip_recvfrom

    5. lwip_close --> calls sys_sem_free() and sys_mbox_free()

    }

    Every time lwip_socket() is called, it ends up getting to sys_sem_new() and sys_mbox_new().

    Both functions call xQueueCreate() which allocates a new queue, but this function keeps increasing the address of memory of xQueueHandle although the allocated queue is freed by sys_sem_free() and sys_mbox_free() then fail to allocate a new one. ex: start with address at 20002340--> keep increasing around 2000ffxx.

     I wonder how you have tested it.

  • Hi!

    Once you have fixed the TI implementation of sys_arch.c and still have issues I recommend you try to cut the problem into smaller parts.

    Try to exercise the FreeRTOS to get an idea how things should work. Something like:

    while(1){
    Create semaphore
    Delete semaphore
    }

    and see, if the memory is still leaking. If so, add taskYield() or taskDelay() to the loop. Im not sure at what point RTOS is really freeing the heap. If you get this test working it should be easier to figure out whats wrong with the rest of the project.

    BR, Madis
  • Hi Jin
    i am doing a full test. i was concentrate on the freeing of global sems[], the code i add did free it, but didn't notice the xQueueHandle, i will check about the memory of xQueueHandle.
  • Hi, Simon,
    Have u solved the problem we talked about, did u succeed by using the 9b92's sys_arch.c  implemention?