pthread_mutex_timedlock() exiting prematurely without waiting for timeout - c

I want to protect a function from multithreaded access. For that purpose I am using a pthread_mutex_t mutex. I try to lock it in the beginning of a function, then execute the function, then release it again. If the mutex is in use it should wait for at maximum 60 seconds for it to be come available. If after that it is still not available, the function should fail.
The problem I'm having is it that pthread_mutex_timedlock seems to completely ignore the timeout value I'm giving it. Although I specify a timeout of 60 seconds, if the lock is taken, the function returns immediately with the error code ETIMEDOUT -- without actually waiting.
Here is a minimal example which reproduces the problem. In this case it does not matter whether I'm using recursive or non-recursive mutexes, since I'm not trying to lock them multiple times from the same thread.
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stddef.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <pthread.h>
pthread_mutex_t lock; /* exclusive lock */
//do some work to keep the processor busy..
int wut() {
int x = 0;
for(int i=0; i < 1024*1024*1024; i++)
x += 1;
return x;
}
void InitMutex(){
/*pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&lock, &Attr);*/
pthread_mutex_init(&lock, NULL);
}
//lock mutex, wait at maximum 60 seconds, return sucesss
int LockMutex() {
struct timespec timeoutTime;
timeoutTime.tv_nsec = 0;
timeoutTime.tv_sec = 60;
printf("Nanoseconds: %lu, seconds %lu\n", timeoutTime.tv_nsec, timeoutTime.tv_sec);
int retVal = pthread_mutex_timedlock(&lock, &timeoutTime);
printf("pthread_mutex_timedlock(): %d\n", retVal);
if(retVal != 0) {
const char* errVal = NULL;
switch(retVal) {
case EINVAL: errVal = "EINVAL"; break;
case EAGAIN: errVal = "EAGAIN"; break;
case ETIMEDOUT: errVal = "ETIMEDOUT"; break;
case EDEADLK: errVal = "EDEADLK"; break;
default: errVal = "unknown.."; break;
}
printf("Error taking lock in thread %lu: %s (%s)\n", pthread_self(), errVal , strerror(retVal));
}
return retVal == 0; //indicate success/failure
}
void UnlockMutex() {
pthread_mutex_unlock(&lock);
}
void TestLockNative() {
uint64_t thread_id = pthread_self();
printf("Trying to take lock in thread %lu.\n", thread_id);
int ret = LockMutex();
printf("Got lock in thread %lu. sucess=%d\n", thread_id, ret);
wut();
printf("Giving up lock now from thread %lu.\n", thread_id);
UnlockMutex();
}
void* test_thread(void* arg) {
//TestLock();
TestLockNative();
return NULL;
}
int main() {
InitMutex();
//create two threads which will try to access the protected function at once
pthread_t t1, t2;
pthread_create(&t1, NULL, &test_thread, NULL);
pthread_create(&t2, NULL, &test_thread, NULL);
//wait for threads to end
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
The output of the program is e.g.:
Trying to take lock in thread 139845914396416.
Nanoseconds: 0, seconds 6000
pthread_mutex_timedlock(): 0
Got lock in thread 139845914396416. sucess=1
Trying to take lock in thread 139845906003712.
Nanoseconds: 0, seconds 6000
pthread_mutex_timedlock(): 110
Error taking lock in thread 139845906003712: ETIMEDOUT (Connection timed out) [<-- this occurs immediately, not after 60 seconds]
Got lock in thread 139845906003712. sucess=0
Giving up lock now from thread 139845906003712.
Compilation with gcc -o test test.c -lpthread should work.
So, does anyone know what's going on here and why pthread_mutex_timedlock() ignores my timeout value? It does not behave the way it is documented at all.
I'm using a Ubuntu 16.04.2 LTS system, compiling with gcc.

The manual page for pthread_mutex_timedlock says:
The timeout shall expire when the absolute time specified by abstime passes, as measured
by the clock on which timeouts are based
Therefore, use real time to specify your timeout value:
int LockMutex() {
struct timespec timeoutTime;
clock_gettime(CLOCK_REALTIME, &timeoutTime);
timeoutTime.tv_sec += 60;
int retVal = pthread_mutex_timedlock(&lock, &timeoutTime);
....

Related

C Pthread: Running only 10 threads simultaneously (what is the problem here)

So I'm very new to the whole concept of pthread in C but please hear me out. I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t endCond = PTHREAD_COND_INITIALIZER;
static pthread_cond_t startCond = PTHREAD_COND_INITIALIZER;
void * threadThingy(void * n){
pthread_cond_wait(&startCond, &mutex);
printf("%d: RAND: %d\n", *((int*)n), rand());
//Lock mutex before broadcasting to main thread
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&endCond);
pthread_mutex_unlock(&mutex);
free(n);
fflush(stdout);
return 0;
}
int main(void){
printf("Starting\n");
pthread_t threads[100];
int i = 0;
while(i < 10){
int *arg = malloc(sizeof(int));
*arg = i;
pthread_create(&threads[i], NULL, threadThingy, arg);
i++;
}
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&startCond);
int finished = 0;
while(finished <= 100){
pthread_cond_wait(&endCond, &mutex);
//Lock mutex so no other requests can come in
pthread_mutex_lock(&mutex);
finished++;
int *arg = malloc(sizeof(int));
*arg = 11;
pthread_create(threads[i], NULL, threadThingy, arg);
i++;
pthread_cond_broadcast(&startCond);
pthread_mutex_unlock(&mutex);
}
printf("Stopping\n");
sleep(1000);
}
The whole goal is to run (only) 10 threads simultaneously of the 100. My idea was to start 10 threads, than wait until one is finished and start another one. So I let the program wait until a thread returns, then I start a new one so the thread that just returned gets replaced. What have I missed? Because now I only get this as an output:
Starting
0: RAND: 1804289383
As mentioned by Lavigne958, in function threadThingy() there is deadlock caused by pthread_cond_wait() as it will acquire the lock. Again, you are trying to lock it in next line. This is causing deadlock.
There are a few things need to check:
You need to lock the mutex before calling pthread_cond_wait().
If you solve the above issue, using multiple condition variable with the same mutex may cause further deadlock.
If you are not joining the threads, it will be better to create detached threads using PTHREAD_CREATE_DETACHED attribute.
The problem of N number of threads running simultaneously can be solved with one semaphore OR one condition variable(and one mutex). Example with semaphore is given below.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
sem_t mysem;
#define NUM_CONCURRENT_THREADS 4
#define MAX_THREADS 40
void *thread(void *arg)
{
printf("Thread id %ld: started\n", pthread_self());
sleep(5); // Do some work
printf("Thread id %ld: Exiting\n", pthread_self());
sem_post(&mysem);
return NULL;
}
int main()
{
pthread_t t[MAX_THREADS];
pthread_attr_t attr;
int rc, i = 0;
sem_init(&mysem, 0, NUM_CONCURRENT_THREADS);
rc = pthread_attr_init(&attr);
rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
printf("\nParent begin\n");
while(i < MAX_THREADS)
{
sem_wait(&mysem);
pthread_create(&t[i], &attr, thread, NULL);
i++;
}
printf("\nParent end.\n");
sem_destroy(&mysem);
return 0;
}
Please check blog Tech Easy for more information on threads.
in the function that your threads run, you start by waiting on a condition but you forgot to take the mutex before. So you first must take the mutex before waiting on the condition.
you have what we call a deadlock.
What happens is:
the first thread wakes up (the pthread_con_wait function acquires the lock for you already)
then you try to acquire the lock again => deadlock because you already own the lock so you kinda deadlock yourself.

