fix some O(N) problems for N threads
Repairs include GC setup, thread finalization, and place synchronization.
This commit is contained in:
parent
b5f0c97762
commit
c89fa0cda7
|
@ -1046,6 +1046,8 @@ typedef struct Scheme_Thread {
|
||||||
Scheme_Object *dead_box; /* contains non-zero when the thread is dead */
|
Scheme_Object *dead_box; /* contains non-zero when the thread is dead */
|
||||||
Scheme_Object *running_box; /* contains pointer to thread when it's running */
|
Scheme_Object *running_box; /* contains pointer to thread when it's running */
|
||||||
|
|
||||||
|
struct Scheme_Thread *gc_prep_chain;
|
||||||
|
|
||||||
struct Scheme_Thread *nester, *nestee;
|
struct Scheme_Thread *nester, *nestee;
|
||||||
|
|
||||||
struct future_t *current_ft;
|
struct future_t *current_ft;
|
||||||
|
|
|
@ -230,6 +230,7 @@ typedef struct Thread_Local_Variables {
|
||||||
struct Scheme_Thread *scheme_current_thread_;
|
struct Scheme_Thread *scheme_current_thread_;
|
||||||
struct Scheme_Thread *scheme_main_thread_;
|
struct Scheme_Thread *scheme_main_thread_;
|
||||||
struct Scheme_Thread *scheme_first_thread_;
|
struct Scheme_Thread *scheme_first_thread_;
|
||||||
|
struct Scheme_Thread *gc_prep_thread_chain_;
|
||||||
struct Scheme_Thread_Set *scheme_thread_set_top_;
|
struct Scheme_Thread_Set *scheme_thread_set_top_;
|
||||||
struct Scheme_Current_LWC *scheme_current_lwc_;
|
struct Scheme_Current_LWC *scheme_current_lwc_;
|
||||||
int num_running_threads_;
|
int num_running_threads_;
|
||||||
|
@ -333,6 +334,7 @@ typedef struct Thread_Local_Variables {
|
||||||
int place_evts_array_size_;
|
int place_evts_array_size_;
|
||||||
struct Evt **place_evts_;
|
struct Evt **place_evts_;
|
||||||
struct Scheme_Place_Object *place_object_;
|
struct Scheme_Place_Object *place_object_;
|
||||||
|
struct Scheme_Place *all_child_places_;
|
||||||
struct Scheme_Object **reusable_ifs_stack_;
|
struct Scheme_Object **reusable_ifs_stack_;
|
||||||
struct Scheme_Object *empty_self_shift_cache_;
|
struct Scheme_Object *empty_self_shift_cache_;
|
||||||
struct Scheme_Bucket_Table *scheme_module_code_cache_;
|
struct Scheme_Bucket_Table *scheme_module_code_cache_;
|
||||||
|
@ -575,6 +577,7 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
|
||||||
#define scheme_current_thread XOA (scheme_get_thread_local_variables()->scheme_current_thread_)
|
#define scheme_current_thread XOA (scheme_get_thread_local_variables()->scheme_current_thread_)
|
||||||
#define scheme_main_thread XOA (scheme_get_thread_local_variables()->scheme_main_thread_)
|
#define scheme_main_thread XOA (scheme_get_thread_local_variables()->scheme_main_thread_)
|
||||||
#define scheme_first_thread XOA (scheme_get_thread_local_variables()->scheme_first_thread_)
|
#define scheme_first_thread XOA (scheme_get_thread_local_variables()->scheme_first_thread_)
|
||||||
|
#define gc_prep_thread_chain XOA (scheme_get_thread_local_variables()->gc_prep_thread_chain_)
|
||||||
#define scheme_thread_set_top XOA (scheme_get_thread_local_variables()->scheme_thread_set_top_)
|
#define scheme_thread_set_top XOA (scheme_get_thread_local_variables()->scheme_thread_set_top_)
|
||||||
#define scheme_current_lwc XOA (scheme_get_thread_local_variables()->scheme_current_lwc_)
|
#define scheme_current_lwc XOA (scheme_get_thread_local_variables()->scheme_current_lwc_)
|
||||||
#define num_running_threads XOA (scheme_get_thread_local_variables()->num_running_threads_)
|
#define num_running_threads XOA (scheme_get_thread_local_variables()->num_running_threads_)
|
||||||
|
@ -678,6 +681,7 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
|
||||||
#define place_evts_array_size XOA (scheme_get_thread_local_variables()->place_evts_array_size_)
|
#define place_evts_array_size XOA (scheme_get_thread_local_variables()->place_evts_array_size_)
|
||||||
#define place_evts XOA (scheme_get_thread_local_variables()->place_evts_)
|
#define place_evts XOA (scheme_get_thread_local_variables()->place_evts_)
|
||||||
#define place_object XOA (scheme_get_thread_local_variables()->place_object_)
|
#define place_object XOA (scheme_get_thread_local_variables()->place_object_)
|
||||||
|
#define all_child_places XOA (scheme_get_thread_local_variables()->all_child_places_)
|
||||||
#define reusable_ifs_stack XOA (scheme_get_thread_local_variables()->reusable_ifs_stack_)
|
#define reusable_ifs_stack XOA (scheme_get_thread_local_variables()->reusable_ifs_stack_)
|
||||||
#define empty_self_shift_cache XOA (scheme_get_thread_local_variables()->empty_self_shift_cache_)
|
#define empty_self_shift_cache XOA (scheme_get_thread_local_variables()->empty_self_shift_cache_)
|
||||||
#define scheme_module_code_cache XOA (scheme_get_thread_local_variables()->scheme_module_code_cache_)
|
#define scheme_module_code_cache XOA (scheme_get_thread_local_variables()->scheme_module_code_cache_)
|
||||||
|
|
|
@ -57,6 +57,8 @@ static int place_val_MARK(void *p, struct NewGC *gc) {
|
||||||
gcMARK2(pr->mref, gc);
|
gcMARK2(pr->mref, gc);
|
||||||
gcMARK2(pr->pumper_threads, gc);
|
gcMARK2(pr->pumper_threads, gc);
|
||||||
gcMARK2(pr->place_obj, gc);
|
gcMARK2(pr->place_obj, gc);
|
||||||
|
gcMARK2(pr->prev, gc);
|
||||||
|
gcMARK2(pr->next, gc);
|
||||||
|
|
||||||
return
|
return
|
||||||
gcBYTES_TO_WORDS(sizeof(Scheme_Place));
|
gcBYTES_TO_WORDS(sizeof(Scheme_Place));
|
||||||
|
@ -68,6 +70,8 @@ static int place_val_FIXUP(void *p, struct NewGC *gc) {
|
||||||
gcFIXUP2(pr->mref, gc);
|
gcFIXUP2(pr->mref, gc);
|
||||||
gcFIXUP2(pr->pumper_threads, gc);
|
gcFIXUP2(pr->pumper_threads, gc);
|
||||||
gcFIXUP2(pr->place_obj, gc);
|
gcFIXUP2(pr->place_obj, gc);
|
||||||
|
gcFIXUP2(pr->prev, gc);
|
||||||
|
gcFIXUP2(pr->next, gc);
|
||||||
|
|
||||||
return
|
return
|
||||||
gcBYTES_TO_WORDS(sizeof(Scheme_Place));
|
gcBYTES_TO_WORDS(sizeof(Scheme_Place));
|
||||||
|
|
|
@ -1497,6 +1497,8 @@ place_val {
|
||||||
gcMARK2(pr->mref, gc);
|
gcMARK2(pr->mref, gc);
|
||||||
gcMARK2(pr->pumper_threads, gc);
|
gcMARK2(pr->pumper_threads, gc);
|
||||||
gcMARK2(pr->place_obj, gc);
|
gcMARK2(pr->place_obj, gc);
|
||||||
|
gcMARK2(pr->prev, gc);
|
||||||
|
gcMARK2(pr->next, gc);
|
||||||
|
|
||||||
size:
|
size:
|
||||||
gcBYTES_TO_WORDS(sizeof(Scheme_Place));
|
gcBYTES_TO_WORDS(sizeof(Scheme_Place));
|
||||||
|
|
|
@ -45,6 +45,7 @@ static mzrt_mutex *id_counter_mutex;
|
||||||
|
|
||||||
SHARED_OK mz_proc_thread *scheme_master_proc_thread;
|
SHARED_OK mz_proc_thread *scheme_master_proc_thread;
|
||||||
THREAD_LOCAL_DECL(static struct Scheme_Place_Object *place_object);
|
THREAD_LOCAL_DECL(static struct Scheme_Place_Object *place_object);
|
||||||
|
THREAD_LOCAL_DECL(static Scheme_Place *all_child_places);
|
||||||
THREAD_LOCAL_DECL(static uintptr_t force_gc_for_place_accounting);
|
THREAD_LOCAL_DECL(static uintptr_t force_gc_for_place_accounting);
|
||||||
static Scheme_Object *scheme_place(int argc, Scheme_Object *args[]);
|
static Scheme_Object *scheme_place(int argc, Scheme_Object *args[]);
|
||||||
static Scheme_Object *place_pumper_threads(int argc, Scheme_Object *args[]);
|
static Scheme_Object *place_pumper_threads(int argc, Scheme_Object *args[]);
|
||||||
|
@ -144,6 +145,8 @@ void scheme_init_place(Scheme_Env *env)
|
||||||
PLACE_PRIM_W_ARITY("place-dead-evt", make_place_dead, 1, 1, plenv);
|
PLACE_PRIM_W_ARITY("place-dead-evt", make_place_dead, 1, 1, plenv);
|
||||||
|
|
||||||
scheme_finish_primitive_module(plenv);
|
scheme_finish_primitive_module(plenv);
|
||||||
|
|
||||||
|
REGISTER_SO(all_child_places);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Scheme_Object* scheme_place_enabled(int argc, Scheme_Object *args[]) {
|
static Scheme_Object* scheme_place_enabled(int argc, Scheme_Object *args[]) {
|
||||||
|
@ -457,6 +460,11 @@ Scheme_Object *scheme_place(int argc, Scheme_Object *args[]) {
|
||||||
|
|
||||||
place_data->ready = NULL;
|
place_data->ready = NULL;
|
||||||
place_data->place_obj = NULL;
|
place_data->place_obj = NULL;
|
||||||
|
|
||||||
|
place->next = all_child_places;
|
||||||
|
if (place->next)
|
||||||
|
place->next->prev = place;
|
||||||
|
all_child_places = place;
|
||||||
|
|
||||||
{
|
{
|
||||||
Scheme_Custodian_Reference *mref;
|
Scheme_Custodian_Reference *mref;
|
||||||
|
@ -528,6 +536,14 @@ static void do_place_kill(Scheme_Place *place)
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme_remove_managed(place->mref, (Scheme_Object *)place);
|
scheme_remove_managed(place->mref, (Scheme_Object *)place);
|
||||||
|
|
||||||
|
if (place->next)
|
||||||
|
place->next->prev = place->prev;
|
||||||
|
if (place->prev)
|
||||||
|
place->prev->next = place->next;
|
||||||
|
else
|
||||||
|
all_child_places = place->next;
|
||||||
|
|
||||||
if (!refcount) {
|
if (!refcount) {
|
||||||
destroy_place_object_locks(place_obj);
|
destroy_place_object_locks(place_obj);
|
||||||
}
|
}
|
||||||
|
@ -2206,7 +2222,7 @@ static void *place_start_proc(void *data_arg) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheme_pause_one_place(Scheme_Place *p)
|
static void pause_one_place(Scheme_Place *p)
|
||||||
{
|
{
|
||||||
Scheme_Place_Object *place_obj = p->place_obj;
|
Scheme_Place_Object *place_obj = p->place_obj;
|
||||||
|
|
||||||
|
@ -2234,7 +2250,7 @@ static void resume_one_place_with_lock(Scheme_Place_Object *place_obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheme_resume_one_place(Scheme_Place *p)
|
static void resume_one_place(Scheme_Place *p)
|
||||||
{
|
{
|
||||||
Scheme_Place_Object *place_obj = p->place_obj;
|
Scheme_Place_Object *place_obj = p->place_obj;
|
||||||
|
|
||||||
|
@ -2245,6 +2261,24 @@ void scheme_resume_one_place(Scheme_Place *p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void pause_all_child_places()
|
||||||
|
{
|
||||||
|
Scheme_Place *p = all_child_places;
|
||||||
|
while (p) {
|
||||||
|
pause_one_place(p);
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resume_all_child_places()
|
||||||
|
{
|
||||||
|
Scheme_Place *p = all_child_places;
|
||||||
|
while (p) {
|
||||||
|
resume_one_place(p);
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void destroy_place_object_locks(Scheme_Place_Object *place_obj) {
|
void destroy_place_object_locks(Scheme_Place_Object *place_obj) {
|
||||||
mzrt_mutex_destroy(place_obj->lock);
|
mzrt_mutex_destroy(place_obj->lock);
|
||||||
if (place_obj->pause)
|
if (place_obj->pause)
|
||||||
|
@ -2279,10 +2313,10 @@ void scheme_place_check_for_interruption()
|
||||||
mzrt_mutex_unlock(place_obj->lock);
|
mzrt_mutex_unlock(place_obj->lock);
|
||||||
|
|
||||||
if (local_pause) {
|
if (local_pause) {
|
||||||
scheme_pause_all_places();
|
pause_all_child_places();
|
||||||
mzrt_sema_wait(local_pause);
|
mzrt_sema_wait(local_pause);
|
||||||
mzrt_sema_destroy(local_pause);
|
mzrt_sema_destroy(local_pause);
|
||||||
scheme_resume_all_places();
|
resume_all_child_places();
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2311,7 +2345,7 @@ void scheme_place_set_memory_use(intptr_t mem_use)
|
||||||
custodian limits that will kill this place; pause this
|
custodian limits that will kill this place; pause this
|
||||||
place and its children to give the original place time
|
place and its children to give the original place time
|
||||||
to kill this one */
|
to kill this one */
|
||||||
scheme_pause_all_places();
|
pause_all_child_places();
|
||||||
mzrt_ensure_max_cas(place_obj->parent_need_gc, 1);
|
mzrt_ensure_max_cas(place_obj->parent_need_gc, 1);
|
||||||
scheme_signal_received_at(place_obj->parent_signal_handle);
|
scheme_signal_received_at(place_obj->parent_signal_handle);
|
||||||
} else if (mem_use > (1 + place_obj->use_factor) * place_obj->prev_notify_memory_use) {
|
} else if (mem_use > (1 + place_obj->use_factor) * place_obj->prev_notify_memory_use) {
|
||||||
|
@ -2334,7 +2368,7 @@ void scheme_place_check_memory_use()
|
||||||
if (force_gc_for_place_accounting) {
|
if (force_gc_for_place_accounting) {
|
||||||
force_gc_for_place_accounting = 0;
|
force_gc_for_place_accounting = 0;
|
||||||
scheme_collect_garbage();
|
scheme_collect_garbage();
|
||||||
scheme_resume_all_places();
|
resume_all_child_places();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2462,7 +2496,7 @@ static void *place_start_proc_after_stack(void *data_arg, void *stack_base) {
|
||||||
REGISTER_SO(place_object);
|
REGISTER_SO(place_object);
|
||||||
place_object = place_obj;
|
place_object = place_obj;
|
||||||
place_obj->refcount++;
|
place_obj->refcount++;
|
||||||
|
|
||||||
{
|
{
|
||||||
void *signal_handle;
|
void *signal_handle;
|
||||||
signal_handle = scheme_get_signal_handle();
|
signal_handle = scheme_get_signal_handle();
|
||||||
|
|
|
@ -3815,6 +3815,8 @@ typedef struct Scheme_Place {
|
||||||
struct GC_Thread_Info *gc_info; /* managed by the GC */
|
struct GC_Thread_Info *gc_info; /* managed by the GC */
|
||||||
#endif
|
#endif
|
||||||
Scheme_Object *pumper_threads; /* Scheme_Vector of scheme threads */
|
Scheme_Object *pumper_threads; /* Scheme_Vector of scheme threads */
|
||||||
|
|
||||||
|
struct Scheme_Place *prev, *next; /* keeping a list of child places */
|
||||||
} Scheme_Place;
|
} Scheme_Place;
|
||||||
|
|
||||||
typedef struct Scheme_Place_Object {
|
typedef struct Scheme_Place_Object {
|
||||||
|
@ -3882,9 +3884,4 @@ void scheme_place_set_memory_use(intptr_t amt);
|
||||||
void scheme_place_check_memory_use();
|
void scheme_place_check_memory_use();
|
||||||
void scheme_clear_place_ifs_stack();
|
void scheme_clear_place_ifs_stack();
|
||||||
|
|
||||||
void scheme_pause_all_places();
|
|
||||||
void scheme_pause_one_place(Scheme_Place *p);
|
|
||||||
void scheme_resume_all_places();
|
|
||||||
void scheme_resume_one_place(Scheme_Place *p);
|
|
||||||
|
|
||||||
#endif /* __mzscheme_private__ */
|
#endif /* __mzscheme_private__ */
|
||||||
|
|
|
@ -156,6 +156,7 @@ THREAD_LOCAL_DECL(static int buffer_init_size);
|
||||||
THREAD_LOCAL_DECL(Scheme_Thread *scheme_current_thread = NULL);
|
THREAD_LOCAL_DECL(Scheme_Thread *scheme_current_thread = NULL);
|
||||||
THREAD_LOCAL_DECL(Scheme_Thread *scheme_main_thread = NULL);
|
THREAD_LOCAL_DECL(Scheme_Thread *scheme_main_thread = NULL);
|
||||||
THREAD_LOCAL_DECL(Scheme_Thread *scheme_first_thread = NULL);
|
THREAD_LOCAL_DECL(Scheme_Thread *scheme_first_thread = NULL);
|
||||||
|
THREAD_LOCAL_DECL(static Scheme_Thread *gc_prep_thread_chain = NULL);
|
||||||
|
|
||||||
XFORM_NONGCING Scheme_Thread *scheme_get_current_thread() { return scheme_current_thread; }
|
XFORM_NONGCING Scheme_Thread *scheme_get_current_thread() { return scheme_current_thread; }
|
||||||
XFORM_NONGCING intptr_t scheme_get_multiple_count() { return scheme_current_thread->ku.multiple.count; }
|
XFORM_NONGCING intptr_t scheme_get_multiple_count() { return scheme_current_thread->ku.multiple.count; }
|
||||||
|
@ -292,10 +293,16 @@ typedef struct {
|
||||||
# define MALLOC_MREF() (Scheme_Custodian_Reference *)scheme_make_late_weak_box(NULL)
|
# define MALLOC_MREF() (Scheme_Custodian_Reference *)scheme_make_late_weak_box(NULL)
|
||||||
# define CUSTODIAN_FAM(x) ((Scheme_Custodian_Weak_Box *)x)->val
|
# define CUSTODIAN_FAM(x) ((Scheme_Custodian_Weak_Box *)x)->val
|
||||||
# define xCUSTODIAN_FAM(x) SCHEME_BOX_VAL(x)
|
# define xCUSTODIAN_FAM(x) SCHEME_BOX_VAL(x)
|
||||||
|
# define SET_MREF_POSITION(mref, i) (((Scheme_Custodian_Weak_Box *)mref)->hash_key = (i & 0xFFFF))
|
||||||
|
# define EXTRACT_MREF_START_POSITION(mref, c) (((Scheme_Custodian_Weak_Box *)mref)->hash_key | ((c) & ~0xFFFF))
|
||||||
|
# define EXTRACT_MREF_POSITION_DELTA(mref, c) 0x10000
|
||||||
#else
|
#else
|
||||||
# define MALLOC_MREF() MALLOC_ONE_WEAK(Scheme_Custodian_Reference)
|
# define MALLOC_MREF() MALLOC_ONE_WEAK(Scheme_Custodian_Reference)
|
||||||
# define CUSTODIAN_FAM(x) (*(x))
|
# define CUSTODIAN_FAM(x) (*(x))
|
||||||
# define xCUSTODIAN_FAM(x) (*(x))
|
# define xCUSTODIAN_FAM(x) (*(x))
|
||||||
|
# define SET_MREF_POSITION(mref, i) /* empty */
|
||||||
|
# define EXTRACT_MREF_START_POSITION(mref, c) ((c)-1)
|
||||||
|
# define EXTRACT_MREF_POSITION_DELTA(mref, c) 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct Proc_Global_Rec {
|
typedef struct Proc_Global_Rec {
|
||||||
|
@ -891,7 +898,7 @@ static void add_managed_box(Scheme_Custodian *m,
|
||||||
Scheme_Object **box, Scheme_Custodian_Reference *mref,
|
Scheme_Object **box, Scheme_Custodian_Reference *mref,
|
||||||
Scheme_Close_Custodian_Client *f, void *data)
|
Scheme_Close_Custodian_Client *f, void *data)
|
||||||
{
|
{
|
||||||
int i;
|
int i, saw = 0;
|
||||||
|
|
||||||
for (i = m->count; i--; ) {
|
for (i = m->count; i--; ) {
|
||||||
if (!m->boxes[i]) {
|
if (!m->boxes[i]) {
|
||||||
|
@ -899,11 +906,16 @@ static void add_managed_box(Scheme_Custodian *m,
|
||||||
m->closers[i] = f;
|
m->closers[i] = f;
|
||||||
m->data[i] = data;
|
m->data[i] = data;
|
||||||
m->mrefs[i] = mref;
|
m->mrefs[i] = mref;
|
||||||
|
SET_MREF_POSITION(mref, i);
|
||||||
|
|
||||||
m->elems++;
|
m->elems++;
|
||||||
adjust_limit_table(m);
|
adjust_limit_table(m);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
saw++;
|
||||||
|
if (i + saw == m->elems)
|
||||||
|
break; /* no empty spaces left */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,6 +925,7 @@ static void add_managed_box(Scheme_Custodian *m,
|
||||||
m->closers[m->count] = f;
|
m->closers[m->count] = f;
|
||||||
m->data[m->count] = data;
|
m->data[m->count] = data;
|
||||||
m->mrefs[m->count] = mref;
|
m->mrefs[m->count] = mref;
|
||||||
|
SET_MREF_POSITION(mref, m->count);
|
||||||
|
|
||||||
m->elems++;
|
m->elems++;
|
||||||
adjust_limit_table(m);
|
adjust_limit_table(m);
|
||||||
|
@ -924,7 +937,7 @@ static void remove_managed(Scheme_Custodian_Reference *mr, Scheme_Object *o,
|
||||||
Scheme_Close_Custodian_Client **old_f, void **old_data)
|
Scheme_Close_Custodian_Client **old_f, void **old_data)
|
||||||
{
|
{
|
||||||
Scheme_Custodian *m;
|
Scheme_Custodian *m;
|
||||||
int i;
|
int i, delta;
|
||||||
|
|
||||||
if (!mr)
|
if (!mr)
|
||||||
return;
|
return;
|
||||||
|
@ -932,21 +945,27 @@ static void remove_managed(Scheme_Custodian_Reference *mr, Scheme_Object *o,
|
||||||
if (!m)
|
if (!m)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = m->count; i--; ) {
|
i = EXTRACT_MREF_START_POSITION(mr, m->count);
|
||||||
if (m->boxes[i] && SAME_OBJ((xCUSTODIAN_FAM(m->boxes[i])), o)) {
|
delta = EXTRACT_MREF_POSITION_DELTA(mr, m->count);
|
||||||
xCUSTODIAN_FAM(m->boxes[i]) = 0;
|
|
||||||
m->boxes[i] = NULL;
|
while (i >= 0) {
|
||||||
CUSTODIAN_FAM(m->mrefs[i]) = 0;
|
if (i < m->count) {
|
||||||
m->mrefs[i] = NULL;
|
if (m->boxes[i] && SAME_OBJ((xCUSTODIAN_FAM(m->boxes[i])), o)) {
|
||||||
if (old_f)
|
xCUSTODIAN_FAM(m->boxes[i]) = 0;
|
||||||
*old_f = m->closers[i];
|
m->boxes[i] = NULL;
|
||||||
if (old_data)
|
CUSTODIAN_FAM(m->mrefs[i]) = 0;
|
||||||
*old_data = m->data[i];
|
m->mrefs[i] = NULL;
|
||||||
m->data[i] = NULL;
|
if (old_f)
|
||||||
--m->elems;
|
*old_f = m->closers[i];
|
||||||
adjust_limit_table(m);
|
if (old_data)
|
||||||
break;
|
*old_data = m->data[i];
|
||||||
|
m->data[i] = NULL;
|
||||||
|
--m->elems;
|
||||||
|
adjust_limit_table(m);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
i -= delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (m->count && !m->boxes[m->count - 1]) {
|
while (m->count && !m->boxes[m->count - 1]) {
|
||||||
|
@ -1265,11 +1284,12 @@ Scheme_Thread *scheme_do_close_managed(Scheme_Custodian *m, Scheme_Exit_Closer_F
|
||||||
CUSTODIAN_FAM(m->mrefs[i]) = NULL;
|
CUSTODIAN_FAM(m->mrefs[i]) = NULL;
|
||||||
|
|
||||||
/* Set m->count to i in case a GC happens while
|
/* Set m->count to i in case a GC happens while
|
||||||
the closer is running. If there's a GC, then
|
the closer is running. */
|
||||||
for_each_managed will be called. */
|
|
||||||
m->count = i;
|
m->count = i;
|
||||||
|
|
||||||
if (is_thread && !the_thread) {
|
if (!o) {
|
||||||
|
/* weak link disappeared */
|
||||||
|
} else if (is_thread && !the_thread) {
|
||||||
/* Thread is already collected, so skip */
|
/* Thread is already collected, so skip */
|
||||||
} else if (cf) {
|
} else if (cf) {
|
||||||
cf(o, f, data);
|
cf(o, f, data);
|
||||||
|
@ -1357,53 +1377,6 @@ Scheme_Thread *scheme_do_close_managed(Scheme_Custodian *m, Scheme_Exit_Closer_F
|
||||||
return kill_self;
|
return kill_self;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*Scheme_For_Each_Func)(Scheme_Object *);
|
|
||||||
|
|
||||||
static void for_each_managed(Scheme_Type type, Scheme_For_Each_Func cf)
|
|
||||||
XFORM_SKIP_PROC
|
|
||||||
/* This function must not allocate. */
|
|
||||||
{
|
|
||||||
Scheme_Custodian *m;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (SAME_TYPE(type, scheme_thread_type))
|
|
||||||
type = scheme_thread_hop_type;
|
|
||||||
|
|
||||||
/* back to front so children are first: */
|
|
||||||
m = last_custodian;
|
|
||||||
|
|
||||||
while (m) {
|
|
||||||
for (i = m->count; i--; ) {
|
|
||||||
if (m->boxes[i]) {
|
|
||||||
Scheme_Object *o;
|
|
||||||
|
|
||||||
o = xCUSTODIAN_FAM(m->boxes[i]);
|
|
||||||
|
|
||||||
if (SAME_TYPE(SCHEME_TYPE(o), type)) {
|
|
||||||
if (SAME_TYPE(type, scheme_thread_hop_type)) {
|
|
||||||
/* We've added an indirection and made it weak. See mr_hop note above. */
|
|
||||||
Scheme_Thread *t;
|
|
||||||
t = (Scheme_Thread *)WEAKIFIED(((Scheme_Thread_Custodian_Hop *)o)->p);
|
|
||||||
if (!t) {
|
|
||||||
/* The thread is already collected */
|
|
||||||
continue;
|
|
||||||
} else if (SAME_OBJ(t->mref, m->mrefs[i]))
|
|
||||||
o = (Scheme_Object *)t;
|
|
||||||
else {
|
|
||||||
/* The main custodian for this thread is someone else */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cf(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m = CUSTODIAN_FAM(m->global_prev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void do_close_managed(Scheme_Custodian *m)
|
static void do_close_managed(Scheme_Custodian *m)
|
||||||
/* The trick is that we may need to kill the thread
|
/* The trick is that we may need to kill the thread
|
||||||
that is running us. If so, delay it to the very
|
that is running us. If so, delay it to the very
|
||||||
|
@ -1483,30 +1456,6 @@ static Scheme_Object *extract_thread(Scheme_Object *o)
|
||||||
return (Scheme_Object *)WEAKIFIED(((Scheme_Thread_Custodian_Hop *)o)->p);
|
return (Scheme_Object *)WEAKIFIED(((Scheme_Thread_Custodian_Hop *)o)->p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pause_place(Scheme_Object *o)
|
|
||||||
{
|
|
||||||
#ifdef MZ_USE_PLACES
|
|
||||||
scheme_pause_one_place((Scheme_Place *)o);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void scheme_pause_all_places()
|
|
||||||
{
|
|
||||||
for_each_managed(scheme_place_type, pause_place);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resume_place(Scheme_Object *o)
|
|
||||||
{
|
|
||||||
#ifdef MZ_USE_PLACES
|
|
||||||
scheme_resume_one_place((Scheme_Place *)o);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void scheme_resume_all_places()
|
|
||||||
{
|
|
||||||
for_each_managed(scheme_place_type, resume_place);
|
|
||||||
}
|
|
||||||
|
|
||||||
void scheme_init_custodian_extractors()
|
void scheme_init_custodian_extractors()
|
||||||
{
|
{
|
||||||
if (!extractors) {
|
if (!extractors) {
|
||||||
|
@ -2053,6 +2002,9 @@ static Scheme_Thread *make_thread(Scheme_Config *config,
|
||||||
process->prev = NULL;
|
process->prev = NULL;
|
||||||
process->next = NULL;
|
process->next = NULL;
|
||||||
|
|
||||||
|
gc_prep_thread_chain = process;
|
||||||
|
scheme_current_thread->gc_prep_chain = process;
|
||||||
|
|
||||||
process->suspend_break = 1; /* until start-up finished */
|
process->suspend_break = 1; /* until start-up finished */
|
||||||
|
|
||||||
process->error_buf = NULL;
|
process->error_buf = NULL;
|
||||||
|
@ -2444,7 +2396,6 @@ static void do_swap_thread()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (!swap_no_setjmp && SETJMP(scheme_current_thread)) {
|
if (!swap_no_setjmp && SETJMP(scheme_current_thread)) {
|
||||||
/* We're back! */
|
/* We're back! */
|
||||||
/* See also initial swap in in start_child() */
|
/* See also initial swap in in start_child() */
|
||||||
|
@ -2537,6 +2488,10 @@ static void do_swap_thread()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scheme_current_thread = new_thread;
|
scheme_current_thread = new_thread;
|
||||||
|
if (!new_thread->gc_prep_chain) {
|
||||||
|
new_thread->gc_prep_chain = gc_prep_thread_chain;
|
||||||
|
gc_prep_thread_chain = new_thread;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fixup current pointers in thread sets */
|
/* Fixup current pointers in thread sets */
|
||||||
if (!scheme_current_thread->return_marks_to) {
|
if (!scheme_current_thread->return_marks_to) {
|
||||||
|
@ -3240,6 +3195,9 @@ Scheme_Object *scheme_call_as_nested_thread(int argc, Scheme_Object *argv[], voi
|
||||||
scheme_first_thread->prev = np;
|
scheme_first_thread->prev = np;
|
||||||
scheme_first_thread = np;
|
scheme_first_thread = np;
|
||||||
|
|
||||||
|
np->gc_prep_chain = gc_prep_thread_chain;
|
||||||
|
gc_prep_thread_chain = np;
|
||||||
|
|
||||||
np->t_set_parent = p->t_set_parent;
|
np->t_set_parent = p->t_set_parent;
|
||||||
schedule_in_set((Scheme_Object *)np, np->t_set_parent);
|
schedule_in_set((Scheme_Object *)np, np->t_set_parent);
|
||||||
|
|
||||||
|
@ -8095,6 +8053,8 @@ static void prepare_thread_for_GC(Scheme_Object *t)
|
||||||
{
|
{
|
||||||
Scheme_Thread *p = (Scheme_Thread *)t;
|
Scheme_Thread *p = (Scheme_Thread *)t;
|
||||||
|
|
||||||
|
if (!p->running) return;
|
||||||
|
|
||||||
/* zero ununsed part of env stack in each thread */
|
/* zero ununsed part of env stack in each thread */
|
||||||
|
|
||||||
if (!p->nestee) {
|
if (!p->nestee) {
|
||||||
|
@ -8267,7 +8227,20 @@ static void get_ready_for_GC()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for_each_managed(scheme_thread_type, prepare_thread_for_GC);
|
/* Prepare each thread that has run: */
|
||||||
|
if (gc_prep_thread_chain) {
|
||||||
|
Scheme_Thread *p, *next;
|
||||||
|
p = gc_prep_thread_chain;
|
||||||
|
while (p != p->gc_prep_chain) {
|
||||||
|
prepare_thread_for_GC((Scheme_Object *)p);
|
||||||
|
next = p->gc_prep_chain;
|
||||||
|
p->gc_prep_chain = NULL;
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
|
prepare_thread_for_GC((Scheme_Object *)p);
|
||||||
|
p->gc_prep_chain = NULL;
|
||||||
|
gc_prep_thread_chain = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MZ_PRECISE_GC
|
#ifdef MZ_PRECISE_GC
|
||||||
scheme_flush_stack_copy_cache();
|
scheme_flush_stack_copy_cache();
|
||||||
|
@ -8318,6 +8291,9 @@ static void done_with_GC()
|
||||||
end_this_gc_real_time = scheme_get_inexact_milliseconds();
|
end_this_gc_real_time = scheme_get_inexact_milliseconds();
|
||||||
scheme_total_gc_time += (end_this_gc_time - start_this_gc_time);
|
scheme_total_gc_time += (end_this_gc_time - start_this_gc_time);
|
||||||
|
|
||||||
|
gc_prep_thread_chain = scheme_current_thread;
|
||||||
|
scheme_current_thread->gc_prep_chain = scheme_current_thread;
|
||||||
|
|
||||||
run_gc_callbacks(0);
|
run_gc_callbacks(0);
|
||||||
|
|
||||||
#ifdef MZ_USE_FUTURES
|
#ifdef MZ_USE_FUTURES
|
||||||
|
|
Loading…
Reference in New Issue
Block a user