summaryrefslogtreecommitdiff
path: root/libguile/fluids.c
diff options
context:
space:
mode:
authorMarius Vollmer <mvo@zagadka.de>2005-03-09 19:20:49 +0000
committerMarius Vollmer <mvo@zagadka.de>2005-03-09 19:20:49 +0000
commitb5fa979ca6d33533189d617a85e17f2a99345068 (patch)
tree8d877919ebabe8fb30468bde16a4938bd2065b20 /libguile/fluids.c
parent443840184b38dbf1223e2bc09e565aaa901a1564 (diff)
downloadguile-b5fa979ca6d33533189d617a85e17f2a99345068.tar.gz
(ensure_state_size, ensure_all_state_sizes, resize_all_states):
Collapsed ensure_state_size and ensure_all_state_sizes into one function named resize_all_states. Allocate new vectors outside of single threaded region. Do only simple things inside that region. (scm_make_fluid, scm_make_dynamic_state): Lock fluid_admin_mutex while adding to the global lists.
Diffstat (limited to 'libguile/fluids.c')
-rw-r--r--libguile/fluids.c66
1 files changed, 36 insertions, 30 deletions
diff --git a/libguile/fluids.c b/libguile/fluids.c
index ab27029f8..bee2bda6d 100644
--- a/libguile/fluids.c
+++ b/libguile/fluids.c
@@ -80,43 +80,46 @@ static scm_t_bits tc16_dynamic_state;
static SCM all_dynamic_states = SCM_EOL;
static SCM all_fluids = SCM_EOL;
-/* Make sure that the dynamic state STATE has the right size. This
- must be called while being single threaded and while
- fluid_admin_mutex is held.
-*/
-static void
-ensure_state_size (SCM state)
-{
- SCM fluids = DYNAMIC_STATE_FLUIDS (state);
- size_t len = SCM_SIMPLE_VECTOR_LENGTH (fluids), i;
-
- if (len != allocated_fluids_len)
- {
- SCM new_fluids = scm_c_make_vector (allocated_fluids_len, SCM_BOOL_F);
- for (i = 0; i < len; i++)
- SCM_SIMPLE_VECTOR_SET (new_fluids, i,
- SCM_SIMPLE_VECTOR_REF (fluids, i));
- SET_DYNAMIC_STATE_FLUIDS (state, new_fluids);
- }
-}
-
/* Make sure that all states have the right size. This must be called
while fluid_admin_mutex is held.
*/
static void
-ensure_all_state_sizes ()
-{
- SCM state;
+resize_all_states ()
+{
+ SCM new_vectors, state;
+
+ /* Replacing the vector of a dynamic state must be done atomically:
+ the old values must be copied into the new vector and the new
+ vector must be installed without someone modifying the old vector
+ concurrently. Since accessing a fluid should be lock-free, we
+ need to put all threads to sleep when replacing a vector.
+ However, when being single threaded, it is best not to do much.
+ Therefore, we allocate the new vectors before going single
+ threaded.
+ */
- scm_frame_begin (0);
- scm_i_frame_single_threaded ();
+ new_vectors = SCM_EOL;
+ for (state = all_dynamic_states; !scm_is_null (state);
+ state = DYNAMIC_STATE_NEXT (state))
+ new_vectors = scm_cons (scm_c_make_vector (allocated_fluids_len,
+ SCM_BOOL_F),
+ new_vectors);
- scm_gc ();
+ scm_i_thread_put_to_sleep ();
for (state = all_dynamic_states; !scm_is_null (state);
state = DYNAMIC_STATE_NEXT (state))
- ensure_state_size (state);
+ {
+ SCM old_fluids = DYNAMIC_STATE_FLUIDS (state);
+ SCM new_fluids = SCM_CAR (new_vectors);
+ size_t i, old_len = SCM_SIMPLE_VECTOR_LENGTH (old_fluids);
- scm_frame_end ();
+ for (i = 0; i < old_len; i++)
+ SCM_SIMPLE_VECTOR_SET (new_fluids, i,
+ SCM_SIMPLE_VECTOR_REF (old_fluids, i));
+ SET_DYNAMIC_STATE_FLUIDS (state, new_fluids);
+ new_vectors = SCM_CDR (new_vectors);
+ }
+ scm_i_thread_wake_up ();
}
/* This is called during GC, that is, while being single threaded.
@@ -236,7 +239,7 @@ next_fluid_num ()
/* Now allocated_fluids and allocated_fluids_len are valid again
and we can allow GCs to occur.
*/
- ensure_all_state_sizes ();
+ resize_all_states ();
}
allocated_fluids_num += 1;
@@ -265,8 +268,10 @@ SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
/* The GC must not run until the fluid is properly entered into the
list.
*/
+ scm_i_scm_pthread_mutex_lock (&fluid_admin_mutex);
SET_FLUID_NEXT (fluid, all_fluids);
all_fluids = fluid;
+ scm_i_pthread_mutex_unlock (&fluid_admin_mutex);
return fluid;
}
@@ -495,10 +500,11 @@ SCM_DEFINE (scm_make_dynamic_state, "make-dynamic-state", 0, 1, 0,
/* The GC must not run until the state is properly entered into the
list.
*/
+ scm_i_scm_pthread_mutex_lock (&fluid_admin_mutex);
SET_DYNAMIC_STATE_NEXT (state, all_dynamic_states);
all_dynamic_states = state;
+ scm_i_pthread_mutex_unlock (&fluid_admin_mutex);
- //fprintf (stderr, "new state %p\n", state);
return state;
}
#undef FUNC_NAME