In this example, different mutexes are used to protect the variables
count1, count2, and
count3. Since the three functions
waiter1(), waiter2(), and
each wait on the same condition variable
cv with different mutexes, the call to
pthread_cond_wait succeeds for one of the threads and the
call is undefined for the other two.
Polyspace reports a violation for function waiter3() even
though the function is not invoked directly or indirectly by a thread, entry-point,
or interrupt. The analysis considers function waiter3() called by
main() through its function address or by an unidentified
thread.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#define Thrd_return_ void *
#define __USE_XOPEN2K8
#define COUNT_LIMIT 5
static void fatal_error(void)
{
exit(1);
}
pthread_mutex_t mutex1;
pthread_mutex_t mutex2;
pthread_mutex_t mutex3;
pthread_cond_t cv;
int count1 = 0, count2 = 0, count3 = 0;
#define DELAY 8
Thrd_return_t waiter1(void* arg)
{
int ret;
while (count1 < COUNT_LIMIT) {
if ((ret = pthread_mutex_lock(&mutex1)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret =
pthread_cond_wait(&cv, &mutex1)) != 0) { //Noncompliant
/* Handle error */
fatal_error();
}
sleep(random() % DELAY);
printf("count1 = %d\n", ++count1);
if ((ret = pthread_mutex_unlock(&mutex1)) != 0) {
/* Handle error */
fatal_error();
}
}
return (Thrd_return_t)0;
}
Thrd_return_t waiter2(void* arg)
{
int ret;
while (count2 < COUNT_LIMIT) {
if ((ret = pthread_mutex_lock(&mutex2)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret =
pthread_cond_wait(&cv, &mutex2)) != 0) { //Noncompliant
/* Handle error */
fatal_error();
}
sleep(random() % DELAY);
printf("count2 = %d\n", ++count2);
if ((ret = pthread_mutex_unlock(&mutex2)) != 0) {
/* Handle error */
fatal_error();
}
}
return (Thrd_return_t)0;
}
Thrd_return_t signaler(void* arg)
{
int ret;
while ((count1 < COUNT_LIMIT) || (count2 < COUNT_LIMIT)) {
sleep(1);
printf("signaling\n");
if ((ret = pthread_cond_broadcast(&cv)) != 0) {
/* Handle error */
fatal_error();
}
}
return (Thrd_return_t)0;
}
Thrd_return_t waiter3(void* arg)
{
int ret;
while (count3 % COUNT_LIMIT != 0) {
if ((ret = pthread_mutex_lock(&mutex3)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret =
pthread_cond_wait(&cv, &mutex3)) != 0) { //Noncompliant
/* Handle error */
fatal_error();
}
sleep(random() % DELAY);
printf("count3 = %d\n", ++count3);
if ((ret = pthread_mutex_unlock(&mutex3)) != 0) {
/* Handle error */
fatal_error();
}
}
return (Thrd_return_t)0;
}
int main(void)
{
int ret;
pthread_t thread1, thread2, thread3;
pthread_mutexattr_t attr;
if ((ret = pthread_mutexattr_init(&attr)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_mutex_init(&mutex1, &attr)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_mutex_init(&mutex2, &attr)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_mutex_init(&mutex3, &attr)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_cond_init(&cv, NULL)) != 0) {
/* handle error */
fatal_error();
}
if ((ret = pthread_create(&thread1, NULL, &waiter1, NULL))) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_create(&thread2, NULL, &waiter2, NULL))) {
/* handle error */
fatal_error();
}
if ((ret = pthread_create(&thread3, NULL, &signaler, NULL))) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_join(thread1, NULL)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_join(thread2, NULL)) != 0) {
/* Handle error */
fatal_error();
}
if ((ret = pthread_join(thread3, NULL)) != 0) {
/* Handle error */
fatal_error();
}
while (1) { ; }
return 0;
}