How to wake up a sleeping thread from the main Thread?
Solution 1
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).
Solution 2
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);
Solution 3
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();
liv2hak
Updated on June 05, 2022Comments
-
liv2hak almost 2 years
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 setreport()
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?