How to Sleep or Pause a Pthread in C on Linux

How to sleep or pause a PThread in c on Linux

You can use a mutex, condition variable, and a shared flag variable to do this. Let's assume these are defined globally:

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int play = 0;

You could structure your playback code like this:

for(;;) { /* Playback loop */
pthread_mutex_lock(&lock);
while(!play) { /* We're paused */
pthread_cond_wait(&cond, &lock); /* Wait for play signal */
}
pthread_mutex_unlock(&lock);
/* Continue playback */
}

Then, to play you can do this:

pthread_mutex_lock(&lock);
play = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);

And to pause:

pthread_mutex_lock(&lock);
play = 0;
pthread_mutex_unlock(&lock);

pthread sleep linux

Just the thread. The POSIX documentation for sleep() says:

The sleep() function shall cause the calling thread to be suspended from execution...

How to pause a pthread ANY TIME I want?

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.

Does calling sleep() from pthread put thread to sleep or process?

The wording in your man page is likely wrong. Trust the standard and trust the man page on kernel.org. Write to the maintainer of the documentation for your distro and tell them to update the manual pages.

Portable way to make a thread sleep for a certain time or until woken up

After some research, it seems events on WinAPI are closest to what I am trying to accomplish, and they have been around since at least Windows XP (I believe even earlier versions had it). On POSIX, the closest match really are conditional variables, though the mutex is not really necessary.

Since the project implements its own thread abstraction wrapper, this gives us some extra freedom.

We’ll introduce a data type event. This is an opaque data structure. On Windows, this corresponds to an event (created as an auto-reset event); on POSIX, this is a struct holding a condition and a mutex.

When a thread goes to sleep, the POSIX implementation locks the mutex, calls pthread_cond_timedwait and unlocks the mutex as soon as it continues. The Windows implementation just calls WaitForSingleObject.

To wake up the sleeping thread, the POSIX implementation locks the mutex, calls pthread_cond_signal and unlocks the mutex again. The Windows implementation calls SetEvent.

On Windows, events can be auto-reset or not. An auto-reset event will be reset as soon as the first waiting thread is woken up (so it will never wake up more than one thread), but will remain set if that thread happens to be running at the time the event is signaled. Other events will remain in signaled state until explicitly reset, thus they can wake up any number of threads or even prevent them from going to sleep in the first place.

On POSIX, a condition can be signaled (waking up one waiting thread) or broadcast (waking up all waiting threads). As I understand it, it is reset after it fires, even if no thread got woken up.

Thus, as long as we never have more than one thread waiting on the same event, auto-reset events on Windows behave much like pthread_cond_signal on POSIX. The only difference is that we need to reset the event after handling it. Our thread abstraction wrapper needs to provide a function for that, which calls ResetEvent on Windows and is a no-op on POSIX.

Unlike conditions, this construct does not provide a mutex to provide synchronized access. Therefore, if the waiting and the signaling thread access a shared data structure, they must implement their own mechanism to synchronize access, e.g. using a mutex or lock.

How to suspend and resume a POSIX thread in C++?

After a little modification of above code , it seems working . Thanks guy for pointing out issues on above code, the changes are as follow.

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<iostream>
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);

class PThread {
public:

pthread_t threadID;
volatile int suspended;
int fd;
pthread_mutex_t lock;
PThread(int fd1)
{
this->fd=fd1;
this->suspended =1; //Initial state: suspend blinking untill resume call
pthread_mutex_init(&this->lock,NULL);
pthread_create(&this->threadID, NULL, led_Flash, (void*)this );

}
~PThread()
{
pthread_join(this->threadID , NULL);
pthread_mutex_destroy(&this->lock);
}

void suspendBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 1;
pthread_mutex_unlock(&this->lock);
}

void resumeBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 0;
pthread_mutex_unlock(&this->lock);
}
};

void gpio_write(int fd, int value)
{
if(value!=0)
printf("%d: on\n", fd);
else
printf("%d: off\n", fd);
}

void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int fd= pt->fd;

while(1)
{
if(!(pt->suspended))
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
}

return NULL;
}

int main()
{
//Create threads with Initial state: suspend/stop blinking untill resume call
class PThread redLED(1);
class PThread amberLED(2);
class PThread greenLED(3);

// Start blinking
redLED.resumeBlink();
amberLED.resumeBlink();
greenLED.resumeBlink();
sleep(5);

// suspend/stop blinking
amberLED.suspendBlink();

sleep(5);

redLED.suspendBlink();

sleep(5);

amberLED.suspendBlink();

sleep(5);

redLED.resumeBlink();

pthread_exit(NULL);

return 0;
}

How to pause execution between threads?

I did some research and found that the only way to produce the desired output is the one I mentioned in the Update part. That is, instead of hard coded the sleep timer, just give each thread a random number:

    // Sleep time in microseconds.
int st = rand() % 500000;
usleep(st);

And actually I have been over-worrying about two threads doing the same thing at once. Even though the two adjacent random timers could be accidentally the same, two threads never get executed on the same core of the CPU at the same time, in case the CPU is of multiple cores, no two instructions can modify the same memory content concurrently.

Is there an alternative sleep function in C to milliseconds?

Yes - older POSIX standards defined usleep(), so this is available on Linux:

int usleep(useconds_t usec);

DESCRIPTION

The usleep() function suspends execution of the calling thread for
(at least) usec microseconds. The sleep may be lengthened slightly by
any system activity or by the time spent processing the call or by the
granularity of system timers.

usleep() takes microseconds, so you will have to multiply the input by 1000 in order to sleep in milliseconds.


usleep() has since been deprecated and subsequently removed from POSIX; for new code, nanosleep() is preferred:

#include <time.h>

int nanosleep(const struct timespec *req, struct timespec *rem);

DESCRIPTION

nanosleep() suspends the execution of the calling thread until either at least the time specified in *req has elapsed, or the
delivery of a signal that triggers the invocation of a handler in the
calling thread or that terminates the process.

The structure timespec is used to specify intervals of time with nanosecond precision. It is defined as follows:

struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};

An example msleep() function implemented using nanosleep(), continuing the sleep if it is interrupted by a signal:

#include <time.h>
#include <errno.h>

/* msleep(): Sleep for the requested number of milliseconds. */
int msleep(long msec)
{
struct timespec ts;
int res;

if (msec < 0)
{
errno = EINVAL;
return -1;
}

ts.tv_sec = msec / 1000;
ts.tv_nsec = (msec % 1000) * 1000000;

do {
res = nanosleep(&ts, &ts);
} while (res && errno == EINTR);

return res;
}


Related Topics



Leave a reply



Submit