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>
