|
@@ -214,30 +214,49 @@ CPUPluginState *qemu_plugin_create_vcpu_state(void)
|
|
|
|
|
|
static void plugin_grow_scoreboards__locked(CPUState *cpu)
|
|
|
{
|
|
|
- if (cpu->cpu_index < plugin.scoreboard_alloc_size) {
|
|
|
+ size_t scoreboard_size = plugin.scoreboard_alloc_size;
|
|
|
+ bool need_realloc = false;
|
|
|
+
|
|
|
+ if (cpu->cpu_index < scoreboard_size) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- bool need_realloc = FALSE;
|
|
|
- while (cpu->cpu_index >= plugin.scoreboard_alloc_size) {
|
|
|
- plugin.scoreboard_alloc_size *= 2;
|
|
|
- need_realloc = TRUE;
|
|
|
+ while (cpu->cpu_index >= scoreboard_size) {
|
|
|
+ scoreboard_size *= 2;
|
|
|
+ need_realloc = true;
|
|
|
}
|
|
|
|
|
|
+ if (!need_realloc) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- if (!need_realloc || QLIST_EMPTY(&plugin.scoreboards)) {
|
|
|
- /* nothing to do, we just updated sizes for future scoreboards */
|
|
|
+ if (QLIST_EMPTY(&plugin.scoreboards)) {
|
|
|
+ /* just update size for future scoreboards */
|
|
|
+ plugin.scoreboard_alloc_size = scoreboard_size;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * A scoreboard creation/deletion might be in progress. If a new vcpu is
|
|
|
+ * initialized at the same time, we are safe, as the new
|
|
|
+ * plugin.scoreboard_alloc_size was not yet written.
|
|
|
+ */
|
|
|
+ qemu_rec_mutex_unlock(&plugin.lock);
|
|
|
+
|
|
|
/* cpus must be stopped, as tb might still use an existing scoreboard. */
|
|
|
start_exclusive();
|
|
|
- struct qemu_plugin_scoreboard *score;
|
|
|
- QLIST_FOREACH(score, &plugin.scoreboards, entry) {
|
|
|
- g_array_set_size(score->data, plugin.scoreboard_alloc_size);
|
|
|
+ /* re-acquire lock */
|
|
|
+ qemu_rec_mutex_lock(&plugin.lock);
|
|
|
+ /* in case another vcpu is created between unlock and exclusive section. */
|
|
|
+ if (scoreboard_size > plugin.scoreboard_alloc_size) {
|
|
|
+ struct qemu_plugin_scoreboard *score;
|
|
|
+ QLIST_FOREACH(score, &plugin.scoreboards, entry) {
|
|
|
+ g_array_set_size(score->data, scoreboard_size);
|
|
|
+ }
|
|
|
+ plugin.scoreboard_alloc_size = scoreboard_size;
|
|
|
+ /* force all tb to be flushed, as scoreboard pointers were changed. */
|
|
|
+ tb_flush(cpu);
|
|
|
}
|
|
|
- /* force all tb to be flushed, as scoreboard pointers were changed. */
|
|
|
- tb_flush(cpu);
|
|
|
end_exclusive();
|
|
|
}
|
|
|
|