@@ -1537,6 +1537,44 @@ void tb_flush(CPUState *cpu)
1537
1537
}
1538
1538
}
1539
1539
1540
+ /*
1541
+ * If we call tb_flush, from inside cpu_exec, then it will queue do_tb_flush to
1542
+ * run asyncronously. Since we wish to do this when we start the forkserver to
1543
+ * flush any translated blocks which may have been translated before the
1544
+ * configuration from environment variables has been parsed, this will cause the
1545
+ * flush to be deferred and instead performed after the fork server is running
1546
+ * resulting in the flush occurring repeatedly rather than just the once, with
1547
+ * the obvious resulting performance overhead.
1548
+ *
1549
+ * However, we know that the fork server should be initialized when the target
1550
+ * application has only a single thread (since the fork syscall will only clone
1551
+ * the calling thread into the child process). Therefore, we don't need any
1552
+ * synchronization with respect to any other VCPUs and can therefore perform the
1553
+ * flush synchronously instead.
1554
+ */
1555
+ void tb_flush_sync (void )
1556
+ {
1557
+ CPUState * cpu = NULL ;
1558
+ size_t num_cpus = 0 ;
1559
+
1560
+ if (!tcg_enabled ()) {
1561
+ return ;
1562
+ }
1563
+
1564
+ CPU_FOREACH (cpu ) {
1565
+ num_cpus ++ ;
1566
+ }
1567
+
1568
+ if (num_cpus != 1 ) {
1569
+ fprintf (stderr , "Warning: More than one VCPU when attempting to flush "
1570
+ "translation block cache. Skipping since we can't do it synchronously." );
1571
+ return ;
1572
+ }
1573
+
1574
+ unsigned tb_flush_count = qatomic_mb_read (& tb_ctx .tb_flush_count );
1575
+ do_tb_flush (cpu , RUN_ON_CPU_HOST_INT (tb_flush_count ));
1576
+ }
1577
+
1540
1578
/*
1541
1579
* Formerly ifdef DEBUG_TB_CHECK. These debug functions are user-mode-only,
1542
1580
* so in order to prevent bit rot we compile them unconditionally in user-mode,
0 commit comments