I am writing code for a memory buffer which allows threads to share memory with each other. I am trying to use critical sections and condition variables for synchronization.
Here is my source code:
size_t ReadBuffer(char *dst_buffer)
{
size_t size = 0;
EnterCriticalSection(&m_CriticalSection);
if (!m_bBufferReady)
{
printf("ReadBuffer: wait for ready buffer\n");
SleepConditionVariableCS (&BufferNotEmpty, &m_CriticalSection, INFINITE);
printf("ReadBuffer: after wait for ready buffer\n");
}
if (m_uRealSize == 0)
{
}
memcpy(dst_buffer, m_pBuffer, m_uRealSize);
size = m_uRealSize;
m_uRealSize = 0;
m_bBufferReady = FALSE;
LeaveCriticalSection(&m_CriticalSection);
WakeConditionVariable (&BufferNotFull);
if (size != 0)
{
SleepConditionVariableCS (&BufferNotEmpty, &m_CriticalSection, INFINITE);
}
return size;
}
size_t WriteBuffer(const char *src_buffer, size_t size)
{
EnterCriticalSection(&m_CriticalSection);
if (m_bBufferReady)
{
SleepConditionVariableCS (&BufferNotFull, &m_CriticalSection, INFINITE);
printf("WriteBuffer: after wait for free buffer\n");
}
if (size > m_uBufferSize)
size = m_uBufferSize;
memcpy(m_pBuffer, src_buffer, size);
m_uRealSize = size;
m_bBufferReady = TRUE;
LeaveCriticalSection(&m_CriticalSection);
WakeConditionVariable (&BufferNotEmpty);
SleepConditionVariableCS (&BufferNotFull, &m_CriticalSection, INFINITE);
return size;
}
When WriteBuffer is called with a zero size buffer it is treated as the end of communication. At that point the reading thread exits correctly but the writing thread hangs on the last call to SleepConditionVariableCS.
When I use Windows events instead of conditional variables, everything works OK, so I don't think this is a problem with the algorithm. But I want to be able to use conditional variables instead of events. Is there some restriction to the use of conditional variables? Or maybe it is connected to the critical section somehow?
What is going wrong, and how can I fix it?
I think the first problem is that you're calling SleepConditionalVariableCS after exiting the critical section.
From the documentation for SleepConditionVariableCS:
This critical section must be entered exactly once by the caller at the time SleepConditionVariableCS is called.
As described in the documentation for LeaveCriticalSection, exiting a critical section you don't own causes an error that "may cause another thread using EnterCriticalSection to wait indefinitely".
Related
I am attempting to write a thread safe task queue for multithreading in C++, using SDL2's threading library.
The thread function which runs on all threads is as follows:
int threadFunc(void * pData)
{
ThreadData* data = (ThreadData*)pData;
SDLTaskManager* pool = data->pool;
Task* task = nullptr;
while (true)
{
SDL_LockMutex(pool->mLock);
while (!pool->mRunning && pool->mCurrentTasks.empty())
{
//mutex is unlocked, then locked again when signal received
SDL_CondWait(pool->mConditionFlag, pool->mLock);
if (pool->mShuttingDown)
return 0;
}
//mutex is locked at this stage so no other threads can alter contents of deque
//code inside if block should not be executed if deque is empty
if (!pool->mCurrentTasks.empty())
{
/*out of range error here*/
task = pool->mCurrentTasks.front();
pool->mCurrentTasks.pop_front();
}
if (task != nullptr)
{
pool->notifyThreadWorking(true);
data->taskCount++;
}
else
{
pool->stop();
SDL_UnlockMutex(pool->mLock);
continue;
}
SDL_UnlockMutex(pool->mLock);
task->execute();
SDL_LockMutex(pool->mLock);
pool->notifyThreadWorking(false);
pool->mCompleteTasks.push_back(task);
SDL_UnlockMutex(pool->mLock);
task = nullptr;
}
return 0;
}
As you can see, according to the comments in the code, an out of range error occurs inside an if block, where the deque is empty. However, there is a check there to make sure that the code is only executed if the deque is not empty. The mutex is locked by SDL_CondWait so no other thread should be able to make changes to the deque, until that mutex is unlocked again.
The producer code is as follows:
SDL_LockMutex(pool->mLock);
for (int i = 0; i < numTasks; i++)
{
pool->mCurrentTasks.push_back(new Task());
}
pool->mRunning = true;
SDL_CondBroadcast(pool->mConditionFlag);
SDL_UnlockMutex(pool->mLock);
The fact that the code inside the if block is being executed, shows that at the time if (!pool->mCurrentTasks.empty()) is evaluated, the deque has member data, but not when it reaches task = pool->mCurrentTasks.front(); By my understanding of mutex' this shouldn't be possible. How can this be?
I have a weird problem with pthread_cond_wait and pthread_cond_signal. I have arranged a series of threads. They are all in sleep state when started. A wake up function will signal these threads, do some work, and wait for the results.
In the setup below, td is thread data, containing the mutex and conditions, and th is an array containing the pointer to the threads:
for (size_t i = 0; i < NUM_THREADS; i++) {
pthread_cond_init(&td[i].cond, NULL);
pthread_mutex_init(&td[i].cond_mutex, NULL);
pthread_mutex_init(&td[i].work_mutex, NULL);
pthread_mutex_lock(&td[i].cond_mutex);
pthread_mutex_lock(&td[i].work_mutex);
pthread_create(&th[i], NULL, thread_worker, (void *)&td[i]);
}
Thread worker is like this:
void*
thread_worker(void* data)
{
THREAD_DATA *td = (THREAD_DATA *)data;
while (1) {
pthread_cond_wait(&td->cond, &td->cond_mutex); // marker
// do work ...
pthread_mutex_unlock(&td->work_mutex);
}
pthread_exit(NULL);
}
This job function is supposed to wake up all the threads, do the job, and wait for them to finish:
void
job()
{
for (size_t i = 0; i < NUM_THREADS; i++) {
pthread_cond_signal(&td[i].cond);
}
for (size_t i = 0; i < NUM_THREADS; i++) {
pthread_mutex_lock(&td[i].work_mutex); // block until the work is done
}
}
In some rare situations (1 out of 1000 runs maybe), the above setup will encounter a freeze. When that happens, the 'marker' line in thread_worker will not be signaled by pthread_cond_signal, it just kept on waiting. It's very rare but it happens from time to time. I've produced numerous log messages, and I verified that pthread_cond_wait is always called before pthread_cond_signal. What am I doing wrong here?
There is nothing there that forces the pthread_cond_wait() to be called before the pthread_cond_signal(). Despite what you say about logging, it's entirely possible for the logged lines to be out-of-sequence with what really happened.
You aren't using mutexes and condition variables correctly: mutexes should only be unlocked by the same thread that locked them, and condition variables should be paired with a test over some shared state (called a predicate). The shared state is supposed to be protected by the mutex that is passed to pthread_cond_wait().
For example, your example can be reworked to correctly use mutexes and condition variables. First, add an int work_status to the THREAD_DATA structure, where 0 indicates that the thread is waiting for work, 1 indicates that work is available and 2 indicates that the work is complete.
You don't appear to need two mutexes in each THREAD_DATA, and you don't want to lock the mutex in the main thread when you're setting it up:
for (size_t i = 0; i < NUM_THREADS; i++) {
pthread_cond_init(&td[i].cond, NULL);
pthread_mutex_init(&td[i].cond_mutex, NULL);
td[i].work_status = 0;
pthread_create(&th[i], NULL, thread_worker, (void *)&td[i]);
}
Have the threads wait on work_status using the condition variable:
void*
thread_worker(void* data)
{
THREAD_DATA *td = (THREAD_DATA *)data;
while (1) {
/* Wait for work to be available */
pthread_mutex_lock(&td->cond_mutex);
while (td->work_status != 1)
pthread_cond_wait(&td->cond, &td->cond_mutex);
pthread_mutex_unlock(&td->cond_mutex);
// do work ...
/* Tell main thread that the work has finished */
pthread_mutex_lock(&td->cond_mutex);
td->work_status = 2;
pthread_cond_signal(&td->cond);
pthread_mutex_unlock(&td->cond_mutex);
}
pthread_exit(NULL);
}
...and set and wait on work_status as appropriate in job():
void
job()
{
/* Tell threads that work is available */
for (size_t i = 0; i < NUM_THREADS; i++) {
pthread_mutex_lock(&td[i].cond_mutex);
td[i].work_status = 1;
pthread_cond_signal(&td[i].cond);
pthread_mutex_unlock(&td[i].cond_mutex);
}
/* Wait for threads to signal work complete */
for (size_t i = 0; i < NUM_THREADS; i++) {
pthread_mutex_lock(&td[i].cond_mutex);
while (td[i].work_status != 2)
pthread_cond_wait(&td[i].cond, &td[i].cond_mutex);
pthread_mutex_unlock(&td[i].cond_mutex);
}
}
Some check lists:
1) Do you lock the mutex td->cond_mutex before waiting on the cond variable? Otherwise, it's undefined.
2) Do you check predicate after pthread_cond_wait() returns? Typical usage is
while(!flag) pthread_cond_wait(&cv, &mutex); //waits on flag
which is not what you have. This is to protect against spurious wake-ups and also ensure the predicate hasn't changed in the meantime.
3) pthread_cond_signal() is guaranteed to wake up at least one thread. You may want to use pthread_cond_broadcast() if there are multiple threads waiting on the same condition variable.
4) If no thread is waiting on a conditional variable then pthread_cond_signal() or pthread_cond_broadcast() has no effect.
I am trying to tell when a producer process accesses a shared windows mutex. After this happens, I need to lock that same mutex and process the associated data. Is there a build in way in Windows to do this, short of a ridiculous loop?
I know the result of this is doable through creating a custom Windows event in the producer process, but I want to avoid changing this programs code as much as possible.
What I believe will work (in a ridiculously inefficient way) would be this (NOTE: this is not my real code, I know there are like 10 different things very wrong with this; I want to avoid doing anything like this):
#include <Windows.h>
int main() {
HANDLE h = CreateMutex(NULL, 0, "name");
if(!h) return -1;
int locked = 0;
while(true) {
if(locked) {
//can assume it wont be locked longer than a second, but even if it does should work fine
if(WaitForSingleObject(h, 1000) == WAIT_OBJECT_0) {
// do processing...
locked = 0;
ReleaseMutex(h);
}
// oh god this is ugly, and wastes so much CPU...
} else if(!(locked = WaitForSingleObject(h, 0) == WAIT_TIMEOUT)) {
ReleaseMutex(h);
}
}
return 0;
}
If there is an easier way with C++ for whatever reason, my code is actually that. This example was just easier to construct in C.
You will not be able to avoid changing the producer if efficient sharing is needed. Your design is fundamentally flawed for that.
A producer needs to be able to signal a consumer when data is ready to be consumed, and to make sure it does not alter the data while it is busy being consumed. You cannot do that with a single mutex alone.
The best way is to have the producer set an event when data is ready, and have the consumer reset the event when the data has been consumed. Use the mutex only to sync access to the data, not to signal the data's readiness.
#include <Windows.h>
int main()
{
HANDLE readyEvent = CreateEvent(NULL, TRUE, FALSE, "ready");
if (!readyEvent) return -1;
HANDLE mutex = CreateMutex(NULL, FALSE, "name");
if (!mutex) return -1;
while(true)
{
if (WaitForSingleObject(readyEvent, 1000) == WAIT_OBJECT_0)
{
if (WaitForSingleObject(mutex, 1000) == WAIT_OBJECT_0)
{
// process as needed...
ResetEvent(readyEvent);
ReleaseMutex(mutex);
}
}
}
return 0;
}
If you can't change the producer to use an event, then at least add a flag to the data itself. The producer can lock the mutex, update the data and flag, and unlock the mutex. Consumers will then have to periodically lock the mutex, check the flag and read the new data if the flag is set, reset the flag, and unlock the mutex.
#include <Windows.h>
int main()
{
HANDLE mutex = CreateMutex(NULL, FALSE, "name");
if (!mutex) return -1;
while(true)
{
if (WaitForSingleObject(mutex, 1000) == WAIT_OBJECT_0)
{
if (ready)
{
// process as needed...
ready = false;
}
ReleaseMutex(mutex);
}
}
return 0;
}
So either way, your logic will have to be tweaked in both the producer and consumer.
Otherwise, if you can't change the producer at all, then you have no choice but to change the consumer alone to simply check the data for changes peridiodically:
#include <Windows.h>
int main()
{
HANDLE mutex = CreateMutex(NULL, 0, "name");
if (!mutex) return -1;
while(true)
{
if (WaitForSingleObject(mutex, 1000) == WAIT_OBJECT_0)
{
// check data for changes
// process new data as needed
// cache results for next time...
ReleaseMutex(mutex);
}
}
return 0;
}
Tricky. I'm going to answer the underlying question: when is the memory written?
This can be observed via a four step solution:
Inject a DLL in the watched process
Add a vectored exception handler for STATUS_GUARD_PAGE_VIOLATION
Set the guard page bit on the 2 MB memory range (finding it could be a challenge)
From the vectored exception handler, inform your process and re-establish the guard bit (it's one-shot)
You may need only a single guard page if the image is always fully rewritten.
I have a question about C concurrency programming in Embedded System with about 64Mb Ram.
Especially, I want to reduce the default memory used by a Thread, so I have defined:
pthread_attr_t attr_test;
size_t stacksize = 0x186A0; // 100Kbyte
pthread_attr_init(&attr_test);
pthread_attr_setdetachstate(&attr_test, PTHREAD_CREATE_DETACHED);
pthread_attr_setstacksize(&attr_test, stacksize);
So, When the Thread starts, it uses only 100Kbyte of virtual Memory.
BUT when the Thread ends and calls pthread_exit, the virtual Memory used by the process, increases rapidly!....
Why? What can I do?
Thanks!
UPDATE:
Thread ->
void *thread_test(void *arg1) {
int *param;
param = (int*)arg1;
printf("Thread %d start\n", *param);
pthread_cond_wait(&condition[*param], &mutex[*param]);
printf("Thread %d stop\n",*param);
pthread_exit(0);
}
Main ->
int main(void) {
pthread_t IDthread[MAX_THREADS];
int param[MAX_THREADS];
int pointer;
int i, keyb;
void *stkaddr;
size_t stacksize;
puts("!!! THREAD TEST !!!");
printf("Process ID %d\n\n", getpid());
for(i=0; i<MAX_THREADS; i++)
{
pthread_cond_init(&condition[i], NULL);
pthread_mutex_init(&mutex[i], NULL);
IDthread[i] = 0;
param[i] = i;
}
stacksize = 0x186A0; // 100Kbyte
pthread_attr_init(&attr_test);
pthread_attr_setdetachstate(&attr_test, PTHREAD_CREATE_DETACHED);
/* setting the size of the stack also */
pthread_attr_setstacksize(&attr_test, stacksize);
pointer = 0;
do {
keyb = getchar();
if (keyb == '1')
{
if (pointer < MAX_THREADS)
{
pthread_create(&IDthread[pointer], &attr_test, thread_test, ¶m[pointer]);
sleep(1);
pointer++;
}
else
puts("MAX Threads Number");
}
if (keyb == '2')
{
if (pointer != 0)
{
pointer--;
pthread_cond_signal(&condition[pointer]);
sleep(1);
}
else
puts("0 Thread is running");
}
} while (keyb != '0');
printf("FINE\n");
return EXIT_SUCCESS;
}
There is a known issue with the joinable or detached threads, quoting from the manual:
Only when a
terminated joinable thread has been joined are the last of its
resources released back to the system. When a detached thread
terminates, its resources are automatically released back to the
system
you can make the thread detachable with:
pthread_attr_setdetachstate(3)
There are some problems with your test.
At first, pthread_attr_setstacksize has the following documentation:
The stack size attribute determines the minimum size (in bytes) that will be allocated for threads created using the thread attributes object attr.
So each thread could use more than what you have set. But more than that, threads may allocate memory from the OS to use as stack. And this also applies to the main thread.
Therefore I don't think there is a way to achieve what you want by looking at the result of top command, since this information is only visible from within the thread itself.
Also note that the virtual memory used by the process is not related to the amount of RAM used by the process.
Here is something you can try to check the total stack of a thread.
I have a thread to monitor serial port using select system call, the run function of the thread is as follows:
void <ProtocolClass>::run()
{
int fd = mPort->GetFileDescriptor();
fd_set readfs;
int maxfd=fd+1;
int res;
struct timeval Timeout;
Timeout.tv_usec=0;
Timeout.tv_sec=3;
//BYTE ack_message_frame[ACKNOWLEDGE_FRAME_SIZE];
while(true)
{
usleep(10);
FD_ZERO(&readfs);
FD_SET(fd,&readfs);
res=select(maxfd,&readfs,NULL,NULL,NULL);
if(res<0)
perror("\nselect failed");
else if( res==0)
puts("TIMEOUT");
else if(FD_ISSET(fd,&readfs))
{//IF INPUT RECEIVED
qDebug("************RECEIVED DATA****************");
FlushBuf();
qDebug("\nReading data into a read buffer");
int bytes_read=mPort->ReadPort(mBuf,1000);
mFrameReceived=false;
for(int i=0;i<bytes_read;i++)
{
qDebug("%x",mBuf[i]);
}
//if complete frame has been received, write the acknowledge message frame to the port.
if(bytes_read>0)
{
qDebug("\nAbout to Process Received bytes");
ProcessReceivedBytes(mBuf,bytes_read);
qDebug("\n Processed Received bytes");
if(mFrameReceived)
{
int no_bytes=mPort->WritePort(mAcknowledgeMessage,ACKNOWLEDGE_FRAME_SIZE);
}//if frame received
}//if bytes read > 0
} //if input received
}//end while
}
The problem is when I exit from this thread, using
delete <protocolclass>::instance();
the program crashes with a glibc error of malloc memory corruption. On checking the core with gdb it was found the when exiting the thread it was processing the data and thus the error. The destructor of the protocol class looks as follows:
<ProtocolClass>::~<ProtocolClass>()
{
delete [] mpTrackInfo; //delete data
wait();
mPort->ClosePort();
s_instance = NULL; //static instance of singleton
delete mPort;
}
Is this due to select? Do the semantics for destroying objects change when select is involved? Can someone suggest a clean way to destroy threads involving select call.
Thanks
I'm not sure what threading library you use, but you should probably signal the thread in one way or another that it should exit, rather than killing it.
The most simple way would be to keep a boolean that is set true when the thread should exit, and use a timeout on the select() call to check it periodically.
ProtocolClass::StopThread ()
{
kill_me = true;
// Wait for thread to die
Join();
}
ProtocolClass::run ()
{
struct timeval tv;
...
while (!kill_me) {
...
tv.tv_sec = 1;
tv.tv_usec = 0;
res = select (maxfd, &readfds, NULL, NULL, &tv);
if (res < 0) {
// Handle error
}
else if (res != 0) {
...
}
}
You could also set up a pipe and include it in readfds, and then just write something to it from another thread. That would avoid waking up every second and bring down the thread without delay.
Also, you should of course never use a boolean variable like that without some kind of lock, ...
Are the threads still looking at mpTrackInfo after you delete it?
Not seeing the code it is hard.
But Iwould think that the first thing the destructor should do is wait for any threads to die (preferably with some form of join() to make sure they are all accounted for). Once they are dead you can start cleaning up the data.
your thread is more than just memory with some members, so just deleting and counting on the destructor is not enough. Since I don't know qt threads I think this link can put you on your way:
trolltech message
Two possible problems:
What is mpTrackInfo? You delete it before you wait for the thread to exit. Does the thread use this data somewhere, maybe even after it's been deleted?
How does the thread know it's supposed to exit? The loop in run() seems to run forever, which should cause wait() in the destructor to wait forever.