Pthread: lock PTHREAD_MUTEX_ERRORCHECK mutex from non-owner thread

classical question please;
I didn't find confirmation from code;
C language.
I'm running the below code on Windows.
/* This is an implementation of the threads API of POSIX 1003.1-2001.*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
//equivalent to PTHREAD_MUTEX_ERRORCHECK
void* thread_function(void *args)
{
int rc;
rc = pthread_mutex_unlock( & mutex );
printf( "[thread_function] pthread_mutex_unlock rc: %d \n", rc);
return 0;
}
int main(int argc, char* argv[])
{
int rc;
pthread_t id;
pthread_mutex_lock( &mutex );
rc = pthread_create(&id, NULL, thread_function, NULL);
pthread_join(id, NULL);
printf( "[main] completed\n");
}
rc = pthread_mutex_unlock( & mutex ); - returns rc equal to 1 which is as expected.
but when I change the code to rc = pthread_mutex_lock( & mutex ); - the error does not occur.
But in many Pthread API doc it is mentioned that:
"If the mutex type is PTHREAD_MUTEX_ERRORCHECK, then error checking shall be provided. If a thread attempts to relock a mutex that it has already locked, an error shall be returned."
But it is not returned for me, and the question why?
The only guess I have - it depends on PThread realization which I'm using.
And it also may depend on OS; i.e. same code and the same version of Pthread lib will give different result on Linux.
Can anyone please clarify?
Thanks!
When a thread tries to lock a mutex locked by another thread, it blocks. This is of course the whole point: it would be useless if it were an error. The error checking is for programs where a thread might try to lock a mutex it has already locked. That usually results from a logic bug, although one could simulate a recursive mutex with it or perhaps use the locked state of the mutex as some sort of memory.
Generally, when you tried to lock mutex(Default Type) second time in the same thread your code has been blocked. To prevent this blocking situation, error checking mutex is used.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#define IN_MAIN ""
#define IN_THREAD "\t"
#define START_MAIN printf(IN_MAIN "\n-- Main Start -- \n");
#define END_MAIN printf(IN_MAIN "-- Main End -- \n\n"); \
exit(EXIT_SUCCESS);
#define ERROR_HANDLER(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void * thread_routine(void * arg)
{
printf(IN_THREAD "-- Thread Start -- \n");
int ret;
pthread_mutex_lock(&mutex);
printf(IN_THREAD " Thread acquire lock for first time \n");
ret = pthread_mutex_lock(&mutex);
if(ret)
{
switch(ret)
{
case EDEADLK:
printf(IN_THREAD " A deadlock condition was detected \n");
break;
default:
ERROR_HANDLER(ret, "pthread_mutex_lock");
}
}
sleep(1);
ret = pthread_mutex_unlock(&mutex);
printf(IN_THREAD " Thread release lock first time -- %d \n", ret);
sleep(1);
ret = pthread_mutex_unlock(&mutex);
printf(IN_THREAD " Thread release lock second time -- %d \n", ret);
printf(IN_THREAD "-- Thread End --\n");
pthread_exit(NULL);
}
int main(int argc, char ** argv)
{
START_MAIN;
pthread_t thread_id;
pthread_mutexattr_t mutex_attr;
int mutex_type, ret=0;
pthread_mutexattr_init(&mutex_attr);
ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
if(ret)
ERROR_HANDLER(ret, "pthread_mutexattr_settype");
pthread_mutex_init(&mutex, &mutex_attr);
pthread_create(&thread_id, NULL, thread_routine, NULL);
pthread_join(thread_id, NULL);
END_MAIN;
}
Consider above example, when you execute the above code, it print "A deadlock condition was detected". This is because of the type of mutex is error check.
Now comment the line
ret = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
and execute the code. You'll notice your code is blocked after it print "Thread acquire lock for first time".
One of the mistakes in the Posix spec is the notion of "default" mutex type -- which is implementation dependent. Meaning the the semantics of a "default" mutex is any ones guess. Confusing? You bet.
My advice is to never use "default" for mutex type if you care about portability at all.

How to properly suspend multiple threads with posix signals?

In the context of an existing multi-threaded application I want to suspend a list of threads for a specific duration then resume their normal execution. I know some of you wil say that I should not do that but I know that and I don't have a choice.
I came up with the following code that sort of work but randomly failed. For each thread I want to suspend, I send a signal and wait for an ack via a semaphore. The signal handler when invoked, post the semaphore and sleep for the specified duration.
The problem is when the system is fully loaded, the call to sem_timedwait sometimes fails with ETIMEDOUT and I am left with an inconsistent logic with semaphore used for the ack: I don't know if the signal has been dropped or is just late.
// compiled with: gcc main.c -o test -pthread
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define NUMTHREADS 40
#define SUSPEND_SIG (SIGRTMIN+1)
#define SUSPEND_DURATION 80 // in ms
static sem_t sem;
void checkResults(const char *msg, int rc) {
if (rc == 0) {
//printf("%s success\n", msg);
} else if (rc == ESRCH) {
printf("%s failed with ESRCH\n", msg);
} else if (rc == EINVAL) {
printf("%s failed with EINVAL\n", msg);
} else {
printf("%s failed with unknown error: %d\n", msg, rc);
}
}
static void suspend_handler(int signo) {
sem_post(&sem);
usleep(SUSPEND_DURATION*1000);
}
void installSuspendHandler() {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = suspend_handler;
int rc = sigaction(SUSPEND_SIG, &sa, NULL);
checkResults("sigaction SUSPEND", rc);
}
void *threadfunc(void *param) {
int tid = *((int *) param);
free(param);
printf("Thread %d entered\n", tid);
// this is an example workload, the real app is doing many things
while (1) {
int rc = sleep(30);
if (rc != 0 && errno == EINTR) {
//printf("Thread %d got a signal delivered to it\n", tid);
} else {
//printf("Thread %d did not get expected results! rc=%d, errno=%d\n", tid, rc, errno);
}
}
return NULL;
}
int main(int argc, char **argv) {
pthread_t threads[NUMTHREADS];
int i;
sem_init(&sem, 0, 0);
installSuspendHandler();
for(i=0; i<NUMTHREADS; ++i) {
int *arg = malloc(sizeof(*arg));
if ( arg == NULL ) {
fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
exit(EXIT_FAILURE);
}
*arg = i;
int rc = pthread_create(&threads[i], NULL, threadfunc, arg);
checkResults("pthread_create()", rc);
}
sleep(3);
printf("Will start to send signals...\n");
while (1) {
printf("***********************************************\n");
for(i=0; i<NUMTHREADS; ++i) {
int rc = pthread_kill(threads[i], SUSPEND_SIG);
checkResults("pthread_kill()", rc);
printf("Waiting for Semaphore for thread %d ...\n", i);
// compute timeout abs timestamp for ack
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
const int TIMEOUT = SUSPEND_DURATION*1000*1000; // in nano-seconds
ts.tv_nsec += TIMEOUT; // timeout to receive ack from signal handler
// normalize timespec
ts.tv_sec += ts.tv_nsec / 1000000000;
ts.tv_nsec %= 1000000000;
rc = sem_timedwait(&sem, &ts); // try decrement semaphore
if (rc == -1 && errno == ETIMEDOUT) {
// timeout
// semaphore is out of sync
printf("Did not received signal handler sem_post before timeout of %d ms for thread %d", TIMEOUT/1000000, i);
abort();
}
checkResults("sem_timedwait", rc);
printf("Received Semaphore for thread %d.\n", i);
}
sleep(1);
}
for(i=0; i<NUMTHREADS; ++i) {
int rc = pthread_join(threads[i], NULL);
checkResults("pthread_join()\n", rc);
}
printf("Main completed\n");
return 0;
}
Questions?
Is it possible for a signal to be dropped and never delivered?
What causes the timeout on the semaphore at random time when the system is loaded?
usleep() is not among the async-signal-safe functions (though sleep() is, and there are other async-signal-safe functions by which you can produce a timed delay). A program that calls usleep() from a signal handler is therefore non-conforming. The specifications do not describe what may happen -- neither with such a call itself nor with the larger program execution in which it occurs. Your questions can be answered only for a conforming program; I do that below.
Is it possible for a signal to be dropped and never delivered?
It depends on what exactly you mean:
If a normal (not real-time) signal is delivered to a thread that already has that signal queued then no additional instance is queued.
A thread can die with signals still queued for it; those signals will not be handled.
A thread can change a given signal's disposition (to SIG_IGN, for example), though this is a per-process attribute, not a per-thread one.
A thread can block a signal indefinitely. A blocked signal is not dropped -- it remains queued for the thread and will eventually be received some time after it is unblocked, if that ever happens.
But no, having successfully queued a signal via the kill() or raise() function, that signal will not be randomly dropped.
What causes the timeout on the semaphore at random time when the system is loaded?
A thread can receive a signal only when it is actually running on a core. On a system with more runnable processes than cores, some runnable processes must be suspended, without a timeslice on any core, at any given time. On a heavily-loaded system, that's the norm. Signals are asynchronous, so you can send one to a thread that is currently waiting for a timeslice without the sender blocking. It is entirely possible, then, that the thread you have signaled does not get scheduled to run before the timeout expires. If it does run, it may have the signal blocked for one reason or another, and not get around to unblocking it before it uses up its timeslice.
Ultimately, you can use your semaphore-based approach to check whether the target thread handled the signal within any timeout of your choice, but you cannot predict in advance how long it will take for the thread to handle the signal, nor even whether it will do so in any finite amount of time (for example, it could die for one reason or another before doing so).

Is this a correct solution to measure thread context switch overhead?

I'm trying to measure thread switch overhead time.
I have two threads, a shared variable, a mutex lock, and two condition variables. Two threads will switch back and forth to write either a 1 or a 0 to the shared variable.
I'm assuming the pthread_cond_wait(&cond, &mutex) wait time is approximately equal to 2 x thread context switch time. Since if a thread1 has to wait for a condition variable it has to give up the mutex lock to the thread2->thread2 context switch-> thread2 performs its task and signals the condition variable to wake up the first thread
->context switch back to thread1->thread1 reacquires the lock.
Is my assumption correct?
My code is below:
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <dirent.h>
#include <ctype.h>
#include<signal.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <pthread.h>
int var = 0;
int setToZero = 1;
int count = 5000;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t isZero = PTHREAD_COND_INITIALIZER;
pthread_cond_t isOne = PTHREAD_COND_INITIALIZER;
struct timespec firstStart;
unsigned long long timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
void* thread1(void* param)
{
int rc;
struct timespec previousStart;
struct timespec start; //start timestamp
struct timespec stop; //stop timestamp
unsigned long long result;
int idx = 0;
int measurements[count];
clock_gettime(CLOCK_MONOTONIC, &stop);
result = timespecDiff(&stop,&firstStart);
printf("first context-switch time:%llu\n", result);
clock_gettime(CLOCK_MONOTONIC, &previousStart);
while(count > 0){
//acquire lock
rc = pthread_mutex_lock(&mutex);
clock_gettime(CLOCK_MONOTONIC,&start);
while(setToZero){
pthread_cond_wait(&isOne,&mutex); // use condition variables so the threads don't busy wait inside local cache
}
clock_gettime(CLOCK_MONOTONIC,&stop);
var = 0;
count--;
setToZero = 1;
//printf("in thread1\n");
pthread_cond_signal(&isZero);
//end of critical section
rc = pthread_mutex_unlock(&mutex); //release lock
result = timespecDiff(&stop,&start);
measurements[idx] = result;
idx++;
}
result = 0;
int i = 0;
while(i < idx)
{
result += measurements[i++];
}
result = result /(2*idx);
printf("thread1 result: %llu\n",result);
}
void* thread2(void* param)
{
int rc;
struct timespec previousStart;
struct timespec start; //start timestamp
struct timespec stop; //stop timestamp
unsigned long long result;
int idx = 0;
int measurements[count];
while(count > 0){
//acquire lock
rc = pthread_mutex_lock(&mutex);
clock_gettime(CLOCK_MONOTONIC,&start);
while(!setToZero){
pthread_cond_wait(&isZero,&mutex);
}
clock_gettime(CLOCK_MONOTONIC,&stop);
var = 1;
count--;
setToZero = 0;
//printf("in thread2\n");
pthread_cond_signal(&isOne);
//end of critical section
rc = pthread_mutex_unlock(&mutex); //release lock
result = timespecDiff(&stop,&start);
measurements[idx] = result;
idx++;
}
result = 0;
int i = 0;
while(i < idx)
{
result += measurements[i++];
}
result = result /(2*idx);
printf("thread2 result: %llu\n",result);
}
int main(){
pthread_t threads[2];
pthread_attr_t attr;
pthread_attr_init(&attr);
clock_gettime(CLOCK_MONOTONIC,&firstStart);
pthread_create(&threads[0],&attr,thread1,NULL);
pthread_create(&threads[1],&attr,thread2,NULL);
printf("waiting...\n");
pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);
pthread_cond_destroy(&isOne);
pthread_cond_destroy(&isZero);
}
I get the following times:
first context-switch time:144240
thread1 result: 3660
thread2 result: 3770
You say:
I'm assuming the pthread_cond_wait(&cond, &mutex) wait time is approximately equal to 2 x thread context switch time.
This is not a valid assumption. Once the mutex is released, this notifies the kernel, which then has to wake the other thread. It may not choose to do that immediately for example if there are other threads waiting to run. The mutex - as its name suggests - guarantees when things will not happen. It makes no guarantees about when they will.
You can't expect to reliably measure context switches from within a process, and certainly not using a Posix API because there is none which promises to do that.
On Linux you can count context switches for a process or thread using /proc/[pid]/status.
On Windows this information is available from the Performance Monitor API.
Whether either of these will get you towards your goal I don't know. I suspect what you really want to know is how much using a multithreaded system affects performance, but that'll require you to measure the performance of the application as a whole.

pthread_cond_timedwait call is not working with mutex locking mechanism

I have a logging application. In which after specific time (user configureable time) i need to close the current log file and and create a new log file and log the data.
There are 2 critical sections of code in my program.
Writing the data to file (in while(1))
Close and open the new file
Whenever time expires i need to stop the logging to the file and close it & open the new log file and start logging.
For this purpose i have created a sample application exactly same as my application, but instead of file operation here am doing with printf.
I am using pthread_cond_timedwait call to handle the timer related operation. Here is my sample code -
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>
#include <pthread.h>
/* For safe condition variable usage, must use a boolean predicate and */
/* a mutex with the condition. */
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#define WAIT_TIME_SECONDS 10
void *threadfunc(void *parm)
{
int rc;
struct timespec abstime;
struct timeval now;
/* Usually worker threads will loop on these operations */
while (1) {
rc = gettimeofday(&now, NULL);
/* Convert from timeval to timespec */
abstime.tv_sec = now.tv_sec + WAIT_TIME_SECONDS;
abstime.tv_nsec = (now.tv_usec + 1000UL * WAIT_TIME_SECONDS) * 1000UL;
abstime.tv_sec += abstime.tv_nsec / (1000 * 1000 * 1000);
abstime.tv_nsec %= (1000 * 1000 * 1000);
printf("Thread blocked\n");
pthread_mutex_lock(&mutex);
rc = pthread_cond_timedwait(&cond, &mutex, &abstime);
pthread_mutex_unlock(&mutex);
printf("Wait timed out!\n");
/* critical section of code */
pthread_mutex_lock(&lock);
printf("Thread consumes work here\n");
pthread_mutex_unlock(&lock);
}
return NULL;
}
int main(int argc, char **argv)
{
int rc=0;
pthread_t threadid;
rc = pthread_create(&threadid, NULL, threadfunc, NULL);
if (rc != 0) {
printf("Thread creation failed err:%d\n", errno);
return -1;
}
while (1) {
/* critical section of code */
sleep(1);
pthread_mutex_lock(&lock);
printf("One work item to give to a thread\n");
pthread_mutex_unlock(&lock);
}
printf("Wait for threads and cleanup\n");
pthread_join(threadid, NULL);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
printf("Main completed\n");
return 0;
}
This code is not working. Whenever pthread_cond_timedwait expires threadfunc function should acquire mutex lock and it needs print the statements. After printing am releasing the mutex. But it is not happening. Control is never transfered from main() to threadfunc. Whats is going wrong here?
But instead of mutex if i use a variable to do the handling of critical section of code am able to do it. Say -
static int stop = 0; // take a global variable
//inside threadfunc
/* critical section of code */
stop = 1; //Replace pthread_mutex_lock with this
printf("Thread consumes work here\n");
stop = 0; //Replace pthread_mutex_unlock with this
//in main()
while (1) {
/* critical section of code */
sleep(1);
if (!stop)
printf("One work item to give to a thread\n");
}
This approach is working fine.
When i am using more then one mutex in my code am not able to implement this. What is the real thing happening behind? Am i missing anything while am using mutex to handle critical section of a code?
Thanks in advance!

Resources