简体   繁体   中英

How to wake up a sleeping thread from the main Thread?

I have a capture program which in addition do capturing data and writing it into a file also prints some statistics.The function that prints the statistics

static void report(void)
{
         /*Print statistics*/
}

is called roughly every second using an ALARM that expires every second.So The program is like

void capture_program()
{
       pthread_t report_thread

            while()
            {
                     if(pthread_create(&report_thread,NULL,report,NULL)){
                            fprintf(stderr,"Error creating reporting thread! \n");
                     }

                     /*
                        Capturing code
                        --------------
                        --------------
                      */
                      if(doreport)
                             /*wakeup the sleeping thread.*/

            }
}

void *report(void *param)
{
       //access some register from hardware
       //sleep for a second 

}

The expiry of the timer sets the doreport flag.If this flag is set report() is called which clears the flag.

How do I wake up the sleeping thread (that runs the report()) when the timer goes off in the main thread?

You can sleep a thread using sigwait, and then signal that thread to wake up with pthread_kill. Kill sounds bad, but it doesn't kill the thread, it sends a signal. This method is very fast. It was much faster than condition variables. I am not sure it is easier, harder, safer or more dangerous, but we needed the performance so we went this route.

in startup code somewhere:

sigemptyset(&fSigSet);
sigaddset(&fSigSet, SIGUSR1);
sigaddset(&fSigSet, SIGSEGV);

to sleep, the thread does this:

int nSig;
sigwait(&fSigSet, &nSig);

to wake up (done from any other thread)

pthread_kill(pThread, SIGUSR1);

or to wake up you could do this:

tgkill(nPid, nTid, SIGUSR1);

Our code calls this on the main thread before creating child threads. I'm not sure why this would be required.

pthread_sigmask(SIG_BLOCK, &fSigSet, NULL);

How do I wake up the sleeping thread (that runs the report()) when the timer goes off in the main thread?

I think a condition variable is the mechanism you are looking for. Have the report-thread block on the condition variable, and the main thread signal the condition variable whenever you want the report-thread to wake up (see the link for more detailed instructions).

I had a similar issue when coding an UDP chat server: there is a thread_1 that only works when an alarm interruption (timeout to see if the client is still alive) OR another thread_2 (this thread meets client requests) signals arrives. What I did was put this thread_1 to sleep ( sleep(n*TICK_TIMER) , where TICK_TIMER is the alarm expiration value, n is some integer >1), and wake up this thread with SIGALRM signal. See sleep() doc

The alarm handler ( to use this you have to init it: "signal(SIGALRM, tick_handler); alarm(5);")

void tick_handler(){tick_flag++; alarm(5); }

will send a SIGALRM when timeout occurs.

And the command to wake this sleep thread_1 from another thread_2 is:

    pthread_kill(X,SIGALRM);

where X is a pthread_t type. If your thread_1 is your main thread, you can get this number by pthread_t X = pthread_self();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM