As part of a multi-threaded code that I am designing, I am using mutexes to control access to a shared data segments in the code. I have no problems initalising and manipulating the mutexes to control access, however terminating the mutex itself is proving to be a bit difficult.
I am terminating the mutex in the following way
Code:
/* If critical section is being accessed,
get current thread to leave it*/
if(lock_flag == 1)
pthread_mutex_unlock( &cs_mutex);
if( (ret = pthread_mutex_destroy(&cs_mutex)) != 0)
{
printf("\nError occurred in terminating mutex");
exit(1);
}
Is this an appropriate way of terminating the mutex ? If not could someone please advise a much better strategy ?
Thanks for your post. In this regard, I was wondering if you could elaborate on it to convince me why I should use pthread_cond_wait(). AFAIK, pthread_cond_wait() causes the mutex lock to be released and blocks the calling thread on a certain condition variable value.
If the calling thread is blocked (which is the thread associated with main() in my case), wouldn't this make it even more difficult to terminate the mutex ?
In your case it would not make sense. It would serialize the program flow which is not what you want probably.
The reason I suggested using pthread_cond_wait (somewhat naively) is that I don't see any locking around your lock_flag variable. If that's the case and multiple threads could access the variable...races abound.
Here's an entirely contrived example for clarity. it's a useless exercise of course.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#define INTERVAL 5
int flag = 0;
pthread_cond_t waitvar = PTHREAD_COND_INITIALIZER;
pthread_mutex_t *mutex_create(pthread_mutexattr_t * attr)
{
pthread_mutex_t *new_mutex;
if ((new_mutex = malloc(sizeof(pthread_mutex_t))) == NULL) {
return NULL;
}
pthread_mutexattr_init(attr);
pthread_mutex_init(new_mutex, attr);
return new_mutex;
}
void *create_and_wait(void *mtx)
{
time_t now, then;
pthread_mutex_t *amtx = mtx;
now = then = time(NULL);
while ((now = time(NULL)) < then + INTERVAL) {
sleep(1);
printf("In thread %d doing countdown.\n", pthread_self());
}
pthread_mutex_lock(amtx);
flag = pthread_self();
pthread_cond_broadcast(&waitvar);
pthread_mutex_unlock(amtx);
pthread_exit(NULL);
}
int main(void)
{
int y = 0, oldflag = flag;
pthread_t _thread;
pthread_mutexattr_t new;
pthread_mutex_t *tmtx;
while ((y++) < INTERVAL) {
if ((tmtx = mutex_create(&new)) == NULL) {
break;
} /*might as well be NULL - but new could be set to whatever */
pthread_mutex_lock(tmtx); /*obtain lock before blocking on mutex */
pthread_create(&_thread, NULL, create_and_wait, tmtx);
/*
* wait for thread to signal it's wait is over via setting the flag variable to it's thread id and calling pthread_cond_signal
* join on the exited thread and reset oldflag
* unlock the temp mutex - must be done before calling pthread_mutex_destroy or EBUSY
* clear the mutex attributes, etc.. (whatever pthread_mutex_destroy does for the implementation)
* cleanup and start over
*/
while (flag == oldflag) {
pthread_cond_wait(&waitvar, tmtx);
pthread_join(flag, NULL);
oldflag = flag;
pthread_mutex_unlock(tmtx);
printf("Thread id %d exited.\npthread_mutex_destroy = %d.\n",
flag, pthread_mutex_destroy(tmtx));
printf("Mutex at %p.\n", tmtx);
free(tmtx);
tmtx = NULL;
break;
}
}
return y;
}