Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suspend pthreads without using condition

I want to suspend pthreads but apparently, there is no such function as pthread_suspend. I read somewhere about suspending pthreads using mutexes and conditions and used it as following:

#include <pthread.h>

class PThread {
public:
pthread_t myPthread;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;

void start() {
pthread_create(&myPthread, NULL, threadRun, (void*)this );
}

Thread() { }

void suspendMe() {
pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);
}

void resume() {
pthread_cond_signal(&m_ResumeCond);
}
};

but I don't understand why we need both mutex and condition to suspend and resume a pthread. Is it possible to suspend and resume it without using conditions?

like image 805
sleep Avatar asked Jun 29 '10 13:06

sleep


2 Answers

Your code is not correct - the pthread_cond_wait() requires that the mutex be locked already when you call it:

void suspendMe()
{
    pthread_mutex_lock(&m_SuspendMutex);
    pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
    pthread_mutex_unlock(&m_SuspendMutex);
}

However, this is still wrong. A thread can wake up from pthread_cond_wait() at any name, not necessarily only when it is signalled. This means that you need to pair pthread_cond_wait() with some shared state that encodes the condition that the thread is really waiting for - in the simplest case, you can just use a flag variable. pthread_cond_signal() is used to tell the thread that it should wake and re-check the shared state. Applying this to your implementation:

class PThread {
    public:

    pthread_t myPthread;
    bool suspended;
    pthread_mutex_t m_SuspendMutex;
    pthread_cond_t m_ResumeCond;

    void start() {
        suspended = false;
        pthread_create(&myPthread, NULL, threadRun, (void*)this );
    }

    Thread() { }

    void suspendMe() {
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = true;
        do {
            pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
        } while (suspended);
        pthread_mutex_unlock(&m_SuspendMutex);
    }

    void resume() {
        /* The shared state 'suspended' must be updated with the mutex held. */
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = false;
        pthread_cond_signal(&m_ResumeCond);
        pthread_mutex_unlock(&m_SuspendMutex);
    }
};

The reason the mutex is provided is to protect the shared state and avoid race conditions - the pthread_cond_wait() function actually performs an atomic-unlock-and-wait when it waits, which allows a "missed wakeup" to be avoided. For example in this code, the mutex prevents suspended from changing to false in between the suspended = true; and pthread_cond_wait() lines.

like image 141
caf Avatar answered Oct 02 '22 16:10

caf


If a thread wasn't waiting on some condition or other, how could you "signal" it to resume. It can't just stop executing anything at all and then magically start again, so it waits on a condition.

To elaborate, in pthreads, the way to resume a thread is in fact to use condition variables. There isn't an API available to suspend/resume a thread in any other way. Waiting on pthread_cond_wait is cheap, it blocks until the condition is signaled, not using (much?) CPU. You use the condition to signal the thread to wake up, and the mutex is required to protect access to the condition variable and the code in the thread upon wakeup.

like image 29
Mark B Avatar answered Oct 02 '22 17:10

Mark B