Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion pthread_cond_* implementation questions
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
terekhov  
View profile  
 More options Jan 25 2001, 6:20 am
Newsgroups: comp.programming.threads
From: terek...@my-deja.com
Date: Thu, 25 Jan 2001 11:10:45 GMT
Local: Thurs, Jan 25 2001 6:10 am
Subject: Re: pthread_cond_* implementation questions

David Schwartz <dav...@webmaster.com> wrote:
>terek...@my-deja.com wrote:

>> David Schwartz <dav...@webmaster.com> wrote:

>> > ...it's buggy.

>> well, please SHOW me the bug.

>The bug is that you call 'pthread_cond_signal' which is only
>allowed if _any_ woken thread can do the job. In this case,
>the main thread can't, so if the 'pthread_cond_signal' wakes
>the main thread, the program will stall.

please read the source code again...

main thread can not steal any "ball" signals from players
because main thread is not waiting for any signals while players
are busy playing the game. the main thread is asleep:

  .
  .
  .
  // Give them 5 sec. to play
  Sleep( 5000 ); //Win32
  //sleep( 5 );
  .
  .
  .

>> > Players A and B use pthread_cond_signal, but it's possible...

>> It is not fair to claim that it's buggy just saying
>> "it's possible that they might need to wakeup two threads...".

>> It would be another program then (with added new features).

>Huh?

if the program's main thread would need to wait for signals
while players are playing it would be another program.

it could have been made to allow players to leave game
while game is not over, declare game over, replace
old players with new ones,.... these would be added new
features implementation of which would require main thread
to be in listening mode through out the game.

Current program does not support/allow it hence main does not
need to be in wait mode until game is not over (after sleeping
5. sec)

>> The program is intentionally designed to use signals
>> (in order to demonstrate the problem with _signal call
>> impl.) in such way that players need ALWAYS AND ONLY
>> talk to each other or main() <- last player leaving the game,
>> but NEVER to both (another player and main).

>The problem is that the pthread_cond_signal doesn't know which thread
>it 'needs' to wake up. You do, so you need to code that information.
>The program is buggy.

well, it might be that the program is in fact buggy.
but you did not show me any bug.

>> main() commands (sets the state of game to be over)
>> players carry out (stop playing).

>> Broadcast is only needed for final "game over"
>> signal issued by main().

>Nonesense. You are only guaranteed that pthread_cond_signal
>will wake _some_ thread, but not which. If player
>A's pthread_cond_signal wakes the main thread, player B
>will never wakeup.

in the situation when player A's pthread_cond_signal
wakes the main thread (that can only happen when game is
over), player B will be unblocked by already happened
broadcast from main (which declared the game to be over).

>> > It's compliant

>> That is really good.

>> Tomorrow (I have to go urgently now) I will try to
>> demonstrate the lost-signal "problem" of current
>> pthread-win32 and ACE-(variant w/o SingleObjectAndWait)
>> implementations: players start suddenly drop their balls :-)
>> (with no change in source code).

>Signals aren't lost, they're going to the main thread,
>which isn't coded correctly to handle them. Try this:

>  // Wait for players to stop
>  do {

>    pthread_cond_wait( &cndGameStateChange,&mtxGameStateLock );
>printf("Main thread stole a signal\n");

>  } while ( eGameState < BOTH_PLAYERS_GONE );

>I bet everytime you thing a signal is lost, you'll see that printf.
>The signal isn't lost, it was stolen by another thread.

well, you can probably loose your bet.. it was indeed stolen
by "another" thread but not the one you seem to think of.

I think that what actually happens is the following:

H:\SA\UXX\pt\PTHREADS\TESTS>tennis3.exe

PLAYER-A

PLAYER-B

----PLAYER-B: SPURIOUS WAKEUP!!!

PLAYER-A GONE

PLAYER-B GONE

GAME OVER

H:\SA\UXX\pt\PTHREADS\TESTS>

here you can see that PLAYER-B after playing his first
ball (which came via signal from PLAYER-A) just dropped
it down. What happened is that his signal to player A
was consumed as spurious wakeup by himself (player B).

The implementation has a problem:

================
waiting threads:
================

