accomodate signal-handler calls from multiple threads
svn: r9225
This commit is contained in:
parent
2a17f76cec
commit
e4190d765f
|
@ -1655,6 +1655,7 @@ void wxDoEvents()
|
|||
c->main_cells,
|
||||
c->main_break_cell,
|
||||
NULL, 0);
|
||||
scheme_set_break_main_target(user_main_thread);
|
||||
cp = scheme_intern_symbol("mred");
|
||||
user_main_thread->name = cp;
|
||||
}
|
||||
|
@ -1778,7 +1779,7 @@ static void MrEdSleep(float secs, void *fds)
|
|||
#ifdef mred_BREAK_HANDLER
|
||||
static void user_break_hit(int ignore)
|
||||
{
|
||||
scheme_break_thread(user_main_thread);
|
||||
scheme_break_main_thread();
|
||||
scheme_signal_received();
|
||||
|
||||
# ifdef SIGSET_NEEDS_REINSTALL
|
||||
|
@ -2369,7 +2370,7 @@ void IOFrame::OnMenuCommand(long id)
|
|||
else if (id == 81)
|
||||
media->Paste();
|
||||
else if (id == 83)
|
||||
scheme_break_thread(user_main_thread);
|
||||
scheme_break_main_thread();
|
||||
else if (id == 77)
|
||||
if (OnClose())
|
||||
Show(FALSE);
|
||||
|
@ -2448,7 +2449,7 @@ static Bool RecordInput(void *m, wxEvent *event, void *data)
|
|||
|
||||
static Bool SendBreak(void *m, wxEvent *event, void *data)
|
||||
{
|
||||
scheme_break_thread(user_main_thread);
|
||||
scheme_break_main_thread();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ scheme_thread
|
|||
scheme_thread_w_details
|
||||
scheme_kill_thread
|
||||
scheme_break_thread
|
||||
scheme_break_main_thread
|
||||
scheme_set_break_main_target
|
||||
scheme_thread_block
|
||||
scheme_thread_block_enable_break
|
||||
scheme_swap_thread
|
||||
|
|
|
@ -26,6 +26,8 @@ scheme_thread
|
|||
scheme_thread_w_details
|
||||
scheme_kill_thread
|
||||
scheme_break_thread
|
||||
scheme_break_main_thread
|
||||
scheme_set_break_main_target
|
||||
scheme_thread_block
|
||||
scheme_thread_block_enable_break
|
||||
scheme_swap_thread
|
||||
|
|
|
@ -28,6 +28,8 @@ EXPORTS
|
|||
scheme_thread_w_details
|
||||
scheme_kill_thread
|
||||
scheme_break_thread
|
||||
scheme_break_main_thread
|
||||
scheme_set_break_main_target
|
||||
scheme_thread_block
|
||||
scheme_thread_block_enable_break
|
||||
scheme_swap_thread
|
||||
|
|
|
@ -28,6 +28,8 @@ EXPORTS
|
|||
scheme_thread_w_details
|
||||
scheme_kill_thread
|
||||
scheme_break_thread
|
||||
scheme_break_main_thread
|
||||
scheme_set_break_main_target
|
||||
scheme_thread_block
|
||||
scheme_thread_block_enable_break
|
||||
scheme_swap_thread
|
||||
|
|
|
@ -169,7 +169,7 @@ extern Scheme_Object *scheme_initialize(Scheme_Env *env);
|
|||
|
||||
static void user_break_hit(int ignore)
|
||||
{
|
||||
scheme_break_thread(NULL);
|
||||
scheme_break_main_thread();
|
||||
scheme_signal_received();
|
||||
|
||||
# ifdef SIGSET_NEEDS_REINSTALL
|
||||
|
|
|
@ -6458,38 +6458,7 @@ void scheme_block_child_signals(int block)
|
|||
|
||||
static void child_done(int ingored)
|
||||
{
|
||||
pid_t result;
|
||||
int status;
|
||||
System_Child *sc, *prev;
|
||||
|
||||
do {
|
||||
do {
|
||||
result = WAITANY(&status);
|
||||
} while ((result == -1) && (errno == EINTR));
|
||||
|
||||
if (result > 0) {
|
||||
if (WIFEXITED(status))
|
||||
status = WEXITSTATUS(status);
|
||||
else
|
||||
status = MZ_FAILURE_STATUS;
|
||||
|
||||
prev = NULL;
|
||||
for (sc = scheme_system_children; sc; prev = sc, sc = sc->next) {
|
||||
if (sc->id == result) {
|
||||
sc->done = 1;
|
||||
sc->status = status;
|
||||
|
||||
if (prev) {
|
||||
prev->next = sc->next;
|
||||
} else
|
||||
scheme_system_children = sc->next;
|
||||
|
||||
scheme_signal_received();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (result > 0);
|
||||
scheme_signal_received();
|
||||
|
||||
# ifdef SIGSET_NEEDS_REINSTALL
|
||||
MZ_SIGSET(SIGCHLD, child_done);
|
||||
|
@ -6514,6 +6483,43 @@ static void init_sigchld(void)
|
|||
}
|
||||
}
|
||||
|
||||
void scheme_check_child_done()
|
||||
{
|
||||
pid_t result;
|
||||
int status;
|
||||
System_Child *sc, *prev;
|
||||
|
||||
if (scheme_system_children) {
|
||||
do {
|
||||
do {
|
||||
result = WAITANY(&status);
|
||||
} while ((result == -1) && (errno == EINTR));
|
||||
|
||||
if (result > 0) {
|
||||
if (WIFEXITED(status))
|
||||
status = WEXITSTATUS(status);
|
||||
else
|
||||
status = MZ_FAILURE_STATUS;
|
||||
|
||||
prev = NULL;
|
||||
for (sc = scheme_system_children; sc; prev = sc, sc = sc->next) {
|
||||
if (sc->id == result) {
|
||||
sc->done = 1;
|
||||
sc->status = status;
|
||||
|
||||
if (prev) {
|
||||
prev->next = sc->next;
|
||||
} else
|
||||
scheme_system_children = sc->next;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (result > 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*========================================================================*/
|
||||
|
|
|
@ -92,6 +92,8 @@ MZ_EXTERN Scheme_Object *scheme_thread_w_details(Scheme_Object *thunk,
|
|||
int suspend_to_kill);
|
||||
MZ_EXTERN void scheme_kill_thread(Scheme_Thread *p);
|
||||
MZ_EXTERN void scheme_break_thread(Scheme_Thread *p);
|
||||
MZ_EXTERN void scheme_break_main_thread();
|
||||
MZ_EXTERN void scheme_set_break_main_target(Scheme_Thread *p);
|
||||
|
||||
MZ_EXTERN void scheme_thread_block(float sleep_time);
|
||||
MZ_EXTERN void scheme_thread_block_enable_break(float sleep_time, int enable);
|
||||
|
|
|
@ -74,6 +74,8 @@ Scheme_Object *(*scheme_thread_w_details)(Scheme_Object *thunk,
|
|||
int suspend_to_kill);
|
||||
void (*scheme_kill_thread)(Scheme_Thread *p);
|
||||
void (*scheme_break_thread)(Scheme_Thread *p);
|
||||
void (*scheme_break_main_thread)();
|
||||
void (*scheme_set_break_main_target)(Scheme_Thread *p);
|
||||
void (*scheme_thread_block)(float sleep_time);
|
||||
void (*scheme_thread_block_enable_break)(float sleep_time, int enable);
|
||||
void (*scheme_swap_thread)(Scheme_Thread *process);
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
scheme_extension_table->scheme_thread_w_details = scheme_thread_w_details;
|
||||
scheme_extension_table->scheme_kill_thread = scheme_kill_thread;
|
||||
scheme_extension_table->scheme_break_thread = scheme_break_thread;
|
||||
scheme_extension_table->scheme_break_main_thread = scheme_break_main_thread;
|
||||
scheme_extension_table->scheme_set_break_main_target = scheme_set_break_main_target;
|
||||
scheme_extension_table->scheme_thread_block = scheme_thread_block;
|
||||
scheme_extension_table->scheme_thread_block_enable_break = scheme_thread_block_enable_break;
|
||||
scheme_extension_table->scheme_swap_thread = scheme_swap_thread;
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#define scheme_thread_w_details (scheme_extension_table->scheme_thread_w_details)
|
||||
#define scheme_kill_thread (scheme_extension_table->scheme_kill_thread)
|
||||
#define scheme_break_thread (scheme_extension_table->scheme_break_thread)
|
||||
#define scheme_break_main_thread (scheme_extension_table->scheme_break_main_thread)
|
||||
#define scheme_set_break_main_target (scheme_extension_table->scheme_set_break_main_target)
|
||||
#define scheme_thread_block (scheme_extension_table->scheme_thread_block)
|
||||
#define scheme_thread_block_enable_break (scheme_extension_table->scheme_thread_block_enable_break)
|
||||
#define scheme_swap_thread (scheme_extension_table->scheme_swap_thread)
|
||||
|
|
|
@ -95,6 +95,10 @@ extern HANDLE scheme_break_semaphore;
|
|||
|
||||
#include "schfd.h"
|
||||
|
||||
#if defined(UNIX_PROCESSES)
|
||||
extern void scheme_check_child_done();
|
||||
#endif
|
||||
|
||||
#define DEFAULT_INIT_STACK_SIZE 1000
|
||||
#define MAX_INIT_STACK_SIZE 100000
|
||||
|
||||
|
@ -119,6 +123,8 @@ extern void scheme_gmp_tls_unload(long *s);
|
|||
extern void scheme_gmp_tls_snapshot(long *s, long *save);
|
||||
extern void scheme_gmp_tls_restore_snapshot(long *s, long *save, int do_free);
|
||||
|
||||
static void check_ready_break();
|
||||
|
||||
extern int scheme_num_read_syntax_objects;
|
||||
extern int scheme_hash_request_count;
|
||||
extern int scheme_hash_iteration_count;
|
||||
|
@ -210,7 +216,8 @@ extern MZ_DLLIMPORT void (*GC_collect_end_callback)(void);
|
|||
static void get_ready_for_GC(void);
|
||||
static void done_with_GC(void);
|
||||
|
||||
static short delay_breaks = 0, delayed_break_ready = 0;
|
||||
static volatile short delayed_break_ready = 0;
|
||||
static Scheme_Thread *main_break_target_thread;
|
||||
|
||||
void (*scheme_sleep)(float seconds, void *fds);
|
||||
void (*scheme_notify_multithread)(int on);
|
||||
|
@ -3216,6 +3223,8 @@ Scheme_Object *scheme_call_as_nested_thread(int argc, Scheme_Object *argv[], voi
|
|||
GC cleaning for this thread: */
|
||||
prepare_this_thread_for_GC(p);
|
||||
|
||||
check_ready_break();
|
||||
|
||||
np->nester = p;
|
||||
p->nestee = np;
|
||||
np->external_break = p->external_break;
|
||||
|
@ -3579,6 +3588,8 @@ void scheme_check_break_now(void)
|
|||
{
|
||||
Scheme_Thread *p = scheme_current_thread;
|
||||
|
||||
check_ready_break();
|
||||
|
||||
if (p->external_break && scheme_can_break(p)) {
|
||||
scheme_thread_block_w_thread(0.0, p);
|
||||
p->ran_some = 1;
|
||||
|
@ -3726,14 +3737,36 @@ static void exit_or_escape(Scheme_Thread *p)
|
|||
select_thread();
|
||||
}
|
||||
|
||||
void scheme_break_thread(Scheme_Thread *p)
|
||||
/* This function can be called from an interrupt handler. */
|
||||
void scheme_break_main_thread()
|
||||
/* This function can be called from an interrupt handler.
|
||||
On some platforms, it will even be called from multiple
|
||||
OS threads. In the case of multiple threads, there's a
|
||||
tiny chance that a single Ctl-C will trigger multiple
|
||||
break exceptions. */
|
||||
{
|
||||
if (delay_breaks) {
|
||||
delayed_break_ready = 1;
|
||||
return;
|
||||
}
|
||||
delayed_break_ready = 1;
|
||||
}
|
||||
|
||||
void scheme_set_break_main_target(Scheme_Thread *p)
|
||||
{
|
||||
if (!main_break_target_thread) {
|
||||
REGISTER_SO(main_break_target_thread);
|
||||
}
|
||||
main_break_target_thread = p;
|
||||
}
|
||||
|
||||
static void check_ready_break()
|
||||
{
|
||||
if (delayed_break_ready) {
|
||||
if (scheme_main_thread) {
|
||||
delayed_break_ready = 0;
|
||||
scheme_break_thread(main_break_target_thread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scheme_break_thread(Scheme_Thread *p)
|
||||
{
|
||||
if (!p) {
|
||||
p = scheme_main_thread;
|
||||
if (!p)
|
||||
|
@ -3801,6 +3834,8 @@ void scheme_thread_block(float sleep_time)
|
|||
|
||||
start_sleep_check:
|
||||
|
||||
check_ready_break();
|
||||
|
||||
if (!p->external_break && !p->next && scheme_check_for_break && scheme_check_for_break())
|
||||
p->external_break = 1;
|
||||
|
||||
|
@ -3818,6 +3853,10 @@ void scheme_thread_block(float sleep_time)
|
|||
/* Check scheduled_kills early and often. */
|
||||
check_scheduled_kills();
|
||||
|
||||
#if defined(UNIX_PROCESSES)
|
||||
scheme_check_child_done();
|
||||
#endif
|
||||
|
||||
if (!do_atomic && (sleep_end >= 0.0)) {
|
||||
double msecs = 0.0;
|
||||
|
||||
|
@ -4029,6 +4068,7 @@ void scheme_thread_block(float sleep_time)
|
|||
}
|
||||
|
||||
/* Check for external break again after swap or sleep */
|
||||
check_ready_break();
|
||||
if (p->external_break && !p->suspend_break && scheme_can_break(p)) {
|
||||
raise_break(p);
|
||||
}
|
||||
|
@ -7108,9 +7148,6 @@ static void get_ready_for_GC()
|
|||
#endif
|
||||
|
||||
did_gc_count++;
|
||||
|
||||
delayed_break_ready = 0;
|
||||
delay_breaks = 1;
|
||||
}
|
||||
|
||||
extern int GC_words_allocd;
|
||||
|
@ -7132,10 +7169,6 @@ static void done_with_GC()
|
|||
scheme_block_child_signals(0);
|
||||
#endif
|
||||
|
||||
delay_breaks = 0;
|
||||
if (delayed_break_ready)
|
||||
scheme_break_thread(NULL);
|
||||
|
||||
scheme_total_gc_time += (scheme_get_process_milliseconds() - start_this_gc_time);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user