Threading in C with sleep
I am learning C threading concepts and I wrote simple below code. Now when I compile and run it , I get random behaviour like it prints unexpectedly.
#include #include void * func_threadName(void * i) < int *x=(int *)i; printf("I'm thread : %d\n",*x); return NULL; >main() < int iter; printf("testing multithreading. \n"); pthread_t thread_arr[3]; for (iter=0;iter<3;iter++) < pthread_create(&thread_arr[iter],NULL,func_threadName,&iter); >for (iter=0;iter <3;iter++) < pthread_join(thread_arr[iter],NULL); >>
diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o testing multithreading. I'm thread : 0 I'm thread : 0 I'm thread : 0 diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o testing multithreading. I'm thread : 0 I'm thread : 2 I'm thread : 1 diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o testing multithreading. I'm thread : 2 I'm thread : 2 I'm thread : 0
But when I make a slight change like below after creating thread, it works perfectly and prints in order.
diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o testing multithreading. I'm thread : 0 I'm thread : 1 I'm thread : 2 diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o testing multithreading. I'm thread : 0 I'm thread : 1 I'm thread : 2 diwakar@diwakar-VPCEH25EN:~/Documents/my_C_codes$ ./thread_test.o testing multithreading. I'm thread : 0 I'm thread : 1 I'm thread : 2
I would like to understand that in the first case , is the unpredictable behaviour shown because all threads share the same memory space and hence before one thread terminates, other is using the same value of i ? Any additional info is welcome.
How to pause a pthread ANY TIME I want?
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 in the pthread’s call-back function to perform pause and resume(like the solution below). Because the «process» in ucos-ii can be paused or resumed at any time! How to sleep or pause a PThread in c on Linux I have found one solution on the web-site below, but it can’t be built because it’s out of date. It uses the process in Linux to simulate the task(acts like the process in our Linux) in ucos-ii. http://www2.hs-esslingen.de/~zimmerma/software/index_uk.html If pthread can act like the process which can be paused and resumed at any time, please tell me some related functions, I can figure it out myself. If it can’t, I think I should focus on the older solution. Thanks a lot.
Wait, why exactly can’t you just use a condition variable and a shared atomic flag to pause/resume a process?
Let’s image what your CPU schedules processes in your system. For example, when a process runs out its own time-splices in CPU, it will be asked to sleep. Although maybe there’s no sleep-related or synchronization-related sentence in your program, the OS will sticks to ask your process to do so. Now, what I’m going to do is using pthreads to simulate the processes in OS.
4 Answers 4
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.
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.
On Linux you can probably setup custom signal handler (eg. using signal()) that will contain wait for another signal (eg. using sigsuspend()). You then send the signals using pthread_kill() or tgkill(). It is important to use so-called «realtime signals» for this, because normal signals like SIGUSR1 and SIGUSR2 don’t get queued, which means that they can get lost under high load conditions. You send a signal several times, but it gets received only once, because before while signal handler is running, new signals of the same kind are ignored. So if you have concurent threads doing PAUSE/RESUME , you can loose RESUME event and cause deadlock. On the other hand, the pending realtime signals (like SIGRTMIN+1 and SIGRTMIN+2) are not deduplicated, so there can be several same rt signals in queue at the same time.
DISCLAIMER: I had not tried this yet. But in theory it should work.
Also see man 7 signal-safety. There is a list of calls that you can safely call in signal handlers. Fortunately sigsuspend() seems to be one of them.
UPDATE: I have working code right here:
//Filename: pthread_pause.c //Author: Tomas 'Harvie' Mudrunka 2021 //Build: CFLAGS=-lpthread make pthread_pause; ./pthread_pause //Test: valgrind --tool=helgrind ./pthread_pause //I've wrote this code as excercise to solve following stack overflow question: // https://stackoverflow.com/questions/9397068/how-to-pause-a-pthread-any-time-i-want/68119116#68119116 #define _GNU_SOURCE //pthread_yield() needs this #include #include //#include #include #include #include #include #include #include #include #include #define PTHREAD_XSIG_STOP (SIGRTMIN+0) #define PTHREAD_XSIG_CONT (SIGRTMIN+1) #define PTHREAD_XSIGRTMIN (SIGRTMIN+2) //First unused RT signal pthread_t main_thread; sem_t pthread_pause_sem; pthread_once_t pthread_pause_once_ctrl = PTHREAD_ONCE_INIT; void pthread_pause_once(void) < sem_init(&pthread_pause_sem, 0, 1); >#define pthread_pause_init() (pthread_once(&pthread_pause_once_ctrl, &pthread_pause_once)) #define NSEC_PER_SEC (1000*1000*1000) // timespec_normalise() from https://github.com/solemnwarning/timespec/ struct timespec timespec_normalise(struct timespec ts) < while(ts.tv_nsec >= NSEC_PER_SEC) < ++(ts.tv_sec); ts.tv_nsec -= NSEC_PER_SEC; >while(ts.tv_nsec if(ts.tv_nsec < 0) < // Negative nanoseconds isn't valid according to POSIX. --(ts.tv_sec); ts.tv_nsec = (NSEC_PER_SEC + ts.tv_nsec); >return ts; > void pthread_nanosleep(struct timespec t) < //Sleep calls on Linux get interrupted by signals, causing premature wake //Pthread (un)pause is built using signals //Therefore we need self-restarting sleep implementation //IO timeouts are restarted by SA_RESTART, but sleeps do need explicit restart //We also need to sleep using absolute time, because relative time is paused //You should use this in any thread that gets (un)paused struct timespec wake; clock_gettime(CLOCK_MONOTONIC, &wake); t = timespec_normalise(t); wake.tv_sec += t.tv_sec; wake.tv_nsec += t.tv_nsec; wake = timespec_normalise(wake); while(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wake, NULL)) if(errno!=EINTR) break; return; >void pthread_nsleep(time_t s, long ns) < struct timespec t; t.tv_sec = s; t.tv_nsec = ns; pthread_nanosleep(t); >void pthread_sleep(time_t s) < pthread_nsleep(s, 0); >void pthread_pause_yield() < //Call this to give other threads chance to run //Wait until last (un)pause action gets finished sem_wait(&pthread_pause_sem); sem_post(&pthread_pause_sem); //usleep(0); //nanosleep(&((const struct timespec)), NULL); //pthread_nsleep(0,1); //pthread_yield() is not enough, so we use sleep pthread_yield(); > void pthread_pause_handler(int signal) < //Do nothing when there are more signals pending (to cleanup the queue) //This is no longer needed, since we use semaphore to limit pending signals /* sigset_t pending; sigpending(&pending); if(sigismember(&pending, PTHREAD_XSIG_STOP)) return; if(sigismember(&pending, PTHREAD_XSIG_CONT)) return; */ //Post semaphore to confirm that signal is handled sem_post(&pthread_pause_sem); //Suspend if needed if(signal == PTHREAD_XSIG_STOP) < sigset_t sigset; sigfillset(&sigset); sigdelset(&sigset, PTHREAD_XSIG_STOP); sigdelset(&sigset, PTHREAD_XSIG_CONT); sigsuspend(&sigset); //Wait for next signal >else return; > void pthread_pause_enable() < //Having signal queue too deep might not be necessary //It can be limited using RLIMIT_SIGPENDING //You can get runtime SigQ stats using following command: //grep -i sig /proc/$(pgrep binary)/status //This is no longer needed, since we use semaphores //struct rlimit sigq = ; //setrlimit(RLIMIT_SIGPENDING, &sigq); pthread_pause_init(); //Prepare sigset sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, PTHREAD_XSIG_STOP); sigaddset(&sigset, PTHREAD_XSIG_CONT); //Register signal handlers //signal(PTHREAD_XSIG_STOP, pthread_pause_handler); //signal(PTHREAD_XSIG_CONT, pthread_pause_handler); //We now use sigaction() instead of signal(), because it supports SA_RESTART const struct sigaction pause_sa = < .sa_handler = pthread_pause_handler, .sa_mask = sigset, .sa_flags = SA_RESTART, .sa_restorer = NULL >; sigaction(PTHREAD_XSIG_STOP, &pause_sa, NULL); sigaction(PTHREAD_XSIG_CONT, &pause_sa, NULL); //UnBlock signals pthread_sigmask(SIG_UNBLOCK, &sigset, NULL); > void pthread_pause_disable() < //This is important for when you want to do some signal unsafe stuff //Eg.: locking mutex, calling printf() which has internal mutex, etc. //After unlocking mutex, you can enable pause again. pthread_pause_init(); //Make sure all signals are dispatched before we block them sem_wait(&pthread_pause_sem); //Block signals sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, PTHREAD_XSIG_STOP); sigaddset(&sigset, PTHREAD_XSIG_CONT); pthread_sigmask(SIG_BLOCK, &sigset, NULL); sem_post(&pthread_pause_sem); >int pthread_pause(pthread_t thread) < sem_wait(&pthread_pause_sem); //If signal queue is full, we keep retrying while(pthread_kill(thread, PTHREAD_XSIG_STOP) == EAGAIN) usleep(1000); pthread_pause_yield(); return 0; >int pthread_unpause(pthread_t thread) < sem_wait(&pthread_pause_sem); //If signal queue is full, we keep retrying while(pthread_kill(thread, PTHREAD_XSIG_CONT) == EAGAIN) usleep(1000); pthread_pause_yield(); return 0; >void *thread_test() < //Whole process dies if you kill thread immediately before it is pausable //pthread_pause_enable(); while(1) < //Printf() is not async signal safe (because it holds internal mutex), //you should call it only with pause disabled! //Will throw helgrind warnings anyway, not sure why. //See: man 7 signal-safety pthread_pause_disable(); printf("Running!\n"); pthread_pause_enable(); //Pausing main thread should not cause deadlock //We pause main thread here just to test it is OK pthread_pause(main_thread); //pthread_nsleep(0, 1000*1000); pthread_unpause(main_thread); //Wait for a while //pthread_nsleep(0, 1000*1000*100); pthread_unpause(main_thread); >> int main() < pthread_t t; main_thread = pthread_self(); pthread_pause_enable(); //Will get inherited by all threads from now on //you need to call pthread_pause_enable (or disable) before creating threads, //otherwise first (un)pause signal will kill whole process pthread_create(&t, NULL, thread_test, NULL); while(1) < pthread_pause(t); printf("PAUSED\n"); pthread_sleep(3); printf("UNPAUSED\n"); pthread_unpause(t); pthread_sleep(1); /* pthread_pause_disable(); printf("RUNNING!\n"); pthread_pause_enable(); */ pthread_pause(t); pthread_unpause(t); >pthread_join(t, NULL); printf("DIEDED!\n"); >
I am also working on library called «pthread_extra», which will have stuff like this and much more. Will publish soon.
UPDATE2: This is still causing deadlocks when calling pause/unpause rapidly (removed sleep() calls). Printf() implementation in glibc has mutex, so if you suspend thread which is in middle of printf() and then want to printf() from your thread which plans to unpause that thread later, it will never happen, because printf() is locked. Unfortunately i’ve removed the printf() and only run empty while loop in the thread, but i still get deadlocks under high pause/unpause rates. and i don’t know why. Maybe (even realtime) Linux signals are not 100% safe. There is realtime signal queue, maybe it just overflows or something.
UPDATE3: i think i’ve managed to fix the deadlock, but had to completely rewrite most of the code. Now i have one (sig_atomic_t) variable per each thread which holds state whether that thread should be running or not. Works kinda like condition variable. pthread_(un)pause() transparently remembers this for each thread. I don’t have two signals. now i only have one signal. handler of that signal looks at that variable and only blocks on sigsuspend() when that variable says the thread should NOT run. otherwise it returns from signal handler. in order to suspend/resume the thread i now set the sig_atomic_t variable to desired state and call that signal (which is common for both suspend and resume). It is important to use realtime signals to be sure handler will actualy run after you’ve modified the state variable. Code is bit complex because of the thread status database. I will share the code in separate solution as soon as i manage to simplify it enough. But i want to preserve the two signal version in here, because it kinda works, i like the simplicity and maybe people will give us more insight on how to optimize it.
UPDATE4: I’ve fixed the deadlock in original code (no need for helper variable holding the status) by using single handler for two signals and optimizing signal queue a bit. There is still some problem with printf() shown by helgrind, but it is not caused by my signals, it happens even when i do not call pause/unpause at all. Overall this was only tested on LINUX, not sure how portable the code is, because there seem to be some undocumented behaviour of signal handlers which was originaly causing the deadlock.
Please note that pause/unpause cannot be nested. if you pause 3 times, and unpause 1 time, the thread WILL RUN. If you need such behaviour, you should create some kind of wrapper which will count the nesting levels and signal the thread accordingly.
UPDATE5: I’ve improved robustness of the code by following changes: I ensure proper serialization of pause/unpause calls by use of semaphores. This hopefuly fixes last remaining deadlocks. Now you can be sure that when pause call returns, the target thread is actualy already paused. This also solves issues with signal queue overflowing. Also i’ve added SA_RESTART flag, which prevents internal signals from causing interuption of IO waits. Sleeps/delays still have to be restarted manualy, but i provide convenient wrapper called pthread_nanosleep() which does just that.
UPDATE6: i realized that simply restarting nanosleep() is not enough, because that way timeout does not run when thread is paused. Therefore i’ve modified pthread_nanosleep() to convert timeout interval to absolute time point in the future and sleep until that. Also i’ve hidden semaphore initialization, so user does not need to do that.
pthread sleep linux
I am creating a program with multiple threads using pthreads. Is sleep() causing the process (all the threads) to stop executing or just the thread where I am calling sleep ?
6 Answers 6
The sleep() function shall cause the calling thread to be suspended from execution.
Here’s what «man 3 sleep» says: «sleep() makes the calling process sleep until seconds seconds have elapsed. » (Ubuntu 10). The function is in unistd.h. Is this documentation wrong or is there a second sleep function?
@user48956: For historical reasons, the man pages often use «process» where the behaviour now applies to the «thread» — this is the case in the sleep(3) man page that you refer to. I suggest submitting a bug to Ubuntu about the documentation.
#include usleep(microseconds);
Note that usleep() is obsolete and has been removed from POSIX.1-2008. You should use either sleep(), or nanosleep() if higher resolution is required.
I usually use nanosleep and it works fine. Nanosleep supends the execution of the calling thread. I have had the same doubt because in some man pages sleep refers to the entire process.
In practice, there are few cases where you just want to sleep for a small delay (milliseconds). For Linux, read time(7), and see also this answer. For a delay of more than a second, see sleep(3), for a small delay, see nanosleep(2). (A counter example might be a RasPerryPi running some embedded Linux and driving a robot; in such case you might indeed read from some hardware device every tenth of seconds). Of course what is sleeping is just a single kernel-scheduled task (so a process or thread).
It is likely that you want to code some event loop. In such a case, you probably want something like poll(2) or select(2), or you want to use condition variables (read a Pthread tutorial about pthread_cond_init etc. ) associated with mutexes.
Threads are expensive resources (since each needs a call stack, often of a megabyte at least). You should prefer having one or a few event loops instead of having thousands of threads.
sleep() function does not cease a specific thread, but it stops the whole process for the specified amount of time. For stopping the execution of a particular thread, we can use one pthread condition object and use pthread_cond_timedwait() function for making the thread wait for a specific amount of time. Each thread will have its own condition object and it will never receive a signal from any other thread.
This is inaccurate. The sleep() will cause the current thread to sleep. See sleep(3) . Lots of older man pages still use the word «process,» but in reality a thread is a process.