fix `nack-guard-evt'

The generated NACK shouldn't become ready when the thread where
the NACK is created terminates.
This commit is contained in:
Matthew Flatt 2013-04-22 16:24:25 -06:00
parent 27b7e7dc7e
commit 74fb6feb45
7 changed files with 52 additions and 6 deletions

View File

@ -478,6 +478,20 @@
(test 10 channel-get ch)
(test (void) sync/timeout 0 n)))
(let ()
(define ok? 'not-ready)
(thread-wait
(thread
(lambda ()
(sync (nack-guard-evt
(lambda (nack)
(thread (lambda ()
(sync nack)
(set! ok? #f)))
(sync (system-idle-evt))
always-evt))))))
(sync (system-idle-evt))
(test 'not-ready values ok?))
;; ----------------------------------------
;; Poll waitables

View File

@ -1116,6 +1116,7 @@ typedef struct Scheme_Thread {
Scheme_Object *resumed_box; /* contains pointer to thread when it's resumed */
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 *sync_box; /* semaphore used for NACK events */
struct Scheme_Thread *gc_prep_chain;

View File

@ -1872,6 +1872,7 @@ static int thread_val_MARK(void *p, struct NewGC *gc) {
gcMARK2(pr->resumed_box, gc);
gcMARK2(pr->dead_box, gc);
gcMARK2(pr->running_box, gc);
gcMARK2(pr->sync_box, gc);
gcMARK2(pr->mbox_first, gc);
gcMARK2(pr->mbox_last, gc);
@ -1986,6 +1987,7 @@ static int thread_val_FIXUP(void *p, struct NewGC *gc) {
gcFIXUP2(pr->resumed_box, gc);
gcFIXUP2(pr->dead_box, gc);
gcFIXUP2(pr->running_box, gc);
gcFIXUP2(pr->sync_box, gc);
gcFIXUP2(pr->mbox_first, gc);
gcFIXUP2(pr->mbox_last, gc);

View File

@ -784,6 +784,7 @@ thread_val {
gcMARK2(pr->resumed_box, gc);
gcMARK2(pr->dead_box, gc);
gcMARK2(pr->running_box, gc);
gcMARK2(pr->sync_box, gc);
gcMARK2(pr->mbox_first, gc);
gcMARK2(pr->mbox_last, gc);

View File

@ -636,6 +636,8 @@ void *scheme_win32_get_break_semaphore(void *th);
Scheme_Object *scheme_get_thread_dead(Scheme_Thread *p);
Scheme_Object *scheme_get_thread_suspend(Scheme_Thread *p);
Scheme_Object *scheme_get_thread_sync(Scheme_Thread *p);
void scheme_clear_thread_sync(Scheme_Thread *p);
void scheme_zero_unneeded_rands(Scheme_Thread *p);

View File

@ -3601,7 +3601,7 @@ static int nack_guard_evt_is_ready(Scheme_Object *o, Scheme_Schedule_Info *sinfo
nack = scheme_alloc_object();
nack->type = scheme_nack_evt_type;
SCHEME_PTR1_VAL(nack) = sema;
result = scheme_get_thread_dead(scheme_current_thread);
result = scheme_get_thread_sync(scheme_current_thread);
SCHEME_PTR2_VAL(nack) = result;
a[0] = nack;

View File

@ -2630,6 +2630,10 @@ static void thread_is_dead(Scheme_Thread *r)
o = SCHEME_PTR_VAL(r->dead_box);
scheme_post_sema_all(o);
}
if (r->sync_box) {
scheme_post_sema_all(r->sync_box);
r->sync_box = NULL;
}
if (r->running_box) {
SCHEME_PTR_VAL(r->running_box) = NULL;
r->running_box = NULL;
@ -5854,6 +5858,23 @@ static int dead_ready(Scheme_Object *o, Scheme_Schedule_Info *sinfo)
return 0;
}
Scheme_Object *scheme_get_thread_sync(Scheme_Thread *p)
{
if (!p->sync_box) {
Scheme_Object *sema;
sema = scheme_make_sema(0);
p->sync_box = sema;
}
return p->sync_box;
}
void scheme_clear_thread_sync(Scheme_Thread *p)
{
if (p->sync_box)
p->sync_box = NULL;
}
/*========================================================================*/
/* syncing */
/*========================================================================*/
@ -6483,6 +6504,9 @@ void scheme_post_syncing_nacks(Syncing *syncing)
int i, c;
Scheme_Object *l;
if (syncing->thread && syncing->thread->sync_box)
syncing->thread->sync_box = NULL;
if (syncing->set) {
c = syncing->set->argc;
@ -6504,11 +6528,14 @@ void scheme_post_syncing_nacks(Syncing *syncing)
}
}
static void escape_during_sync(Syncing *syncing) {
#ifdef MZ_PRECISE_GC
static void escape_during_sync(Syncing *syncing)
{
Scheme_Thread *p = syncing->thread;
#endif
syncing->thread = NULL;
if (p->sync_box)
scheme_post_sema_all(p->sync_box);
scheme_post_syncing_nacks(syncing);
#ifdef MZ_PRECISE_GC
@ -6516,7 +6543,6 @@ scheme_post_syncing_nacks(syncing);
GC_destroy_orphan_msg_memory(p->place_channel_msg_in_flight);
p->place_channel_msg_in_flight = NULL;
}
syncing->thread = NULL;
#endif
}