delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2002/04/17/10:07:37

Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
From: "Gerald S. Williams" <gsw AT agere DOT com>
To: <cygwin AT cygwin DOT com>
Subject: RE: pthread_cond_wait does not relock mutex on release
Date: Wed, 17 Apr 2002 10:04:20 -0400
Message-ID: <GBEGLOMMCLDACBPKDIHFGEOFCHAA.gsw@agere.com>
MIME-Version: 1.0
X-Priority: 3 (Normal)
X-MSMail-Priority: Normal
Importance: Normal
In-Reply-To: <000b01c1e579$2c477a90$c07dadcf@homeke6pijupjp>
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4807.1700

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 AT agere DOT 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/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019