Task synchronization and resource sharing

Hi. I have two tasks running, one that is altering a variable when an event comes and the other that is checking its value. in the second task where i have no delay or yield, i am seeing that the value of the variable doesn’t alter. Adding a vTaskDelay of 1-2 ms solves the problem. Can someone explain why this would happen? The following is a pseudo code but the concept illustrates the real problem.

#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>

/* Shared variable */
int sharedValue = 0;

/*-----------------------------------------------------------*/
/* Task that modifies the sharedValue every 10 ms */
void vModifierTask(void *pvParameters)
{
    (void)pvParameters;
    for (;;)
    {
        if (event == NETWORK_DATA_RECEIVED)
        {
            printf("Network data received\n");
            sharedValue = 5;
        }
        // sharedValue++;
        vTaskDelay(pdMS_TO_TICKS(10));  /* runs every 10 ms */
    }
}

/*-----------------------------------------------------------*/
/* Task that continuously checks sharedValue (no delay) */
void vCheckerTask(void *pvParameters)
{
    (void)pvParameters;
    for (;;)
    {
        /* Poll the value continuously */
        if (sharedValue > 0)
        {
            printf("sharedValue = %d\n", sharedValue);
        }
        /* No delay or yield here! */
    }
}

/*-----------------------------------------------------------*/
int main(void)
{
    /* Create both tasks at the same priority */
    xTaskCreate(vModifierTask, "Modifier", configMINIMAL_STACK_SIZE, NULL, 0, NULL);
    xTaskCreate(vCheckerTask,  "Checker",  configMINIMAL_STACK_SIZE, NULL, 0, NULL);

    /* Start the scheduler */
    vTaskStartScheduler();

    /* Should never reach here */
    for (;;);
    return 0;
}

Do you have configUSE_TIME_SLICING set to 1 ?
Otherwised the vModifierTask might not get the chance to run. Or better use a higher priority for this task.
You also have to use volatile int sharedValue = 0;. Otherwise the code might not work as expected most likely when compiling with optimization enabled.
Otherwise it’s undefined behaviour.
The same applies to your (also seemingly shared) event variable.

Using configMINIMAL_STACK_SIZE (128 ?) for your tasks which call pretty stack hungry printf or similar functions is a licence to cause a stack overflow. It’s probably too small.
See also FreeRTOS stack usage and stack overflow checking - FreeRTOS™

Thanks for your reply. Time slicing is set to 1, haven’t checked the volatile variable. Stack size is set to 256 but i deem it’s enough for this task.

Watch out for the stack needs of printf, it can be a hog.

The issue with not being volatile, is that under the “as if” rule for optimization, since the variable isn’t volatile, the function can assume that since nothing it does allows the variable to change, it can assume it doesn’t (the C language assumes as a base single-threaded behavior without the volatile tag) and so if it still has the value in its register, not need to load it.

As to not having even a yield, my “rules” say that ALL tasks must block or yield in their loop, and just yielding is only allowed for priority 0.

Note, adding the yield might make the code work even without the yield, as the compiler, unless it does full program global optimization, it won’t know that taskYield() doesn’t change that variable. It may know that printf doesn’t as that is part of the standard library.

But even if it makes it “work”, it is best to still use the volatile to force it.

Thanks for your reply.