Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 19 Oct 1998 15:43:17 -0400 (EDT)
From:      Alfred Perlstein <bright@hotjobs.com>
To:        current@FreeBSD.ORG
Subject:   fix for "broken threads"
Message-ID:  <Pine.BSF.4.05.9810191536030.11526-100000@porkfriedrice.ny.genx.net>

next in thread | raw e-mail | index | archive | help

I lost the original message about broken threads in freebsd but I have a
fix.  I believe the problem lies in incorrect assumptions about thread
locking, a programming error basically, you are double signalling on a
conditional variable which I think is the wrong thing to do.

However I've just started playing with threads so I'm unsure if this is a
"true" fix.  You need 2 conditional variables, that way you don't "double
signal" on the conditional.

I haven't read the spec and perhaps the flip-flop shouldn't be nessesary
but it does make sense to implement.

take a look at this and tell me if it works for you:

/* Fix for the alleged FreeBSD pthread_cond_wait() bug
   
   the fix is to simply make sure you don't double signal 
   on the conditional by having a flip flop machanism via
   conditionals and a single mutex.

   g++ -o condWaitBug -D_REENTRANT -D_THREAD_SAFE -g -Wall condWaitBug.C -pthread

*/

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition=PTHREAD_COND_INITIALIZER;
pthread_cond_t condition2=PTHREAD_COND_INITIALIZER;

static void *condThread(void *)
{

    
	// Wait until we are signalled, then print.
    while (true) {
	assert(!::pthread_cond_wait(&condition, &lock));
	assert(!::pthread_cond_signal(&condition2));
	
	::printf("Got Condition!\n");
    }
}

int main(int, char **)
{
    // Initialize Lock
    pthread_mutexattr_t lock_attr;
    assert(!::pthread_mutexattr_init(&lock_attr));
    assert(!::pthread_mutex_init(&lock, &lock_attr));
    assert(!::pthread_mutexattr_destroy(&lock_attr));

    // Initialize Condition
    pthread_condattr_t cond_attr;
    assert(!::pthread_condattr_init(&cond_attr));
    assert(!::pthread_cond_init(&condition, &cond_attr));
    assert(!::pthread_condattr_destroy(&cond_attr));

    // Lock the lock
    assert(!::pthread_mutex_lock(&lock));
    // Spawn off a dozen threads to get signalled
    for (int j = 0; j < 12; ++j) {
	pthread_t tid;
	pthread_attr_t attr;
	assert(!::pthread_attr_init(&attr));
	assert(!::pthread_create(&tid, NULL, condThread, 0));
	assert(!::pthread_attr_destroy(&attr));
    }

    // Sleep for 3 seconds to make sure the threads started up.
    timeval timeout;
    timeout.tv_sec = 3;
    timeout.tv_usec = 0;
    ::select(0, 0, 0, 0, &timeout);


    for (int k = 0; k < 60; ++k) {
	::printf("Signalling\n");

	::pthread_cond_signal(&condition);
	assert(!::pthread_cond_wait(&condition2, &lock));

	// Sleep for a second
	timeout.tv_sec = 1;
	timeout.tv_usec = 0;
	::select(0, 0, 0, 0, &timeout);
	::pthread_yield();
	::pthread_yield();
    }

    return EXIT_SUCCESS;
}

Alfred Perlstein - Programmer, HotJobs Inc. - www.hotjobs.com
-- There are operating systems, and then there's FreeBSD.
-- http://www.freebsd.org/                        3.0-current


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?Pine.BSF.4.05.9810191536030.11526-100000>