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;
}