The problem is that I have two threads. One thread only sets some request flags, and the other thread resets the request flags. Hence both threads have write access to the flags. I'm trying to do this without synchronization.
Here is what I've implemented, and I can't perceive how it might go wrong.
volatile uint32_t g_FORM_Requests;
#define FORM_REQUEST(X) \
do { \
if (g_FORM_Requests) \
{ \
g_SHELL_Print("Server is busy executing previous requests..."); \
} \
else \
{ \
g_FORM_Requests=(X); \
} \
} while (0x00U)
void * SERVER_Thread( void * Data)
{
uint32_t Snapshot;
while (!Done)
{
/* Take a snapshot of requests. */
Snapshot=g_FORM_Requests;
Execute(Snapshot);
g_FORM_Requests ^= Snapshot;
}
return (NULL);
}
The form issues requests to SERVER_Thread
by calling FORM_REQUEST(X)
macro. Each bit in g_FORM_Requests
is an execution request flag for a separate task. The execution order of these tasks does not matter.
Am I right in assuming that it would work correctly? If not, where is the problem?
EDIT 1:
The volatile
keyword makes sure that at the end of SERVER_Thread
the g_FORM_Requests
is read again before XORing it with Snapshot
. This means if FORM_REQUEST()
is interrupted in the middle of changing g_FORM_Requests
, it would not cause erroneous behavior, because only the bits that are set in Snapshot
will be removed from it.
The question is NOT if we can use volatile keyword as a barrier. I'm utilizing the fact that one of my threads only converts zeros to ones, and the other thread converts ones to zeros. Hence the g_FORM_Requests
variable itself acts as a lock, and partial execution of the Critical Section in each thread is not problematic...