From 0b2a43f193901c96ded43679e1b778812e6dc220 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 9 Apr 2010 21:09:49 +0000 Subject: [PATCH] try to fix Linux build problems related to pthreads svn: r18776 --- src/configure | 62 ++++++++++++++ src/mzscheme/configure.ac | 14 ++++ src/mzscheme/include/schthread.h | 4 +- src/mzscheme/mzconfig.h.in | 3 + src/mzscheme/src/mzrt.c | 138 +++++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 2 deletions(-) diff --git a/src/configure b/src/configure index 40e6229ce0..caf6a35a52 100755 --- a/src/configure +++ b/src/configure @@ -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_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 ################## diff --git a/src/mzscheme/configure.ac b/src/mzscheme/configure.ac index bf8c72adcf..7e6862d502 100644 --- a/src/mzscheme/configure.ac +++ b/src/mzscheme/configure.ac @@ -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_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 ################## diff --git a/src/mzscheme/include/schthread.h b/src/mzscheme/include/schthread.h index 6cd88446a2..5b21840fe4 100644 --- a/src/mzscheme/include/schthread.h +++ b/src/mzscheme/include/schthread.h @@ -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;" diff --git a/src/mzscheme/mzconfig.h.in b/src/mzscheme/mzconfig.h.in index 77f63e7dac..0585cdf198 100644 --- a/src/mzscheme/mzconfig.h.in +++ b/src/mzscheme/mzconfig.h.in @@ -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 diff --git a/src/mzscheme/src/mzrt.c b/src/mzscheme/src/mzrt.c index eb5cc1c6de..43686a37ae 100644 --- a/src/mzscheme/src/mzrt.c +++ b/src/mzscheme/src/mzrt.c @@ -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; };