Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

use va_list from another thread

I am working with FreeRTOS (newlib) on a small embedded system and have found that printf and family waste a tremendous amount of stack space. I have many tasks, and I do not have enough ram to make the stack for each large enough to support printf() calls. To work around this, I am working to create a "printf server" task that will have a large stack and do all printf()s on the behalf of other tasks.

So my question is, what is the proper way to transport the va_list to the other thread(task)? The example below produces garbage params.

A quick word about how this works: task_printf() will plop its parameters into static variables and then signal the server_task to perform the actual print. When the server_task is done, it signals the client to continue.

// printf parameters
static va_list static_args;
static const char *static_format;
static int static_result;


// printf server task.  Processes printf requests forever
void server_task(void *pvParameters)
{
    while(1)
    {
        xSemaphoreTake(printf_start, portMAX_DELAY);  // wait for start command
        static_result = vprintf(static_format, static_args);
        xSemaphoreGive(printf_finished);  // give finish signal
    }
}


// get server task to print something for us
int task_printf(const char *format, ...)
{
    int result;

    xSemaphoreTake(printf_mutex, portMAX_DELAY); // lock

    va_start(static_args, format);
    static_format = format;

    xSemaphoreGive(printf_start);  // give start signal
    xSemaphoreTake(printf_finished, portMAX_DELAY);  // wait for completion

    va_end(static_args);

    ...
}
like image 631
goertzenator Avatar asked Jul 20 '12 20:07

goertzenator


1 Answers

Well, the above actually works now. I messed up on semaphore initialization (not shown) which allowed the caller's stack to trash the args before the printf server could use them.

like image 141
goertzenator Avatar answered Oct 02 '22 23:10

goertzenator