runtime: do a minor GC for cancelled threads

The main idea is to avoid a longjmp and return to the destructor
for the cancelled thread. So, adjust GC and gc_minor to allow
for a NULL continuation.
This commit is contained in:
Yorick Hardy 2025-01-19 22:45:13 +02:00
parent c0c49c786d
commit 73952a8638

View file

@ -6416,6 +6416,7 @@ int gc_minor(void *data, object low_limit, object high_limit, closure cont,
exit(1); exit(1);
} }
if (cont != NULL) {
gc_move2heap(cont); gc_move2heap(cont);
((gc_thread_data *) data)->gc_cont = cont; ((gc_thread_data *) data)->gc_cont = cont;
((gc_thread_data *) data)->gc_num_args = num_args; ((gc_thread_data *) data)->gc_num_args = num_args;
@ -6424,6 +6425,7 @@ int gc_minor(void *data, object low_limit, object high_limit, closure cont,
gc_move2heap(args[i]); gc_move2heap(args[i]);
((gc_thread_data *) data)->gc_args[i] = args[i]; ((gc_thread_data *) data)->gc_args[i] = args[i];
} }
}
// Transport exception stack // Transport exception stack
gc_move2heap(((gc_thread_data *) data)->exception_handler_stack); gc_move2heap(((gc_thread_data *) data)->exception_handler_stack);
@ -6561,8 +6563,13 @@ void GC(void *data, closure cont, object * args, int num_args)
#ifdef CYC_HIGH_RES_TIMERS #ifdef CYC_HIGH_RES_TIMERS
hrt_log_delta("minor gc", tstamp); hrt_log_delta("minor gc", tstamp);
#endif #endif
// if this thread has a continuation (i.e. it is not cancelled)
// then we can continue after the minor GC, otherwise we return
// to the destructor which initiated the minor GC.
if (cont != NULL) {
// Let it all go, Neo... // Let it all go, Neo...
longjmp(*(((gc_thread_data *) data)->jmp_start), 1); longjmp(*(((gc_thread_data *) data)->jmp_start), 1);
}
} }
/** /**
@ -7198,8 +7205,9 @@ void Cyc_exit_thread(void *data, object _, int argc, object * args)
*/ */
static void Cyc_cancel_thread(gc_thread_data * thd) static void Cyc_cancel_thread(gc_thread_data * thd)
{ {
// don't do a minor GC, the thread is terminated without // do a minor GC without a continuation, so that we return
// returning any values. // here without performing a longjmp
GC(thd, (closure)NULL, (object *)NULL, 0);
if (gc_is_mutator_active(thd)) { if (gc_is_mutator_active(thd)) {
gc_remove_mutator(thd); gc_remove_mutator(thd);
} }