{ /** Critical Section

  inc cond.waiters_count

}

  /*
  /* Atomic only if using Win32 SignalObjectAndWait
  /*
  cond.mtx.release

  /*** ^^-- A THREAD WHICH DID SIGNAL MAY ACQUIRE THE MUTEX,
  /***      GO INTO WAIT ON THE SAME CONDITION AND OVERTAKE
  /***      ORIGINAL WAITER(S) CONSUMING ITS OWN SIGNAL!

  cond.sem.wait

Player-A after playing game's initial ball went into
wait (called _wait) but was pre-empted before reaching
wait semaphore. He was counted as waiter but was not
actually waiting/blocked yet.

===============
signal threads:
===============

{ /** Critical Section

  waiters_count = cond.waiters_count

}

  if ( waiters_count != 0 )

    sem.post 1

  endif

Player-B after he received signal/ball from Player A
called _signal. The _signal did see that there was
one waiter blocked on the condition (Player-A) and
released the semaphore.. (but it did not unblock
Player-A because he was not actually blocked).
Player-B thread continued its execution, called _wait,
was counted as second waiter BUT was allowed to slip
through opened semaphore gate (which was opened for
Player-B) and received his own signal. Player B remained
blocked followed by Player A. Deadlock happened which
lasted until main thread came in and said game over.

It seems to me that the implementation fails to
correctly implement the following statement
from specification:

http://www.opengroup.org/
onlinepubs/007908799/xsh/pthread_cond_wait.html

"These functions atomically release mutex and cause
the calling thread to block on the condition variable
cond; atomically here means "atomically with respect
to access by another thread to the mutex and then the
condition variable". That is, if another thread is
able to acquire the mutex after the about-to-block
thread has released it, then a subsequent call to
pthread_cond_signal() or pthread_cond_broadcast()
in that thread behaves as if it were issued after
the about-to-block thread has blocked."

Question: Am I right?

(I produced the program output above by simply
adding “Sleep( 1 )”:

================
waiting threads:
================

{ /** Critical Section

  inc cond.waiters_count

}

  /*
  /* Atomic only if using Win32 SignalObjectAndWait
  /*
  cond.mtx.release

Sleep( 1 ); // Win32

  /*** ^^-- A THREAD WHICH DID SIGNAL MAY ACQUIRE THE MUTEX,
  /***      GO INTO WAIT ON THE SAME CONDITION AND OVERTAKE
  /***      ORIGINAL WAITER(S) CONSUMING ITS OWN SIGNAL!

  cond.sem.wait

to the source code of pthread-win32 implementation:

http://sources.redhat.com/cgi-bin/cvsweb.cgi/pthreads/
condvar.c?rev=1.36&content-type=text/
x-cvsweb-markup&cvsroot=pthreads-win32

  /*
   * We keep the lock held just long enough to increment the count of
   * waiters by one (above).
   * Note that we can't keep it held across the
   * call to sem_wait since that will deadlock other calls
   * to pthread_cond_signal
   */
  cleanup_args.mutexPtr = mutex;
  cleanup_args.cv = cv;
  cleanup_args.resultPtr = &result;

  pthread_cleanup_push (ptw32_cond_wait_cleanup, (void *)
&cleanup_args);

  if ((result = pthread_mutex_unlock (mutex)) == 0)
    {
Sleep( 1 ); // @AT

      /*
       * Wait to be awakened by
       *              pthread_cond_signal, or
       *              pthread_cond_broadcast, or
       *              a timeout
       *
       * Note:
       *      ptw32_sem_timedwait is a cancelation point,
       *      hence providing the
       *      mechanism for making pthread_cond_wait a cancelation
       *      point. We use the cleanup mechanism to ensure we
       *      re-lock the mutex and decrement the waiters count
       *      if we are canceled.
       */
      if (ptw32_sem_timedwait (&(cv->sema), abstime) == -1)
        {
          result = errno;
        }
    }

  pthread_cleanup_pop (1);  /* Always cleanup */

BTW, on my system (2 CPUs) I can manage to get
signals lost even without any source code modification
if I run the tennis program many times in different
shell sessions.

regards,
alexander.

Sent via Deja.com
http://www.deja.com/


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.