summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@oblong.net>2009-03-17 15:52:41 +0100
committerAndy Wingo <wingo@oblong.net>2009-03-17 15:52:41 +0100
commitfcbf843f56bf894f4899d39d494a5046e4a8f597 (patch)
treee5760278b98722c2c806b806fb0caf1e8159ef54
parentdeca2251b9d9128f62142b369a309caf05dbaa88 (diff)
parent8b0174c879bf74981efe702a00471ed5b8e6912e (diff)
downloadguile-fcbf843f56bf894f4899d39d494a5046e4a8f597.tar.gz
Merge commit '8b0174c879bf74981efe702a00471ed5b8e6912e' into vm-check
-rw-r--r--libguile/threads.c18
-rw-r--r--libguile/threads.h7
2 files changed, 22 insertions, 3 deletions
diff --git a/libguile/threads.c b/libguile/threads.c
index 2787ed4bd..bb874e230 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -410,6 +410,7 @@ scm_enter_guile (scm_t_guile_ticket ticket)
if (t)
{
scm_i_pthread_mutex_lock (&t->heap_mutex);
+ t->heap_mutex_locked_by_self = 1;
resume (t);
}
}
@@ -431,7 +432,11 @@ static scm_t_guile_ticket
scm_leave_guile ()
{
scm_i_thread *t = suspend ();
- scm_i_pthread_mutex_unlock (&t->heap_mutex);
+ if (t->heap_mutex_locked_by_self)
+ {
+ t->heap_mutex_locked_by_self = 0;
+ scm_i_pthread_mutex_unlock (&t->heap_mutex);
+ }
return (scm_t_guile_ticket) t;
}
@@ -492,6 +497,7 @@ guilify_self_1 (SCM_STACKITEM *base)
abort ();
scm_i_pthread_mutex_init (&t->heap_mutex, NULL);
+ t->heap_mutex_locked_by_self = 0;
scm_i_pthread_mutex_init (&t->admin_mutex, NULL);
t->clear_freelists_p = 0;
t->gc_running_p = 0;
@@ -506,6 +512,7 @@ guilify_self_1 (SCM_STACKITEM *base)
scm_i_pthread_setspecific (scm_i_thread_key, t);
scm_i_pthread_mutex_lock (&t->heap_mutex);
+ t->heap_mutex_locked_by_self = 1;
scm_i_pthread_mutex_lock (&thread_admin_mutex);
t->next_thread = all_threads;
@@ -1994,9 +2001,14 @@ void
scm_i_thread_sleep_for_gc ()
{
scm_i_thread *t = suspend ();
- t->held_mutex = &t->heap_mutex;
+
+ /* Don't put t->heap_mutex in t->held_mutex here, because if the
+ thread is cancelled during the cond wait, the thread's cleanup
+ function (scm_leave_guile_cleanup) will handle unlocking the
+ heap_mutex, so we don't need to do that again in on_thread_exit.
+ */
scm_i_pthread_cond_wait (&wake_up_cond, &t->heap_mutex);
- t->held_mutex = NULL;
+
resume (t);
}
diff --git a/libguile/threads.h b/libguile/threads.h
index a1d3c655a..8c2694d4d 100644
--- a/libguile/threads.h
+++ b/libguile/threads.h
@@ -72,6 +72,13 @@ typedef struct scm_i_thread {
*/
scm_i_pthread_mutex_t heap_mutex;
+ /* Boolean tracking whether the above mutex is currently locked by
+ this thread. This is equivalent to whether or not the thread is
+ in "Guile mode". This field doesn't need any protection because
+ it is only ever set or tested by the owning thread.
+ */
+ int heap_mutex_locked_by_self;
+
/* The freelists of this thread. Each thread has its own lists so
that they can all allocate concurrently.
*/