I am looking to generate random values for 3 threads running in a freeRTOS environment. Knowing that rand() is not thread-safe I use a mutex to protect it. In addition, I call srand() only once. What should I consider when trying to solve this issue?
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "sensorDriver.h"
SemaphoreHandle_t semaphoreMutexDriver;
uint16_t sensorValue;
void sensorDriver_initialize()
{
srand(time(NULL));
semaphoreMutexDriver = xSemaphoreCreateMutex();
}
void getValue()
{
if (xSemaphoreTake(semaphoreMutexDriver, portMAX_DELAY))
{
sensorValue = (uint16_t)(rand() % 50);
xSemaphoreGive(semaphoreMutexDriver);
}
}
uint16_t sensorDriver_getValue()
{
getValue();
return sensorValue;
}
More code can be added upon request.
UPDATE 1
Tried making the sensorValue local to the function, like that:
uint16_t firstSensorDriver_getValue()
{
if (xSemaphoreTake(semaphoreMutexDriver, portMAX_DELAY))
{
uint16_t sensorValue = (uint16_t)(rand() % 50);
xSemaphoreGive(semaphoreMutexDriver);
return sensorValue;
}
}
Did not do the trick (if better suggestions implementation wise, please do not hesitate), also the thread puts the value into a struct after getting it, not sure if this helps. (each thread in its own struct).
UPDATE 2
Here is the struct and how the value is saved:
struct firstSensor
{
uint16_t firstSensorValue;
EventGroupHandle_t meassureEventGroup;
EventGroupHandle_t dataReadyEventGroup;
};
void firstSensor_fetchSensorValue(FirstSensor self)
{
self->firstSensorValue = sensorDriver_getValue();
}
UPDATE 3
Here is an example of the first and second thread/struct implementation
#ifndef FIRSTSENSOR_H
#define FIRSTSENSOR_H
typedef struct firstSensor* FirstSensor;
FirstSensor firstSensor_create(UBaseType_t taskPriority, EventGroupHandle_t
eventGroupMeassure, EventGroupHandle_t eventGroupDataReady);
uint16_t firstSensor_getSensorValue(FirstSensor self);
void firstSensor_destroySensor(FirstSensor self);
#endif
and similarly second thread header and source file
#ifndef SECONDSENSOR_H
#define SECONDSENSOR_H
typedef struct secondSensor* SecondSensor;
SecondSensor secondSensor_create(UBaseType_t taskPriority, EventGroupHandle_t
eventGroupMeassure, EventGroupHandle_t eventGroupDataReady);
uint16_t secondSensor_getSensorValue(SecondSensor self);
void secondSensor_destroySensor(SecondSensor self);
#endif
And implementation
struct secondSensor
{
uint16_t secondSensorValue;
EventGroupHandle_t meassureEventGroup;
EventGroupHandle_t dataReadyEventGroup;
};
void secondSensor_fetchSensorValue(SecondSensor self)
{
self->secondSensorValue = firstSensorDriver_getValue();
}
void secondSensor_task(void* instance)
{
EventBits_t eventBitsMeasure;
SecondSensor self = (SecondSensor*)instance;
for (;;)
{
eventBitsMeasure = xEventGroupWaitBits(self->meassureEventGroup, BIT_SECOND_SENSOR, pdTRUE, pdTRUE, portMAX_DELAY);
if ((eventBitsMeasure & BIT_SECOND_SENSOR) == BIT_SECOND_SENSOR)
{
secondSensor_fetchSensorValue(self);
xEventGroupSetBits(self->dataReadyEventGroup, BIT_SECOND_SENSOR);
}
}
}
UPDATE 4
Well technically they are random for each emm, run so to say, but they are same within the same run. Picture below on the left is what my small program is printing on the right simple random print.
UPDATE 5
Another weird thing is that everytime I run the code I get the same sequence of numbers as if stand is never called (even though it is), even if I seed the srand() with time(NULL) + clock() which should be different everytime. Maybe it can help...