#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
static int sharedCounter = 0;
SemaphoreHandle_t mutex; // mutex for protecting sharedCounter (not used in flawed code)
void incrementTask1(void *pvParameters) {
for (int i = 0; i < 100; ++i) {
// Reading and updating sharedCounter without lock (not atomic)
int temp = sharedCounter;
// Simulate some work where context switch could happen
vTaskDelay(pdMS_TO_TICKS(1));
temp = temp + 1;
sharedCounter = temp; // write back updated value
// If a context switch happened, Task2 might have updated sharedCounter in the meantime,
// causing Task1 to overwrite Task2's increment (lost update).
// xSemaphoreTake(mutex, portMAX_DELAY);
// sharedCounter++; // **Fix:** perform update while holding mutex
// xSemaphoreGive(mutex);
}
printf("Task1 final counter value: %d\n", sharedCounter);
vTaskDelete(NULL);
}
void incrementTask2(void *pvParameters) {
for (int i = 0; i < 100; ++i) {
int temp = sharedCounter;
vTaskDelay(pdMS_TO_TICKS(1));
temp = temp - 1;
sharedCounter = temp;
// xSemaphoreTake(mutex, portMAX_DELAY);
// sharedCounter++;
// xSemaphoreGive(mutex);
}
printf("Task2 final counter value: %d\n", sharedCounter);
vTaskDelete(NULL);
}
void app_main() {
// Create a mutex (not used in the flawed version of code)
mutex = xSemaphoreCreateMutex();
// Create two tasks of equal priority that both increment the shared counter
xTaskCreate(incrementTask1, "IncTask1", 2048, NULL, 1, NULL);
xTaskCreate(incrementTask2, "IncTask2", 2048, NULL, 1, NULL);
// Both tasks will run and then delete themselves after completing 100 increments each.
vTaskDelay(pdMS_TO_TICKS(500)); // wait for tasks to finish
printf("Expected final counter value = 200, Actual final counter value = %d\n", sharedCounter);
// (Due to race condition, actual value will likely be less than 200 because of lost updates)
vTaskDelete(NULL);
}