How to pause a pthread ANY TIME I want?

前端 未结 3 1271
半阙折子戏
半阙折子戏 2020-12-11 08:16

recently I set out to port ucos-ii to Ubuntu PC.

As we know, it\'s not possible to simulate the \"process\" in the ucos-ii by simply adding a flag in \"while\" loop

相关标签:
3条回答
  • 2020-12-11 09:06

    The Modula-3 garbage collector needs to suspend pthreads at an arbitrary time, not just when they are waiting on a condition variable or mutex. It does it by registering a (Unix) signal handler that suspends the thread and then using pthread_kill to send a signal to the target thread. I think it works (it has been reliable for others but I'm debugging an issue with it right now...) It's a bit kludgy, though....

    Google for ThreadPThread.m3 and look at the routines "StopWorld" and "StartWorld". Handler itself is in ThreadPThreadC.c.

    0 讨论(0)
  • 2020-12-11 09:12

    Here is example of thread function within a class with pause/resume functionality...

    class SomeClass
    {
    public:
        // ... construction/destruction
    
        void Resume();
        void Pause();
        void Stop();
    
    private:
        static void* ThreadFunc(void* pParam);
    
        pthread_t thread;
        pthread_mutex_t mutex;
        pthread_cond_t cond_var;
        int command;
    };
    
    SomeClass::SomeClass()
    {
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond_var, NULL);
    
        // create thread in suspended state..
        command = 0;
        pthread_create(&thread, NULL, ThreadFunc, this);
    }
    
    SomeClass::~SomeClass()
    {
        // we should stop the thread and exit ThreadFunc before calling of blocking pthread_join function
        // also it prevents the mutex staying locked..
        Stop();
        pthread_join(thread, NULL);
    
        pthread_cond_destroy(&cond_var);
        pthread_mutex_destroy(&mutex);
    }
    
    void* SomeClass::ThreadFunc(void* pParam)
    {
        SomeClass* pThis = (SomeClass*)pParam;
        timespec time_ns = {0, 50*1000*1000};   // 50 milliseconds
    
        while(1)
        {
            pthread_mutex_lock(&pThis->mutex);
    
            if (pThis->command == 2) // command to stop thread..
            {
                // be sure to unlock mutex before exit..
                pthread_mutex_unlock(&pThis->mutex);
                return NULL;
            }
            else if (pThis->command == 0) // command to pause thread..
            {
                pthread_cond_wait(&pThis->cond_var, &pThis->mutex);
                // dont forget to unlock the mutex..
                pthread_mutex_unlock(&pThis->mutex);
                continue;
            }
    
            if (pThis->command == 1) // command to run..
            {
                // normal runing process..
                fprintf(stderr, "*");
            }
    
            pthread_mutex_unlock(&pThis->mutex);
    
            // it's important to give main thread few time after unlock 'this'
            pthread_yield();
            // ... or...
            //nanosleep(&time_ns, NULL);
        }
        pthread_exit(NULL);
    }
    
    void SomeClass::Stop()
    {
        pthread_mutex_lock(&mutex);
        command = 2;
        pthread_cond_signal(&cond_var);
        pthread_mutex_unlock(&mutex);
    }
    
    void SomeClass::Pause()
    {
        pthread_mutex_lock(&mutex);
        command = 0;
        // in pause command we dont need to signal cond_var because we not in wait state now..
        pthread_mutex_unlock(&mutex);
    }
    
    void SomeClass::Resume()
    {
        pthread_mutex_lock(&mutex);
        command = 1;
        pthread_cond_signal(&cond_var);
        pthread_mutex_unlock(&mutex);
    }
    
    0 讨论(0)
  • 2020-12-11 09:13

    If stopping at specific points with a condition variable is insufficient, then you can't do this with pthreads. The pthread interface does not include suspend/resume functionality.

    See, for example, answer E.4 here:

    The POSIX standard provides no mechanism by which a thread A can suspend the execution of another thread B, without cooperation from B. The only way to implement a suspend/restart mechanism is to have B check periodically some global variable for a suspend request and then suspend itself on a condition variable, which another thread can signal later to restart B.

    That FAQ answer goes on to describe a couple of non-standard ways of doing it, one in Solaris and one in LinuxThreads (which is now obsolete; do not confuse it with current threading on Linux); neither of those apply to your situation.

    0 讨论(0)
提交回复
热议问题