I've tried several ways to synch the following scenario. The last way I tried is to use an event to signal after FifoQueueData();. Thread 2 would then release from the event and send the data over the network. The problem is that thread 1 loops around too fast and signals the event before Thread 2 waits on that same event. This causes the event to wait until it times out.
thread1 {
for(1 .. 10) {
GenerateData();
FifoQueueData();
}
signal();
}
thread2 {
while(not signalled) {
WaitForQueuedData();
FifoDequeueData();
SendDataOverNetwork();
}
}
Because you are on Windows, you could indeed use the thread message queue for synchronization (this particular queue is threadsafe, maybe message queues are what Olaf means by "normally"). To do that, use GetMessage and PostThreadMessage.
Be aware, however, that message queues are accessible from other code -- for type safety, you might put objects in your own queue, and use the thread message queue only for waking the other thread. (To see why this is important, read about "window shatter attacks"). In that case, you might as well just be using auto-reset events.
The last way I tried is to use an event to signal after FifoQueueData();. Thread 2 would then release from the event and send the data over the network. The problem is that thread 1 loops around too fast and signals the event before Thread 2 waits on that same event. This causes the event to wait until it times out.
If you are going to use events, use 2 manual-reset events and a thread-safe lock, like a critical section. One event signals when the queue has space available, and one event signals when the queue has data. Thread1 would wait for the Available event to be signaled, lock the queue, put data into it, set the Data event, and reset the Available event if the queue is full, before finally unlocking the queue. Thread2 would wait for the Data event, lock the queue, dequeue an item, set the Available event, and reset the Data event if the queue is empty, before finally unlocking the queue and processing the item.
CRITICAL_SECTION csQueue;
HANDLE hAvailableEvent, hDataEvent;
BOOL bFinished;
...
InitializeCriticalSection(&csQueue);
hAvailableEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
hDataEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
bFinished = FALSE;
...
void FifoQueueData(BOOL IsFinished)
{
WaitForSingleObject(hAvailableEvent, INFINITE);
EnterCriticalSection(&csQueuelock);
if (IsFinished)
bFinished = TRUE;
else
{
// put data in the queue
if (queue is full)
ResetEvent(hAvailableEvent);
}
SetEvent(hDataEvent);
LeaveCriticalSection(&csQueuelock);
}
BOOL FifoDequeueData()
{
WaitForSingleObject(hDataEvent, INFINITE);
EnterCriticalSection(&csQueuelock);
if ((queue is empty) && (bFinished))
{
LeaveCriticalSection(&csQueuelock);
return FALSE;
}
// remove data from the queue
SetEvent(hAvailableEvent);
if (queue is empty)
ResetEvent(hDataEvent);
LeaveCriticalSection(&csQueuelock);
}
thread1
{
bFinished = FALSE;
for(1 .. 10)
{
GenerateData();
FifoQueueData(FALSE);
}
FifoQueueData(TRUE);
}
thread2
{
while (FifoDequeueData())
SendDataOverNetwork();
}
Another option is to use an I/O Completion Port. Call CreateIoCompletionPort() before starting the threads, then have Thread1 queue data using PostQueuedCompletionStatus() and Thread2 dequeue data using GetQueuedCompletionStatus(). IOCP uses a FIFO queue and is self-syncing.
HANDLE hQueue;
...
hQueue = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
...
void FifoQueueData(BOOL IsFinished)
{
if (IsFinished)
PostQueuedCompletionStatus(hQueue, 0, 1, NULL);
else
{
LPBYTE buffer = LocalAlloc(LMEM_FIXED, size of data);
if (buffer)
{
// copy data into buffer...
if (!PostQueuedCompletionStatus(hQueue, size of data, 0, (LPOVERLAPPED)buffer))
LocalFree(buffer);
}
}
}
BOOL FifoDequeueData()
{
DWORD dwSize = 0;
ULONG_PTR ulCompletionKey = 0;
LPBYTE buffer;
if (!GetQueuedCompletionStatus(hQueue, &dwSize, &ulCompletionKey, (LPOVERLAPPED*)&buffer, INFINITE))
return FALSE;
if (ulCompletionKey == 1)
return FALSE;
// copy data from buffer up to dwSize bytes as needed...
LocalFree(buffer);
return TRUE;
}
thread1
{
for(1 .. 10)
{
GenerateData();
FifoQueueData(FALSE);
}
FifoQueueData(TRUE);
}
thread2
{
while (FifoDequeueData())
SendDataOverNetwork();
}
Related
Hello everyone im doing my first steps with RTOS. Im trying to receive an amount of data using UART in an interrupt mode. I have a Display Task where the commands are being written to a global buffer, and i just created a UART Handler Task where i want to read the bytes. The problems im facing are.
The semaphore i use inside the UART Task is unknown, even though i declared it global in the main function, so the xSemaphoreTake() function has errors there. Maybe a helpful Note: the UART Task is in a seperated file.
Is my implemntation of the HAL_UART_RxCpltCallback and the UART Task clean?
here is the code i wrote:
SemaphoreHandle_t uartInterruptSemaphore = NULL;
int main(void)
{
/* USER CODE BEGIN 1 */
void mainTask(void* param) {
uartInterruptSemaphore = xSemaphoreCreateBinary();
if(uartInterruptSemaphore != NULL) {
// Display Thread with a 2 priority
xTaskCreate(&displayTask, "Display Thread", 1000, &huart4, 2, NULL);
// deferred Interrupt to be synchronized with the Display Task, must have a higher priority than the display task
xTaskCreate(&UartHandlerTask, "UART Handler Task", 1000, &huart4, 3, NULL);
}
for(;;){
}
}
the callback function i wrote:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *uart_cb) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if(uart_cb->Instance == USART4) {
xSemaphoreGiveFromISR(uartInterruptSemaphore, &xHigherPriorityTaskWoken);
}
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
and the handler task:
void UartHandlerTask(void* param) {
huart_cache = param;
const uint8_t tmp = rx_byte; //rx byte is global volatile variable
for(;;){
if(xSemaphoreTake(uartInterruptSemaphore, portMAX_DELAY) == pdPASS) {
HAL_UART_Receive_IT((UART_HandleTypeDef *)huart_cache, (uint8_t *)&rx_byte, 1);
// write data to the buffer
RX_interrupt(tmp);
}
}
}
I would recommend getting a better handle on C before trying to use an RTOS. This will also show you a better way of unblocking a task form an interrupt than using a binary semaphore: https://www.freertos.org/2020/09/decrease-ram-footprint-and-accelerate-execution-with-freertos-notifications.html
I have an interactive Win32 application and at some point I need to launch another application and wait until that other application has finished. During the time the other application runs, the interactive application shouldn't be responsive expect for resizing and moving the window (this implies of course that the interactive application still should continue redrawing).
My current approach is this:
Create a Thread T
Disable the main window (with EnableWindow(handle, FALSE))
Continue message loop
Special WM_APP message sent from thread T will enable the main window again (EnableWindow(handle, TRUE));
Thread T:
launch the application with CreateProcess
wait until application has terminated using WaitForSingleObject
post a special WM_APP message to the main window using PostMessage.
thread terminates here
This works fine, but I'm not sure if this is the correct approach.
Is there a better approach or should I continue like this?
Your approach is fine, just make sure to use PostMessage() for
send a special WM_APP message to the main window
to avoid deadlock if the main thread happens to wait for thread T.
As commenter noted, an alternative for creating a thread is to use a message loop with MsgWaitForMultipleObjectsEx.
The advantages I see:
There is no additional thread required, so there will be no worries about thread-related problems such as race conditions and deadlocks. These problems are often hard to find and debug (typically they only happen on customer machines), so I try to avoid threads as much as possible.
The program flow for creating the process and waiting for it is simpler. It can be sequential instead of event-based like the thread solution.
You have to judge for yourself if this is a better approach for your scenario.
A function that can be used to wait for a process (or any other waitable handle) while processing messages could be as follows. It's implementation is pretty involved (for background info see the links at the end of my answer) but usage is quite easy (see example afterwards).
// Function to process messages until the state of any of the given objects is signaled,
// the timeout is reached or a WM_QUIT message is received.
// Parameter hDialog can be nullptr, if there is no dialog.
//
// Returns ERROR_SUCCESS if any of the given handles is signaled.
// Returns ERROR_TIMEOUT in case of timeout.
// Returns ERROR_CANCELLED if the WM_QUIT message has been received.
// Returns the value of GetLastError() if MsgWaitForMultipleObjectsEx() fails.
DWORD WaitForObjectsWithMsgLoop(
HWND hDialog, const std::vector<HANDLE>& handles, DWORD timeOutMillis = INFINITE )
{
if( handles.empty() )
return ERROR_INVALID_PARAMETER;
DWORD handleCount = static_cast<DWORD>( handles.size() );
DWORD startTime = GetTickCount();
DWORD duration = 0;
do
{
DWORD status = MsgWaitForMultipleObjectsEx(
handleCount, handles.data(),
timeOutMillis - duration,
QS_ALLINPUT,
MWMO_INPUTAVAILABLE );
if( status == WAIT_FAILED )
{
// MsgWaitForMultipleObjectsEx() has failed.
return GetLastError();
}
else if( status >= WAIT_OBJECT_0 && status < WAIT_OBJECT_0 + handleCount )
{
// Any of the handles is signaled.
return ERROR_SUCCESS;
}
else if( status == WAIT_OBJECT_0 + handleCount )
{
// New input is available, process it.
MSG msg;
while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
if( msg.message == WM_QUIT )
{
// End the message loop because of quit message.
PostQuitMessage( static_cast<int>( msg.wParam ) );
return ERROR_CANCELLED;
}
// Enable message filter hooks (that's what the system does in it's message loops).
// You may use a custom code >= MSGF_USER.
// https://blogs.msdn.microsoft.com/oldnewthing/20050428-00/?p=35753
if( ! CallMsgFilter( &msg, MSGF_USER ) )
{
// Optionally process dialog messages.
if( ! hDialog || ! IsDialogMessage( hDialog, &msg ) )
{
// Standard message processing.
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
}
duration = GetTickCount() - startTime;
}
while( duration < timeOutMillis );
// Timeout reached.
return ERROR_TIMEOUT;
}
The function could be used in a dialog box procedure as follows. Error handling omitted for brevity.
INT_PTR CALLBACK YourDialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
static bool s_childProcessRunning = false;
switch( message )
{
case YourMessageToLaunchProcess:
{
// prevent reentrancy in case the process is already running
if( s_childProcessRunning )
{
MessageBoxW( hDlg, L"Process already running", L"Error", MB_ICONERROR );
return TRUE;
}
// Prepare CreateProcess() arguments
STARTUPINFO si{ sizeof(si) };
PROCESS_INFORMATION pi{};
wchar_t command[] = L"notepad.exe"; // string must be writable!
// Launch the process
if( CreateProcessW( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) )
{
// Set flag to prevent reentrancy.
s_childProcessRunning = true;
// Wait until the child process exits while processing messages
// to keep the window responsive.
DWORD waitRes = WaitForObjectsWithMsgLoop( hDlg, { pi.hProcess } );
// TODO: Check waitRes for error
s_childProcessRunning = false;
// Cleanup
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
return TRUE;
}
// more message handlers...
}
return FALSE;
}
Obligatory Old New Thing links:
Pumping messages while waiting for a period of time
The dialog manager, part 4: The dialog loop
Rescuing thread messages from modal loops via message filters
I am trying to implement a mutex in c using the fetch and increment algorithm (sort of like the bakery algorithm). I have implemented the fetch and add part atomically. I have every thread obtain a ticket number and wait for their number to be "displayed". However, I have not found a way to tackle the issue of waiting for your ticket to be displayed. I have thought of using a queue to store your thread ID and descheudle/yield yourself until someone who has the lock, wakes you up. However, I would need a lock for the queue as well! :(
Are there any recommendations on what I could do to make the queue insertion safe or perhaps a different approach to using a queue?
Here is some code of my initial implementation:
void mutex_lock( mutex_t *mp ) {
while (compareAndSwap(&(mp->guard), 0, 1) == 1) {
// This will loop for a short period of time, Need to change this <--
}
if ( mp->lock == 1 ) {
queue_elem_t elem;
elem.data.tid = gettid();
enq( &(mp->queue), &(elem) );
mp->guard = 0;
deschedule();
}
else {
mp->lock = 1; // Lock the mutex
mp->guard = 0; // Allow others to enq themselves
}
}
Also, lets for now ignore the potential race condition where someone can call make_runnable before you call deschedule, I can write another system call that will say we are about to deschedule so queue make_runnable calls.
I have an issue in my use of critical sections. My app has a large number of threads, say 60, which all need access to a global resource. I therefore protect that resource with a critical section. This works perfectly during operation, however when my application shuts down, I trigger the threads to quit, and then destroy the critical section.
The problem comes if some of those threads are waiting on the critical section at exit time, and thus are blocked from quitting themselves.
I've written a wrapper around the windows CriticalSection calls that has an 'Initialised' flag, which I set to true when the crit is created, and set to false when I'm about to leave the crit (both cases are set when inside the crit). This flag is checked before the 'enter crit' wrapper function tries entering the crit, bypassing the request if the flag is false. The flag is also checked the moment any thread successfully enters the crit, making it immediately leave the crit if it's false.
What I to do prior to deleting the crit is set the flag to false, then wait for any waiting threads to: be allowed into the crit; see the Initialised flag is false; then leave the crit (which should be a pretty quick operating for each thread).
I check the number of threads waiting for access to the crit by checking the LockCount inside the CRITICAL_SECTION struct, and waiting until it hits 0 (in XP, that's LockCount - (RecursionCount-1); in 2003 server and above, the lock count is ((-1) - (LockCount)) >> 2), before I then destroy the critical section.
This should be sufficient, however I'm finding that the LockCount reaches 0 when there's still one thread (always just one thread, never more) waiting to enter the crit, meaning if I delete the crit at that point, the other thread subsequently wakes up from waiting on the crit, and causes a crash as the CRITICAL_SECTION object has by that time been destroyed.
If I keep my own internal lock count of threads waiting for access, I have the correct count; however this isn't ideal as I have to increment this count outside of the crit, meaning that value isn't protected and therefore can't be entirely relied upon at any one time.
Does anyone know why the LockCount in the CRITICAL_SECTION struct would be out by 1? If I use my own lock count, then check the CRITICAL_SECTION's lock count after that last thread has exited (and before I destroy the crit), it's still 0...
Or, is there a better way for me to protect the global resource in my app with that many threads, other than a critical section?
This is my wrapper struct:
typedef struct MY_CRIT {
BOOL Initialised;
CRITICAL_SECTION Crit;
int MyLockCount;
}
Here's my Crit init function:
BOOL InitCrit( MY_CRIT *pCrit )
{
if (pCrit)
{
InitializeCriticalSection( &pCrit->Crit );
pCrit->Initialised = TRUE;
pCrit->MyLockCount = 0;
return TRUE;
}
// else invalid pointer
else
return FALSE;
}
This is my enter crit wrapper function:
BOOL EnterCrit( MY_CRIT *pCrit )
{
// if pointer valid, and the crit is initialised
if (pCrit && pCrit->Initialised)
{
pCrit->MyLockCount++;
EnterCriticalSection( &pCrit->Crit );
pCrit->MyLockCount--;
// if still initialised
if (pCrit->Initialised)
{
return TRUE;
}
// else someone's trying to close this crit - jump out now!
else
{
LeaveCriticalSection( &pCrit->Crit );
return FALSE;
}
}
else // crit pointer is null
return FALSE;
}
And here's my FreeCrit wrapper function:
void FreeCrit( MY_CRIT *pCrit )
{
LONG WaitingCount = 0;
if (pCrit && (pCrit->Initialised))
{
// set Initialised to FALSE to stop any more threads trying to get in from now on:
EnterCriticalSection( &pCrit->Crit );
pCrit->Initialised = FALSE;
LeaveCriticalSection( &pCrit->Crit );
// loop until all waiting threads have gained access and finished:
do {
EnterCriticalSection( &pCrit->Crit );
// check if any threads are still waiting to enter:
// Windows XP and below:
if (IsWindowsXPOrBelow())
{
if ((pCrit->Crit.LockCount > 0) && ((pCrit->Crit.RecursionCount - 1) >= 0))
WaitingCount = pCrit->Crit.LockCount - (pCrit->Crit.RecursionCount - 1);
else
WaitingCount = 0;
}
// Windows 2003 Server and above:
else
{
WaitingCount = ((-1) - (pCrit->Crit.LockCount)) >> 2;
}
// hack: if our own lock count is higher, use that:
WaitingCount = max( WaitingCount, pCrit->MyLockCount );
// if some threads are still waiting, leave the crit and sleep a bit, to give them a chance to enter & exit:
if (WaitingCount > 0)
{
LeaveCriticalSection( &pCrit->Crit );
// don't hog the processor:
Sleep( 1 );
}
// when no other threads are waiting to enter, we can safely delete the crit (and leave the loop):
else
{
DeleteCriticalSection( &pCrit->Crit );
}
} while (WaitingCount > 0);
}
}
You are responsible to make sure that CS is not in use any longer before destroying it. Let us say that no other thread is currently trying to enter, but there is a chance that it is going to attempt very soon. Now you destroy the CS, what this concurrent thread is going to do? At its full pace it hits deleted critical section causing memory access violation?
The actual solution depends on your current app design, but if you are destroying threads, then you will perhaps want to flag your request to stop those threads, and then wait on theit handles to wait for their destruction. And then complete with deleting critical section when you are sure that threads are done.
Note that it is unsafe to rely on CS member values such as .LockCount, and having done things right way you will prehaps not even need thing like IsWindowsXPOrBelow. Critical section API suggest that you use CRITICAL_SECTION structure as "black box" leaving the internals to be implementation specific.
I've got a producer and a consumer. The producer writes fixed size items on a given shared memory area, and the consumer retrieves them.
The producer can be noticeably slower or faster than the consumer, randomly.
What we want is that
If the producer is running faster than the consumer, when it fills the circular buffer, it keeps writing on the oldest frames (other than the one that the consumer is consuming, of course - I stress this point, producer and consumer must be synchronized in the solution, because they are unrelated processes).
If, instead, the consumer is faster than the producer, it must wait for a new frame and consume it when it's there.
I found implementations of producer/consumers with circular buffers, but only ones that didn't respect the first request (ie, if the circular buffer is full, they wait for the consumer to finish, while what I want is to overwrite the oldest frames).
I'd prefer not to roll my own (prone to bugs) solution, but use a pre-canned, tested one. Can someone point me to a good C implementation? (C++ is also ok).
Many thanks.
Basically when the consumers are slow, it means that no one is using the buffer, so there is no difference between dropping the new frames and overriding the old frames. So maybe the following code can help. The producerRTLock cannot lock the buffer because there are consumers using the bufffer and therefore at the application level you can indicate to drop the frames.
class SampleSynchronizer {
mutex mux;
condition_variable con_cond;
unsigned int con_num;
condition_variable pro_cond;
bool prod;
public:
SampleSynchronizer(): con_num(0), prod(false) {
}
void consumerLock() {
unique_lock<mutex> locker(mux);
while(prod)
pro_cond.wait(locker);
con_num++;
}
void consumerUnlock() {
lock_guard<mutex> locker(mux);
con_num--;
con_cond.notify_one();
}
void producerLock() {
unique_lock<mutex> locker(mux);
while(con_num > 0)
con_cond.wait(locker);
prod = true;
}
bool producerRTLock() {
lock_guard<mutex> locker(mux);
if(con_num > 0)
return false;
prod = true;
return true;
}
void producerUnlock() {
lock_guard<mutex> locker(mux);
prod = false;
pro_cond.notify_all();
}
};