mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-22 20:36:20 +08:00
runtime: If no sem_timedwait, use pthread_cond_timedwait.
From-SVN: r181821
This commit is contained in:
parent
85b8555ed3
commit
08ee945e0b
@ -36,6 +36,9 @@
|
|||||||
/* Define to 1 if you have the `random' function. */
|
/* Define to 1 if you have the `random' function. */
|
||||||
#undef HAVE_RANDOM
|
#undef HAVE_RANDOM
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `sem_timedwait' function. */
|
||||||
|
#undef HAVE_SEM_TIMEDWAIT
|
||||||
|
|
||||||
/* Define to 1 if you have the `setenv' function. */
|
/* Define to 1 if you have the `setenv' function. */
|
||||||
#undef HAVE_SETENV
|
#undef HAVE_SETENV
|
||||||
|
|
||||||
|
18
libgo/configure
vendored
18
libgo/configure
vendored
@ -14559,6 +14559,24 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
CFLAGS_hold="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
LIBS_hold="$LIBS"
|
||||||
|
LIBS="$LIBS $PTHREAD_LIBS"
|
||||||
|
for ac_func in sem_timedwait
|
||||||
|
do :
|
||||||
|
ac_fn_c_check_func "$LINENO" "sem_timedwait" "ac_cv_func_sem_timedwait"
|
||||||
|
if test "x$ac_cv_func_sem_timedwait" = x""yes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_SEM_TIMEDWAIT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
CFLAGS="$CFLAGS_hold"
|
||||||
|
LIBS="$LIBS_hold"
|
||||||
|
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_bool_compare_and_swap_4" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_bool_compare_and_swap_4" >&5
|
||||||
$as_echo_n "checking for __sync_bool_compare_and_swap_4... " >&6; }
|
$as_echo_n "checking for __sync_bool_compare_and_swap_4... " >&6; }
|
||||||
if test "${libgo_cv_func___sync_bool_compare_and_swap_4+set}" = set; then :
|
if test "${libgo_cv_func___sync_bool_compare_and_swap_4+set}" = set; then :
|
||||||
|
@ -456,6 +456,14 @@ AC_CHECK_FUNCS(srandom random strerror_r strsignal wait4 mincore setenv)
|
|||||||
AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
|
AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes)
|
||||||
AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
|
AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes)
|
||||||
|
|
||||||
|
CFLAGS_hold="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
LIBS_hold="$LIBS"
|
||||||
|
LIBS="$LIBS $PTHREAD_LIBS"
|
||||||
|
AC_CHECK_FUNCS(sem_timedwait)
|
||||||
|
CFLAGS="$CFLAGS_hold"
|
||||||
|
LIBS="$LIBS_hold"
|
||||||
|
|
||||||
AC_CACHE_CHECK([for __sync_bool_compare_and_swap_4],
|
AC_CACHE_CHECK([for __sync_bool_compare_and_swap_4],
|
||||||
[libgo_cv_func___sync_bool_compare_and_swap_4],
|
[libgo_cv_func___sync_bool_compare_and_swap_4],
|
||||||
[AC_LINK_IFELSE([
|
[AC_LINK_IFELSE([
|
||||||
|
@ -32,9 +32,11 @@ enum
|
|||||||
void
|
void
|
||||||
runtime_lock(Lock *l)
|
runtime_lock(Lock *l)
|
||||||
{
|
{
|
||||||
|
M *m;
|
||||||
uintptr v;
|
uintptr v;
|
||||||
uint32 i, spin;
|
uint32 i, spin;
|
||||||
|
|
||||||
|
m = runtime_m();
|
||||||
if(m->locks++ < 0)
|
if(m->locks++ < 0)
|
||||||
runtime_throw("runtime_lock: lock count");
|
runtime_throw("runtime_lock: lock count");
|
||||||
|
|
||||||
@ -91,7 +93,7 @@ runtime_unlock(Lock *l)
|
|||||||
uintptr v;
|
uintptr v;
|
||||||
M *mp;
|
M *mp;
|
||||||
|
|
||||||
if(--m->locks < 0)
|
if(--runtime_m()->locks < 0)
|
||||||
runtime_throw("runtime_unlock: lock count");
|
runtime_throw("runtime_unlock: lock count");
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
@ -144,6 +146,9 @@ runtime_notewakeup(Note *n)
|
|||||||
void
|
void
|
||||||
runtime_notesleep(Note *n)
|
runtime_notesleep(Note *n)
|
||||||
{
|
{
|
||||||
|
M *m;
|
||||||
|
|
||||||
|
m = runtime_m();
|
||||||
if(m->waitsema == 0)
|
if(m->waitsema == 0)
|
||||||
m->waitsema = runtime_semacreate();
|
m->waitsema = runtime_semacreate();
|
||||||
if(!runtime_casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup)
|
if(!runtime_casp(&n->waitm, nil, m)) { // must be LOCKED (got wakeup)
|
||||||
@ -158,6 +163,7 @@ runtime_notesleep(Note *n)
|
|||||||
void
|
void
|
||||||
runtime_notetsleep(Note *n, int64 ns)
|
runtime_notetsleep(Note *n, int64 ns)
|
||||||
{
|
{
|
||||||
|
M *m;
|
||||||
M *mp;
|
M *mp;
|
||||||
int64 deadline, now;
|
int64 deadline, now;
|
||||||
|
|
||||||
@ -166,6 +172,7 @@ runtime_notetsleep(Note *n, int64 ns)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m = runtime_m();
|
||||||
if(m->waitsema == 0)
|
if(m->waitsema == 0)
|
||||||
m->waitsema = runtime_semacreate();
|
m->waitsema = runtime_semacreate();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@ -9,19 +10,43 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
/* If we don't have sem_timedwait, use pthread_cond_timedwait instead.
|
||||||
|
We don't always use condition variables because on some systems
|
||||||
|
pthread_mutex_lock and pthread_mutex_unlock must be called by the
|
||||||
|
same thread. That is never true of semaphores. */
|
||||||
|
|
||||||
|
struct go_sem
|
||||||
|
{
|
||||||
|
sem_t sem;
|
||||||
|
|
||||||
|
#ifndef HAVE_SEM_TIMEDWAIT
|
||||||
|
int timedwait;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/* Create a semaphore. */
|
/* Create a semaphore. */
|
||||||
|
|
||||||
uintptr
|
uintptr
|
||||||
runtime_semacreate(void)
|
runtime_semacreate(void)
|
||||||
{
|
{
|
||||||
sem_t *p;
|
struct go_sem *p;
|
||||||
|
|
||||||
/* Call malloc rather than runtime_malloc. This will allocate space
|
/* Call malloc rather than runtime_malloc. This will allocate space
|
||||||
on the C heap. We can't call runtime_malloc here because it
|
on the C heap. We can't call runtime_malloc here because it
|
||||||
could cause a deadlock. */
|
could cause a deadlock. */
|
||||||
p = malloc (sizeof (sem_t));
|
p = malloc (sizeof (struct go_sem));
|
||||||
if (sem_init (p, 0, 0) != 0)
|
if (sem_init (&p->sem, 0, 0) != 0)
|
||||||
runtime_throw ("sem_init");
|
runtime_throw ("sem_init");
|
||||||
|
|
||||||
|
#ifndef HAVE_SEM_TIMEDWAIT
|
||||||
|
if (pthread_mutex_init (&p->mutex, NULL) != 0)
|
||||||
|
runtime_throw ("pthread_mutex_init");
|
||||||
|
if (pthread_cond_init (&p->cond, NULL) != 0)
|
||||||
|
runtime_throw ("pthread_cond_init");
|
||||||
|
#endif
|
||||||
|
|
||||||
return (uintptr) p;
|
return (uintptr) p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,26 +55,56 @@ runtime_semacreate(void)
|
|||||||
int32
|
int32
|
||||||
runtime_semasleep (int64 ns)
|
runtime_semasleep (int64 ns)
|
||||||
{
|
{
|
||||||
|
M *m;
|
||||||
|
struct go_sem *sem;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
m = runtime_m ();
|
||||||
|
sem = (struct go_sem *) m->waitsema;
|
||||||
if (ns >= 0)
|
if (ns >= 0)
|
||||||
{
|
{
|
||||||
|
int64 abs;
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
int err;
|
||||||
|
|
||||||
ns += runtime_nanotime ();
|
abs = ns + runtime_nanotime ();
|
||||||
ts.tv_sec = ns / 1000000000LL;
|
ts.tv_sec = abs / 1000000000LL;
|
||||||
ts.tv_nsec = ns % 1000000000LL;
|
ts.tv_nsec = abs % 1000000000LL;
|
||||||
r = sem_timedwait ((sem_t *) m->waitsema, &ts);
|
|
||||||
|
err = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_SEM_TIMEDWAIT
|
||||||
|
r = sem_timedwait (&sem->sem, &ts);
|
||||||
|
if (r != 0)
|
||||||
|
err = errno;
|
||||||
|
#else
|
||||||
|
if (pthread_mutex_lock (&sem->mutex) != 0)
|
||||||
|
runtime_throw ("pthread_mutex_lock");
|
||||||
|
|
||||||
|
while ((r = sem_trywait (&sem->sem)) != 0)
|
||||||
|
{
|
||||||
|
r = pthread_cond_timedwait (&sem->cond, &sem->mutex, &ts);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
{
|
{
|
||||||
if (errno == ETIMEDOUT || errno == EINTR)
|
err = r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock (&sem->mutex) != 0)
|
||||||
|
runtime_throw ("pthread_mutex_unlock");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (err != 0)
|
||||||
|
{
|
||||||
|
if (err == ETIMEDOUT || err == EAGAIN || err == EINTR)
|
||||||
return -1;
|
return -1;
|
||||||
runtime_throw ("sema_timedwait");
|
runtime_throw ("sema_timedwait");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sem_wait ((sem_t *) m->waitsema) != 0)
|
while (sem_wait (&sem->sem) != 0)
|
||||||
{
|
{
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@ -64,8 +119,20 @@ runtime_semasleep (int64 ns)
|
|||||||
void
|
void
|
||||||
runtime_semawakeup (M *mp)
|
runtime_semawakeup (M *mp)
|
||||||
{
|
{
|
||||||
if (sem_post ((sem_t *) mp->waitsema) != 0)
|
struct go_sem *sem;
|
||||||
|
|
||||||
|
sem = (struct go_sem *) mp->waitsema;
|
||||||
|
if (sem_post (&sem->sem) != 0)
|
||||||
runtime_throw ("sem_post");
|
runtime_throw ("sem_post");
|
||||||
|
|
||||||
|
#ifndef HAVE_SEM_TIMEDWAIT
|
||||||
|
if (pthread_mutex_lock (&sem->mutex) != 0)
|
||||||
|
runtime_throw ("pthread_mutex_lock");
|
||||||
|
if (pthread_cond_broadcast (&sem->cond) != 0)
|
||||||
|
runtime_throw ("pthread_cond_broadcast");
|
||||||
|
if (pthread_mutex_unlock (&sem->mutex) != 0)
|
||||||
|
runtime_throw ("pthread_mutex_unlock");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user