Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 06 Aug 1998 13:51:57 -0400
From:      "Daniel M. Eischen" <eischen@vigrid.com>
To:        shmit@kublai.com
Cc:        freebsd-current@FreeBSD.ORG
Subject:   Re: Pthreads woes revisited.
Message-ID:  <35C9ED3D.41C67EA6@vigrid.com>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

--------------446B9B3D2781E494167EB0E7
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

> I've put together a small C program that demonstrates the problems
> I described in my last message. You can find the program attached
> to this message.
> 
> Note the location of the `sleep(1)' call, it's important. If it moves
> outside of the mutex lock/unlock bits, everything functions normally,
> but if it gets called after the lock, but before the unlock, the first
> signal is missed.
> 

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.

Dan Eischen
eischen@vigrid.com

--------------446B9B3D2781E494167EB0E7
Content-Type: text/plain; charset=us-ascii; name="thr_test.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="thr_test.c"

#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>

pthread_cond_t wakeup;
pthread_mutex_t busy;

void *
thr_routine(void *arg)
{
        int rc;

	/*
	 * The mutex should be taken before the condition wait.
	 * The condition wait will atomically release the mutex and
	 * retake it when awoken.
	 */
	pthread_mutex_lock (&busy);
        for (;;) {
                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;
                }
                printf("%d: Got signal.\n", (int) pthread_self ());
        }

        return NULL;
}

int
main(int argc, char *argv[])
{
        int rc;
        pthread_t thread_id;

        rc = pthread_cond_init(&wakeup, NULL);
        if (rc) {
                fprintf(stderr,
                        "ERROR: couldn't create condition variable: %s.\n",
                        strerror(rc));
                return 1;
        }

        rc = pthread_mutex_init(&busy, NULL);
        if (rc) {
                fprintf(stderr, "ERROR: couldn't create mutex: %s.\n",
                        strerror(rc));
                return 1;
        }

        rc = pthread_create(&thread_id, NULL, thr_routine, NULL);
        if (rc) {
                fprintf(stderr, "ERROR: couldn't create thread: %s.\n",
                        strerror(rc));
                return 1;
        }

        for (;;) {
                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);
                if (rc) {
                        fprintf(stderr, "ERROR: couldn't unlock mutex: %s.\n",
                                strerror(rc));
                        return 1;
                }

                printf("MASTER: Sending signal.\n");
                rc = pthread_cond_signal(&wakeup);
                if (rc) {
                        fprintf(stderr, "ERROR: couldn't signal thread: %s.\n",
                                strerror(rc));
                        return 1;
                }

		/* Allow the other thread to run. */
                pthread_yield ();
        }

        return 0;
}


--------------446B9B3D2781E494167EB0E7--


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?35C9ED3D.41C67EA6>