try to fix Linux build problems related to pthreads

svn: r18776
This commit is contained in:
Matthew Flatt 2010-04-09 21:09:49 +00:00
parent 8242847c7a
commit 0b2a43f193
5 changed files with 219 additions and 2 deletions

62
src/configure vendored
View File

@ -2258,6 +2258,7 @@ show_explicitly_disabled "${enable_foreign}" Foreign
show_explicitly_enabled "${enable_places}" Places
show_explicitly_enabled "${enable_futures}" Futures
show_explicitly_disabled "${enable_futures}" Futures
show_explicitly_enabled "${enable_sgc}" SGC
show_explicitly_enabled "${enable_sgcdebug}" "SGC debug mode"
@ -10760,6 +10761,67 @@ cat >>confdefs.h <<\_ACEOF
#define USE_PTHREAD_INSTEAD_OF_ITIMER 1
_ACEOF
msg="whether pthread_rwlock is available"
{ echo "$as_me:$LINENO: checking $msg" >&5
echo $ECHO_N "checking $msg... $ECHO_C" >&6; }
if test "$cross_compiling" = yes; then
rwlockavail=no
else
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <pthread.h>
pthread_rwlock_t l;
int main() {
return pthread_rwlock_init(&l, NULL);
}
_ACEOF
rm -f conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_link") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && { ac_try='./conftest$ac_exeext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
rwlockavail=yes
else
echo "$as_me: program exited with status $ac_status" >&5
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
( exit $ac_status )
rwlockavail=no
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
{ echo "$as_me:$LINENO: result: $rwlockavail" >&5
echo "${ECHO_T}$rwlockavail" >&6; }
if test "$rwlockavail" = "yes" ; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_PTHREAD_RWLOCK 1
_ACEOF
fi
fi
################ Xrender ##################

View File

