diff options
author | Andy Wingo <wingo@oblong.net> | 2009-03-17 15:52:41 +0100 |
---|---|---|
committer | Andy Wingo <wingo@oblong.net> | 2009-03-17 15:52:41 +0100 |
commit | fcbf843f56bf894f4899d39d494a5046e4a8f597 (patch) | |
tree | e5760278b98722c2c806b806fb0caf1e8159ef54 | |
parent | deca2251b9d9128f62142b369a309caf05dbaa88 (diff) | |
parent | 8b0174c879bf74981efe702a00471ed5b8e6912e (diff) | |
download | guile-fcbf843f56bf894f4899d39d494a5046e4a8f597.tar.gz |
Merge commit '8b0174c879bf74981efe702a00471ed5b8e6912e' into vm-check
-rw-r--r-- | libguile/threads.c | 18 | ||||
-rw-r--r-- | libguile/threads.h | 7 |
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. */ |