This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RE: pthread_cond_wait does not relock mutex on release


Independent of any other issues, the test case is wrong.
Specifically, pthread_cond_wait is allowed to spuriously
return (it's in the standard that way). You do have the
lock, though. That allows you to look at the variable and
determine if this was a spurious signal.

You have to wrap cond_wait with a check of the associated
variable (which would have to be set when you signalled
it).

In other words, this:

>  void *foo(void*)
>  {
>   int status = ::pthread_mutex_lock(&(_pwait_condition->_mutex));
>   ::printf("foo mutex lock\n");
> 
>   status = ::pthread_cond_signal(&(_pwait_condition->_cond));
>   ::printf("foo mutex lock and signal condition then sleep...\n");
> 
>   ::sleep(1);
>   status = ::pthread_mutex_unlock(&(_pwait_condition->_mutex));
>   ::printf("foo mutex unlock\n");
> 
>   return 0;
>  };
> 
>  void *bar(void*)
>  {
>   ::pthread_mutex_lock(&(_pwait_condition->_mutex));
>   ::printf("bar mutex lock and wait\n");
> 
>   ::pthread_cond_wait(&(_pwait_condition->_cond)
>     , &(_pwait_condition->_mutex));
>   ::printf("bar mutex lock and wait released\n");
> 
>   ::pthread_mutex_unlock(&(_pwait_condition->_mutex));
>   ::printf("bar mutex unlock\n");
> 
>   return 0;
>  };

should become something like this:

 void *foo(void*)
 {
  int status = ::pthread_mutex_lock(&(_pwait_condition->_mutex));
  ::printf("foo mutex lock\n");

  _pwait_condition->_status = false;
  status = ::pthread_cond_signal(&(_pwait_condition->_cond));
  ::printf("foo mutex lock and signal condition then sleep...\n");

  ::sleep(1);
  status = ::pthread_mutex_unlock(&(_pwait_condition->_mutex));
  ::printf("foo mutex unlock\n");

  return 0;
 };

 void *bar(void*)
 {
  ::pthread_mutex_lock(&(_pwait_condition->_mutex));
  ::printf("bar mutex lock and wait\n");

  while (_pwait_condition->_status) {
    ::pthread_cond_wait(&(_pwait_condition->_cond)
      , &(_pwait_condition->_mutex));
    ::printf("bar mutex lock and wait released\n");
  }

  ::pthread_mutex_unlock(&(_pwait_condition->_mutex));
  ::printf("bar mutex unlock\n");

  return 0;
 };

That could cause the results you are seeing. Or it could
be something much simpler. Calling printf simultaneously
from multiple threads can mess up the output. Mine was
really strange for this program. You might want to try
adding this to the top of your program:

#include <stdarg.h>

void SAFE_PRINTF(char *format,...)
{
    va_list vargs;
    static pthread_mutex_t printMutex;
    static int initialized = 0;

    /* OK as long as printf is called in single-threaded context first: */
    if (!initialized)
    {
        int status = pthread_mutex_init(&printMutex, 0);
        assert(0==status);
        initialized = 1;
    }

    pthread_mutex_lock(&printMutex);

    va_start(vargs,format);
    vprintf(format,vargs);
    va_end(vargs);

    pthread_mutex_unlock(&printMutex);
}

#define printf SAFE_PRINTF

I get the following output after changing printf:
 create Test
 start
 bar mutex lock and wait
 foo mutex lock
 foo mutex lock and signal condition then sleep...
 bar mutex lock and wait released
 foo mutex unlock
 bar mutex unlock
 end
 delete Test

That is still not exactly what you expected, but makes sense
since foo()'s printf is racing the two in bar(). (I.e., bar()
gets to run before foo()'s mutex_unlock() returns, then foo()
gets to run while bar() is unlocking the mutex again.)

-Jerry

-O Gerald S. Williams, 55A-134A-E   : mailto:gsw@agere.com O-
-O AGERE SYSTEMS, 6755 SNOWDRIFT RD : office:610-712-8661  O-
-O ALLENTOWN, PA, USA 18106-9353    : mobile:908-672-7592  O-


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]