Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Aug 1998 17:13:02 -0400 (EDT)
From:      Daniel Eischen <eischen@vigrid.com>
To:        eischen@vigrid.com, shmit@kublai.com
Cc:        freebsd-current@FreeBSD.ORG
Subject:   Re: Pthreads woes revisited.
Message-ID:  <199808062113.RAA18177@pcnet1.pcnet.com>

next in thread | raw e-mail | index | archive | help
> On Thu, Aug 06, 1998 at 01:51:57PM -0400, Daniel M. Eischen wrote:
> > But your not yielding the CPU after the pthread_cond_signal().
> > The waiter thread (thr_wait) should also take the mutex lock (busy)
> > before the pthread_cond_wait().  See the comments in the revised
> > copy of your code.
> 
> From what I can tell by looking at uthread_mutex.c:pthread_mutex_unlock()
> and uthread_cond.c:pthread_cond_wait(), I don't have to lock the mutex
> before calling pthread_cond_wait().

True, the source for pthread_cond_wait ignores any error code
returned by pthread_mutex_lock().  I don't know if this behaviour
is defined in the POSIX spec (for whatever rev we're currently
supporting), but the intended use is to acquire the mutex before
the cond_wait/cond_timedwait.

You're not adding the pthread_yield() call that I added after
the pthread_cond_signal().  Your program is bogus because there
is no guarantee that the main thread will release the CPU in
order for the other task to run.  You need to perform some
sort of blocking operation after the pthread_cond_signal.  I
chose to use pthread_yield, although sleep would work just as
well.

Furthermore, thr_routine() will never return from the pthread_cond_wait()
unless the busy mutex is available.  You're main thread is taking the
mutex before the sleep and releasing it after the sleep.  There is
no way that thr_routine can wakeup because it needs to acquire the
busy mutex in order to return from the pthread_cond_wait().

Look:

  (from thr_routine)
                printf("%d: Waiting for signal.\n", (int) pthread_self ());
                rc = pthread_cond_wait(&wakeup, &busy);
                if (rc) {
                        fprintf(stderr,
                                "ERROR: couldn't wait for condition: %s.\n",
                                strerror(rc));
                        return NULL;
                }

  (from main)
                printf("MASTER: Acquiring lock.\n");
                rc = pthread_mutex_lock(&busy);
                if (rc) {
                        fprintf(stderr, "ERROR: couldn't lock mutex: %s.\n",
                                strerror(rc));
                        return 1;
                }

                sleep(1);

                printf("MASTER: Releasing lock.\n");
                rc = pthread_mutex_unlock(&busy);

Sleeping while holding the mutex will obviously not allow the
other thread to run.  When the main thread returns from the sleep,
it will run until its time quantum expires, preempted, or blocks
(perhaps signals can affect it too?).  I ran the same test on
Solaris and the main thread *never* yielded the processor to the
other thread until I placed a pthread_yield (sched_yield) after
the pthread_cond_signal.

Please try adding some sort of blocking operation after the
pthread_cond_signal in the main thread.  If you do not want to
use pthread_yield(), then use sleep, select, or anything that
will block the main thread.

I suspect that you want the thread to run while the main thread
is sleeping.  If that is the case, then you must use another mutex
in the main thread.

Dan Eischen
eischen@vigrid.com

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199808062113.RAA18177>