-/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004,
+ * 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+ * Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
#include "libguile/bdw-gc.h"
#include "libguile/_scm.h"
+#include <stdlib.h>
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <sys/time.h>
#endif
+#if HAVE_PTHREAD_NP_H
+# include <pthread_np.h>
+#endif
+
#include <assert.h>
#include <fcntl.h>
#include <nproc.h>
return pthread_get_stackaddr_np (pthread_self ());
}
+#elif HAVE_PTHREAD_ATTR_GET_NP
+/* This one is for FreeBSD 9. */
+static void *
+get_thread_stack_base ()
+{
+ pthread_attr_t attr;
+ void *start, *end;
+ size_t size;
+
+ pthread_attr_init (&attr);
+ pthread_attr_get_np (pthread_self (), &attr);
+ pthread_attr_getstack (&attr, &start, &size);
+ pthread_attr_destroy (&attr);
+
+ end = (char *)start + size;
+
+#if SCM_STACK_GROWS_UP
+ return start;
+#else
+ return end;
+#endif
+}
+
#else
#error Threads enabled with old BDW-GC, but missing get_thread_stack_base impl. Please upgrade to libgc >= 7.1.
#endif
/* Run when a fluid is collected. */
void
-scm_i_reset_fluid (size_t n, SCM val)
+scm_i_reset_fluid (size_t n)
{
scm_i_thread *t;
SCM v = SCM_I_DYNAMIC_STATE_FLUIDS (t->dynamic_state);
if (n < SCM_SIMPLE_VECTOR_LENGTH (v))
- SCM_SIMPLE_VECTOR_SET (v, n, val);
+ SCM_SIMPLE_VECTOR_SET (v, n, SCM_UNDEFINED);
}
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
}
t.critical_section_level = 0;
t.base = base->mem_base;
#ifdef __ia64__
- t.register_backing_store_base = base->reg-base;
+ t.register_backing_store_base = base->reg_base;
#endif
t.continuation_root = SCM_EOL;
t.continuation_base = t.base;
t->join_queue = make_queue ();
t->block_asyncs = 0;
+
+ /* See note in finalizers.c:queue_finalizer_async(). */
+ GC_invoke_finalizers ();
}
\f
scm_i_pthread_mutex_lock (&m->lock);
- /* Since MUTEX is in `t->mutexes', T must be its owner. */
- assert (scm_is_eq (m->owner, t->handle));
-
- unblock_from_queue (m->waiting);
+ /* Check whether T owns MUTEX. This is usually the case, unless
+ T abandoned MUTEX; in that case, T is no longer its owner (see
+ `fat_mutex_lock') but MUTEX is still in `t->mutexes'. */
+ if (scm_is_eq (m->owner, t->handle))
+ unblock_from_queue (m->waiting);
scm_i_pthread_mutex_unlock (&m->lock);
}
/* This handler is executed in non-guile mode. */
scm_i_thread *t = (scm_i_thread *) v, **tp;
+ /* If we were canceled, we were unable to clear `t->guile_mode', so do
+ it here. */
+ t->guile_mode = 0;
+
/* If this thread was cancelled while doing a cond wait, it will
still have a mutex locked, so we unlock it here. */
if (t->held_mutex)
else
{
fprintf (stderr, "Failed to get stack base for current thread.\n");
- exit (1);
+ exit (EXIT_FAILURE);
}
}
-SCM_UNUSED static void
-scm_leave_guile_cleanup (void *x)
-{
- on_thread_exit (SCM_I_CURRENT_THREAD);
-}
-
struct with_guile_args
{
GC_fn_type func;
SCM_ASSERT (SCM_UNBNDP (handler) || scm_is_true (scm_procedure_p (handler)),
handler, SCM_ARG2, FUNC_NAME);
+ GC_collect_a_little ();
data.parent = scm_current_dynamic_state ();
data.thunk = thunk;
data.handler = handler;
scm_i_scm_pthread_cond_wait (&data.cond, &data.mutex);
scm_i_pthread_mutex_unlock (&data.mutex);
+ assert (SCM_I_IS_THREAD (data.thread));
+
return data.thread;
}
{
scm_i_thread *t = SCM_I_THREAD_DATA (new_owner);
- scm_i_pthread_mutex_unlock (&m->lock);
+ /* FIXME: The order in which `t->admin_mutex' and
+ `m->lock' are taken differs from that in
+ `on_thread_exit', potentially leading to deadlocks. */
scm_i_pthread_mutex_lock (&t->admin_mutex);
/* Only keep a weak reference to MUTEX so that it's not
t->mutexes = scm_weak_car_pair (mutex, t->mutexes);
scm_i_pthread_mutex_unlock (&t->admin_mutex);
- scm_i_pthread_mutex_lock (&m->lock);
}
*ret = 1;
break;
SCM_DEFINE (scm_lock_mutex_timed, "lock-mutex", 1, 2, 0,
(SCM m, SCM timeout, SCM owner),
-"Lock @var{mutex}. If the mutex is already locked, the calling thread "
-"blocks until the mutex becomes available. The function returns when "
-"the calling thread owns the lock on @var{mutex}. Locking a mutex that "
-"a thread already owns will succeed right away and will not block the "
-"thread. That is, Guile's mutexes are @emph{recursive}. ")
+ "Lock mutex @var{m}. If the mutex is already locked, the calling\n"
+ "thread blocks until the mutex becomes available. The function\n"
+ "returns when the calling thread owns the lock on @var{m}.\n"
+ "Locking a mutex that a thread already owns will succeed right\n"
+ "away and will not block the thread. That is, Guile's mutexes\n"
+ "are @emph{recursive}.")
#define FUNC_NAME s_scm_lock_mutex_timed
{
SCM exception;
waittime = &cwaittime;
}
+ if (!SCM_UNBNDP (owner) && !scm_is_false (owner))
+ SCM_VALIDATE_THREAD (3, owner);
+
exception = fat_mutex_lock (m, waittime, owner, &ret);
if (!scm_is_false (exception))
scm_ithrow (SCM_CAR (exception), scm_list_1 (SCM_CDR (exception)), 1);
SCM_DEFINE (scm_timed_wait_condition_variable, "wait-condition-variable", 2, 1, 0,
(SCM cv, SCM mx, SCM t),
-"Wait until @var{cond-var} has been signalled. While waiting, "
-"@var{mutex} is atomically unlocked (as with @code{unlock-mutex}) and "
-"is locked again when this function returns. When @var{time} is given, "
+"Wait until condition variable @var{cv} has been signalled. While waiting, "
+"mutex @var{mx} is atomically unlocked (as with @code{unlock-mutex}) and "
+"is locked again when this function returns. When @var{t} is given, "
"it specifies a point in time where the waiting should be aborted. It "
"can be either a integer as returned by @code{current-time} or a pair "
"as returned by @code{gettimeofday}. When the waiting is aborted the "
return (void *) ctx->uc_mcontext.sc_ar_bsp;
}
# endif /* linux */
+# ifdef __FreeBSD__
+# include <ucontext.h>
+void *
+scm_ia64_register_backing_store_base (void)
+{
+ return (void *)0x8000000000000000;
+}
+void *
+scm_ia64_ar_bsp (const void *opaque)
+{
+ const ucontext_t *ctx = opaque;
+ return (void *)(ctx->uc_mcontext.mc_special.bspstore
+ + ctx->uc_mcontext.mc_special.ndirty);
+}
+# endif /* __FreeBSD__ */
#endif /* __ia64__ */