public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
From: alexislefevre@free.fr
To: gcc-help@gcc.gnu.org
Subject: glibc and Thread synchronization
Date: Thu, 03 Jun 2004 22:31:00 -0000	[thread overview]
Message-ID: <1086301899.40bfa6cc04281@imp6-q.free.fr> (raw)

/*
Hi all,
As I'm somewhat relatively new to Linux Threads, I 'm trying to get some help to
circumvent
the issue described below (though not 100% sure I knocked on the right door).
Plateform: linux 2.4.21-0.13mdk
]$gcc --version
gcc (GCC) 3.2.2 (Mandrake Linux 9.1 3.2.2-3mdk)
glibc-2.3.1-10.1.91mdk

To get appropriate thread synchronization, I'm using the usual mutex/condition
variable duo, that is:
Thread 0
              pthread_mutex_lock(&mut);
              pthread_cond_wait(&cond, &mut);
              ....do something on x,y ....
              pthread_mutex_unlock(&mut);
Thread 1
              pthread_mutex_lock(&mut);
	      ....do other things on x,y ....
              if (x > y) pthread_cond_signal(&cond);
              pthread_mutex_unlock(&mut);

The above code is inspired from "man pthread_cond_wait" output

In somecases, this snippet works as expected (if Thread 0 locks the  mutex
first). However, should thread 1
gets the lock on mutex "mut" first, and depending on the timeslice assigned to
each thread (over which there is very few control at the user level),
it can happen that Thread 0 never get the condition signaled. For example:

Thread 1 is getting the lock on muttex mut first
Thread 0 tries to lock mut; as it is already locked, the thread is put asleep.
Thread 1 do the job; when done, the condition is signaled, and the mutex is
unlocked.

However, since there was no thread waiting for the condition when it was
signaled, nothing happens, and thread 0
gets stuck on pthread_cond_wait(&cond, &mut). On my system, the behavior is the
same if pthread_cond_signal(&cond)
is called after pthread_mutex_unlock(&mut), or if I loop in a _trylock in Thread
0. The only solution I found is
to change :
              pthread_mutex_lock(&mut);
	      ....do other things on x,y ....
              if (x > y) pthread_cond_signal(&cond);
              pthread_mutex_unlock(&mut);
into
              pthread_mutex_lock(&mut);
	      ....do other things on x,y ....
              pthread_mutex_unlock(&mut);
	      usleep(1);
              if (x > y) pthread_cond_signal(&cond);

But this is obviously not a smart solution, since x and y could be modified as
soon as the mutex is unlock.

I think this issue is intrisinc to linux thread design, since the signal is lost
if there is no thread waiting
for it. However, this is still enoying because, in my view, it breaks the
expected deterministic behavior
resulting from thread synchronization. I've added below a small, dummy code,
that reproduces the problem.

What I'm looking for is a condition that remains signaled until a thread
eventually reset it (equivalent to an
event in windows world). Has anyone ever found the trick or succeeded into
circumventing this problem ?
Any imputs are most welcomed

Alexis

*/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *thread_function(void *);
void *thread_reader(void *);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

int  counter = 0;
void  *thread_function(void* p)
{
   pthread_mutex_lock( &mutex1 );
   fprintf(stdout,"Thread number %ld WAITING CONDITION for counter \n",
pthread_self());fflush(stdout);
   pthread_cond_wait(&cond,&mutex1);
   counter++;
   pthread_mutex_unlock( &mutex1 );
   fprintf(stdout,"Thread number %ld has INCREMENTED counter \n",
pthread_self());fflush(stdout);
   pthread_exit((void*)0);
}
void  *thread_reader(void* p)
{  
   pthread_mutex_lock( &mutex1 );
   fprintf(stdout,"Thread number %ld is READING counter %d\n", pthread_self(),
counter);fflush(stdout);
   pthread_mutex_unlock( &mutex1 );
   //usleep(1); /* required for thread_function to have condition cond signaled...*/
   pthread_cond_signal(&cond);
   fprintf(stdout,"Thread number %ld has RED counter %d\n", pthread_self(),
counter);fflush(stdout);

   pthread_exit((void*)0);
}

int main(int argc, char *argv[])
{
  #define NTHREADS 2
  int status,rc;
  void * (*f0)(void* args);
  void * (*f1)(void* args);
  pthread_t thread_id[NTHREADS];
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);


  /* Substitute f1,f0 address to see the stuff */
  f1 = thread_function;
  f0 = thread_reader;


		rc = pthread_create( &thread_id[0], &attr, f0, NULL );
			if (rc)
		{
			printf("ERROR; return code from pthread_create  is %d\n", rc);
			exit(-1);
		}

		rc = pthread_create( &thread_id[1], &attr, f1, NULL );
				if (rc)
		{
			printf("ERROR; return code from pthread_create  is %d\n", rc);
			exit(-1);
		}
	/** Joignin the thread*/
  	 pthread_attr_destroy(&attr);
		rc = pthread_join(thread_id[0], (void **)&status);
		if (rc)
		{
			printf("ERROR; return code from pthread_join()  is %d for thread %ld\n",
rc,thread_id[0]);
			exit(-1);
		}
      printf("Completed join with thread %ld status= %d\n",thread_id[0],
status);fflush(stdout);

		rc = pthread_join(thread_id[1], (void **)&status);
		if (rc)
		{
			printf("ERROR; return code from pthread_join()  is %d for thread %ld\n",
rc,thread_id[1]);
			exit(-1);
		}
     printf("Completed join with thread %d status= %d\n",thread_id[1],
status);fflush(stdout);



   printf("Final counter value: %d\n", counter);
   }


             reply	other threads:[~2004-06-03 22:31 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-06-03 22:31 alexislefevre [this message]
2004-06-04  0:27 ` Ishwar Rattan
2004-06-04  2:28   ` alexislefevre

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1086301899.40bfa6cc04281@imp6-q.free.fr \
    --to=alexislefevre@free.fr \
    --cc=gcc-help@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).