Hi,

thanks for your work on a helgrind replacement. Such a tool is a great help 
for us.

I have tested thrcheck from revision 7044 with the attached program. Here are 
some problems I found:

1. The concurrent writes on line 72 are not protected by a mutex (uncommented 
above and below). Thrcheck does not flag this error on my i386 and x86_64 
machines.

2. There is no race-condition for the writes in line 92. However the i386 
version of thrcheck flags an error here.

3. The x86_64 version only shows that one thread is started. Threads 3 -- 9 
are not shown.

4. The i386 version flags a possible race condition in line 41. In my opinion 
there is none.


Greetings
Christoph
#include <iostream>
#include <vector>

extern "C" {
#include <pthread.h>
}

pthread_mutex_t job_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t odd_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t even_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t job_cond = PTHREAD_COND_INITIALIZER;

static int jobs_completed = 0;

static int const NUM_THREADS = 8;

class Job {
public:
   virtual void run() = 0;
};

Job * work[NUM_THREADS] = {NULL, NULL};

extern "C" void * start(void *) {

   while (true) {
      pthread_mutex_lock(&job_mutex);
      
      Job * job = NULL;
      
      while (true) {
         for (int i = 0; i < NUM_THREADS; ++i) {
            if (work[i] != NULL) {
	       job = work[i];
	       work[i] = NULL;
	       break;
	    }
      	 }
	 if (job) break;
	 pthread_cond_wait(&job_cond, &job_mutex);
      }
      pthread_mutex_unlock(&job_mutex);
      job->run();
      
      pthread_mutex_lock(&job_mutex);
      ++jobs_completed;
      pthread_cond_broadcast(&job_cond);
      pthread_mutex_unlock(&job_mutex);
   }
   return NULL;
}


struct Data {
   Data() : counter(0) {}
   int counter;
};

class Loop : public Job {
public:
   Loop(std::vector<Data *> & vec) : vec(vec) {}

   virtual void run() {
      for (std::size_t i = 0; i < vec.size(); ++i) {
         if (i % 2 == 0) {
	    pthread_mutex_lock(&even_mutex);
	    vec[i]->counter++;
	    pthread_mutex_unlock(&even_mutex);
	 } else {
//	    pthread_mutex_lock(&odd_mutex);
	    vec[i]->counter++;
//	    pthread_mutex_unlock(&odd_mutex);	 
	 }
      }
   }

private:
   std::vector<Data *> & vec;
};


class Jump : public Job {
public:
   Jump(std::vector<Data *> & vec, std::size_t my_indices)
    : vec(vec), my_indices(my_indices) {}
    

   virtual void run() {
      for (std::size_t i = 0; i < vec.size(); ++i) {
         if (i % NUM_THREADS == my_indices) {
	    vec[i]->counter++;
	 }
      }
   }

private:
   std::vector<Data *> & vec;
   std::size_t my_indices;
};



class Finish : public Job {
public:
   virtual void run() {
      pthread_exit(NULL);
   }
};

void wait_for_jobs(int num) {
   pthread_mutex_lock(&job_mutex);
   while (jobs_completed < num) pthread_cond_wait(&job_cond, &job_mutex);
   pthread_mutex_unlock(&job_mutex);
}

int main() {

   std::cout << "Starting main programm" << std::endl;
   pthread_t tid[NUM_THREADS];
   for (int i = 0; i < NUM_THREADS; ++i) {
      pthread_create(&tid[i], NULL, start, NULL);
   }
   
   std::cout << "Threads created" << std::endl;
   
   std::vector<Data *> vec;
   for (std::size_t i = 0; i < NUM_THREADS; ++i) {
      vec.push_back(new Data());
      std::cout << "Created counter at address: " << &vec.back()->counter << std::endl;
   }
   
   std::cout << "Vector initialized" << std::endl;
   
   Loop l(vec);
   
   pthread_mutex_lock(&job_mutex);
   for (std::size_t i = 0; i < NUM_THREADS; ++i) {
      work[i] = &l;
   }
   std::cout << "Added loop jobs" << std::endl;   
   pthread_cond_broadcast(&job_cond);
   pthread_mutex_unlock(&job_mutex);
   
   wait_for_jobs(NUM_THREADS);
   
   std::vector<Jump *> jump_vec;
   for (std::size_t i = 0; i < NUM_THREADS; ++i) {
      jump_vec.push_back(new Jump(vec, i));
   }
   pthread_mutex_lock(&job_mutex);
   for (std::size_t i = 0; i < NUM_THREADS; ++i) {
      work[i] = jump_vec[i];
   }
   std::cout << "Added jump jobs" << std::endl;   
   pthread_cond_broadcast(&job_cond);
   pthread_mutex_unlock(&job_mutex);
   
   Finish f;
   pthread_mutex_lock(&job_mutex);
   for (std::size_t i = 0; i < NUM_THREADS; ++i) {
      work[i] = &f;
   }
   pthread_cond_broadcast(&job_cond);
   pthread_mutex_unlock(&job_mutex);
   
   for (std::size_t i = 0; i < NUM_THREADS; ++i) {
      pthread_join(tid[i], NULL);
   }
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Valgrind-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers

Reply via email to