@ -296,6 +296,7 @@ show_explicitly_disabled "${enable_foreign}" Foreign
show_explicitly_enabled "${enable_places}" Places
show_explicitly_enabled "${enable_futures}" Futures
show_explicitly_disabled "${enable_futures}" Futures
show_explicitly_enabled "${enable_sgc}" SGC
show_explicitly_enabled "${enable_sgcdebug}" "SGC debug mode"
@ -1178,6 +1179,19 @@ if test "${enable_pthread}" = "yes" ; then
PREFLAGS="$PREFLAGS -pthread"
LDFLAGS="$LDFLAGS -pthread"
AC_DEFINE(USE_PTHREAD_INSTEAD_OF_ITIMER, 1, [Pthread timer enabled])
[ msg="whether pthread_rwlock is available" ]
AC_MSG_CHECKING($msg)
AC_TRY_RUN(
[ #include <pthread.h>]
pthread_rwlock_t l;
int main() {
return pthread_rwlock_init(&l, NULL);
}, rwlockavail=yes, rwlockavail=no, rwlockavail=no)
AC_MSG_RESULT($rwlockavail)
if test "$rwlockavail" = "yes" ; then
AC_DEFINE(HAVE_PTHREAD_RWLOCK,1,[Have pthread_rwlock])
fi
fi
################ Xrender ##################

View File

@ -30,7 +30,7 @@ extern "C" {
# if _MSC_VER
# define THREAD_LOCAL /* empty */
# define IMPLEMENT_THREAD_LOCAL_VIA_WIN_TLS
# elif defined(OS_X) || (defined(linux) && defined(MZ_USES_SHARED_LIB))
# elif defined(OS_X)
# define IMPLEMENT_THREAD_LOCAL_VIA_PTHREADS
# if defined(__x86_64__) || defined(__i386__)
# define INLINE_GETSPECIFIC_ASSEMBLY_CODE
@ -306,7 +306,7 @@ static inline Thread_Local_Variables *scheme_get_thread_local_variables() {
# else
asm volatile("movl %%gs:0x48(,%1,4), %0" : "=r"(x) : "r"(scheme_thread_local_key));
# endif
# elif defined(linux) && defined(MZ_USES_SHARED_LIB)
# elif defined(linux)
# if defined(__x86_64__)
asm volatile( "mov %1, %%eax;"
"shl $0x4, %%rax;"

View File

@ -35,6 +35,9 @@
/* Whether __attribute__ ((noinline)) works */
#undef MZ_USE_NOINLINE
/* Whether pthread_rwlock is availabale: */
#undef HAVE_PTHREAD_RWLOCK
/* Enable futures and/or places: */
#undef MZ_USE_FUTURES
#undef MZ_USE_PLACES

View File

@ -290,6 +290,8 @@ void mz_proc_thread_exit(void *rc) {
#ifndef WIN32
# ifdef HAVE_PTHREAD_RWLOCK
struct mzrt_rwlock {
pthread_rwlock_t lock;
};
@ -322,6 +324,142 @@ int mzrt_rwlock_destroy(mzrt_rwlock *lock) {
return pthread_rwlock_destroy(&lock->lock);
}
# else
struct mzrt_rwlock {
pthread_mutex_t m;
pthread_cond_t cr, cw;
int readers, writers, write_waiting;
};
static mzrt_rwlock *locks[2];
static void *go(void *id)
{
int i = *(int *)id, j, amt;
for (j = 0; j < 3; j++) {
amt = (random() % 400) + 100;
usleep(amt - 100);
if (!(i % 3)) {
mzrt_rwlock_wrlock(locks[0]);
printf("writing %d\n", i);
usleep(amt);
mzrt_rwlock_unlock(locks[0]);
} else {
mzrt_rwlock_rdlock(locks[0]);
printf("reading %d\n", i);
usleep(amt);
mzrt_rwlock_unlock(locks[0]);
}
printf("done %d\n", i);
}
return NULL;
}
int mzrt_rwlock_create(mzrt_rwlock **lock) {
int err;
*lock = malloc(sizeof(mzrt_rwlock));
err = pthread_mutex_init(&(*lock)->m, NULL);
if (err) { free(*lock); return err; }
err = pthread_cond_init(&(*lock)->cr, NULL);
if (err) { free(*lock); return err; }
err = pthread_cond_init(&(*lock)->cw, NULL);
if (err) { free(*lock); return err; }
return err;
}
static int rwlock_rdlock(mzrt_rwlock *lock, int just_try) {
int err;
err = pthread_mutex_lock(&lock->m);
if (err) return err;
while (lock->writers || lock->write_waiting) {
if (just_try) {
err = pthread_mutex_unlock(&lock->m);
if (err) return err;
return EBUSY;
} else {
err = pthread_cond_wait(&lock->cr, &lock->m);
if (err)
return err;
}
}
lock->readers++;
return pthread_mutex_unlock(&lock->m);
}
int mzrt_rwlock_rdlock(mzrt_rwlock *lock) {
return rwlock_rdlock(lock, 0);
}
static int rwlock_wrlock(mzrt_rwlock *lock, int just_try) {
int err;
err = pthread_mutex_lock(&lock->m);
if (err) return err;
while (lock->writers || lock->readers) {
if (just_try) {
err = pthread_mutex_unlock(&lock->m);
if (err) return err;
return EBUSY;
} else {
lock->write_waiting++;
err = pthread_cond_wait(&lock->cw, &lock->m);
--lock->write_waiting;
if (err)
return err;
}
}
lock->writers++;
return pthread_mutex_unlock(&lock->m);
}
int mzrt_rwlock_wrlock(mzrt_rwlock *lock) {
return rwlock_wrlock(lock, 0);
}
int mzrt_rwlock_tryrdlock(mzrt_rwlock *lock) {
return rwlock_rdlock(lock, 1);
}
int mzrt_rwlock_trywrlock(mzrt_rwlock *lock) {
return rwlock_wrlock(lock, 1);
}
int mzrt_rwlock_unlock(mzrt_rwlock *lock) {
int err;
err = pthread_mutex_lock(&lock->m);
if (err) return err;
if (lock->readers)
--lock->readers; /* must have been a read lock */
else
--lock->writers;
if (lock->write_waiting)
err = pthread_cond_signal(&lock->cw);
else
err = pthread_cond_broadcast(&lock->cr);
if (err) return err;
return pthread_mutex_unlock(&lock->m);
}
int mzrt_rwlock_destroy(mzrt_rwlock *lock) {
pthread_mutex_destroy(&lock->m);
pthread_cond_destroy(&lock->cr);
pthread_cond_destroy(&lock->cw);
free(lock);
return 0;
}
# endif
struct mzrt_mutex {
pthread_mutex_t mutex;
};