@@ -63,18 +63,10 @@ JL_DEFINE_MUTEX(finalizers)
63
63
* the safepoint. This is fine since the thread won't be executing any GC
64
64
* critical region during that time).
65
65
*
66
- * When the GC needs to run the finalizers, it cannot keep the safepoint
67
- * activate since the code in the finalizer might trigger it and falls into
68
- * a dead loop. It also (not required since the lock is recursive) release the
69
- * `finalizers` lock so that other threads can update the finalizers list at
70
- * the same time. Since the safe point is deactivated in this phase and other
71
- * threads might have entered managed state from unmanaged state, when the
72
- * finalizers finish running, the GC thread wait for other threads to enter a
73
- * safe state again before continuing the GC. It is not possible for other
74
- * threads to enter the GC since `jl_gc_running` is still `1` in this phase.
75
- * In the future, it might be better to delay this after the GC is finished so
76
- * that we can wake up other threads and do more useful works as the finalizers
77
- * runs.
66
+ * The finalizers are run after the GC finishes in normal mode (the `gc_state`
67
+ * when `jl_gc_collect` is called) with `jl_in_finalizer = 1`. (TODO:) When we
68
+ * have proper support of GC transition in codegen, we should execute the
69
+ * finalizers in unmanaged (GC safe) mode.
78
70
*/
79
71
80
72
// manipulating mark bits
@@ -363,11 +355,6 @@ JL_DLLEXPORT volatile size_t *jl_gc_signal_page = NULL;
363
355
364
356
static void jl_wait_for_gc (void )
365
357
{
366
- assert (!jl_in_gc && "Safepoint triggered in GC" );
367
- // In case assertion is off. Make safepoint in GC a segfault instead
368
- // of a infinite loop.
369
- if (jl_in_gc )
370
- return ;
371
358
while (jl_gc_running ) {
372
359
jl_cpu_pause (); // yield?
373
360
}
@@ -550,10 +537,10 @@ void jl_gc_inhibit_finalizers(int state)
550
537
{
551
538
// NOTE: currently only called with the codegen lock held, but might need
552
539
// more synchronization in the future
553
- if (jl_gc_finalizers_inhibited && !state && !jl_in_gc ) {
554
- jl_in_gc = 1 ;
540
+ if (jl_gc_finalizers_inhibited && !state && !jl_in_finalizer ) {
541
+ jl_in_finalizer = 1 ;
555
542
run_finalizers ();
556
- jl_in_gc = 0 ;
543
+ jl_in_finalizer = 0 ;
557
544
}
558
545
jl_gc_finalizers_inhibited = state ;
559
546
}
@@ -2312,7 +2299,7 @@ static void _jl_gc_collect(int full, char *stack_hi)
2312
2299
int64_t estimate_freed = -1 ;
2313
2300
2314
2301
#if defined(GC_TIME ) || defined(GC_FINAL_STATS )
2315
- uint64_t post_time = 0 , finalize_time = 0 ;
2302
+ uint64_t post_time = 0 ;
2316
2303
#endif
2317
2304
if (mark_sp == 0 || sweeping ) {
2318
2305
#if defined(GC_TIME ) || defined(GC_FINAL_STATS )
@@ -2424,28 +2411,16 @@ static void _jl_gc_collect(int full, char *stack_hi)
2424
2411
allocd_bytes_since_sweep = 0 ;
2425
2412
jl_gc_total_freed_bytes += freed_bytes ;
2426
2413
freed_bytes = 0 ;
2427
-
2428
- #if defined(GC_FINAL_STATS ) || defined(GC_TIME )
2429
- finalize_time = jl_hrtime ();
2430
- #endif
2431
- if (!jl_gc_finalizers_inhibited && to_finalize .len ) {
2432
- jl_gc_signal_end ();
2433
- run_finalizers ();
2434
- jl_gc_signal_begin ();
2435
- }
2436
- #if defined(GC_FINAL_STATS ) || defined(GC_TIME )
2437
- finalize_time = jl_hrtime () - finalize_time ;
2438
- #endif
2439
2414
}
2440
2415
#if defined(GC_FINAL_STATS ) || defined(GC_TIME )
2441
2416
uint64_t sweep_pause = jl_hrtime () - sweep_t0 ;
2442
2417
#endif
2443
2418
#ifdef GC_FINAL_STATS
2444
- total_sweep_time += sweep_pause - finalize_time - post_time ;
2445
- total_fin_time += finalize_time + post_time ;
2419
+ total_sweep_time += sweep_pause - post_time ;
2420
+ total_fin_time += + post_time ;
2446
2421
#endif
2447
2422
#ifdef GC_TIME
2448
- jl_printf (JL_STDOUT , "GC sweep pause %.2f ms live %ld kB (freed %d kB EST %d kB [error %d] = %d%% of allocd %d kB b/r %ld/%ld) (%.2f ms in post_mark, %.2f ms in %d fin ) (marked in %d inc) mask %d | next in %d kB\n" , NS2MS (sweep_pause ), live_bytes /1024 , SAVE2 /1024 , estimate_freed /1024 , (SAVE2 - estimate_freed ), pct , SAVE3 /1024 , bonus /1024 , SAVE /1024 , NS2MS (post_time ), NS2MS ( finalize_time ), n_finalized , inc_count , sweep_mask , - allocd_bytes /1024 );
2423
+ jl_printf (JL_STDOUT , "GC sweep pause %.2f ms live %ld kB (freed %d kB EST %d kB [error %d] = %d%% of allocd %d kB b/r %ld/%ld) (%.2f ms in post_mark) (marked in %d inc) mask %d | next in %d kB\n" , NS2MS (sweep_pause ), live_bytes /1024 , SAVE2 /1024 , estimate_freed /1024 , (SAVE2 - estimate_freed ), pct , SAVE3 /1024 , bonus /1024 , SAVE /1024 , NS2MS (post_time ), inc_count , sweep_mask , - allocd_bytes /1024 );
2449
2424
#endif
2450
2425
}
2451
2426
n_pause ++ ;
@@ -2469,7 +2444,7 @@ static void _jl_gc_collect(int full, char *stack_hi)
2469
2444
2470
2445
JL_DLLEXPORT void jl_gc_collect (int full )
2471
2446
{
2472
- if (jl_gc_disable_counter || jl_in_gc )
2447
+ if (jl_gc_disable_counter )
2473
2448
return ;
2474
2449
char * stack_hi = (char * )gc_get_stack_ptr ();
2475
2450
gc_debug_print ();
@@ -2487,26 +2462,31 @@ JL_DLLEXPORT void jl_gc_collect(int full)
2487
2462
jl_wait_for_gc ();
2488
2463
jl_gc_state_set (old_state , 1 );
2489
2464
#else
2490
- // For single thread, jl_in_gc is always true when jl_gc_running is
2491
- // true so this should never happen.
2465
+ // For single thread, GC should not call itself (in finalizers) before
2466
+ // setting jl_gc_running to false so this should never happen.
2492
2467
assert (0 && "GC synchronization failure" );
2493
2468
#endif
2494
2469
return ;
2495
2470
}
2496
2471
jl_gc_signal_begin ();
2497
2472
2498
- jl_in_gc = 1 ;
2499
2473
if (!jl_gc_disable_counter )
2500
2474
_jl_gc_collect (full , stack_hi );
2501
- jl_in_gc = 0 ;
2502
2475
2503
2476
// Need to reset the page protection before resetting the flag since
2504
- // the thread will trigger a segfault immediately after returning from the
2505
- // signal handler.
2477
+ // the thread will trigger a segfault immediately after returning from
2478
+ // the signal handler.
2506
2479
jl_gc_signal_end ();
2507
2480
jl_gc_running = 0 ;
2508
2481
JL_SIGATOMIC_END ();
2509
2482
jl_gc_state_set (old_state , 1 );
2483
+
2484
+ if (!jl_gc_finalizers_inhibited ) {
2485
+ int8_t was_in_finalizer = jl_in_finalizer ;
2486
+ jl_in_finalizer = 1 ;
2487
+ run_finalizers ();
2488
+ jl_in_finalizer = was_in_finalizer ;
2489
+ }
2510
2490
}
2511
2491
2512
2492
// allocator entry points
0 commit comments