monitor: let suspend_cnt be thread safe

Monitor code now can be run in more than one thread.  Let it be thread
safe when accessing suspend_cnt counter.

Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
Message-Id: <20180309090006.10018-13-peterx@redhat.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Peter Xu 2018-03-09 16:59:55 +08:00 committed by Eric Blake
parent 546aa56674
commit df152fb950

View File

@ -194,7 +194,7 @@ struct Monitor {
CharBackend chr; CharBackend chr;
int reset_seen; int reset_seen;
int flags; int flags;
int suspend_cnt; int suspend_cnt; /* Needs to be accessed atomically */
bool skip_flush; bool skip_flush;
bool use_io_thr; bool use_io_thr;
@ -3819,7 +3819,7 @@ static int monitor_can_read(void *opaque)
{ {
Monitor *mon = opaque; Monitor *mon = opaque;
return (mon->suspend_cnt == 0) ? 1 : 0; return !atomic_mb_read(&mon->suspend_cnt);
} }
/* /*
@ -3951,7 +3951,7 @@ int monitor_suspend(Monitor *mon)
{ {
if (!mon->rs) if (!mon->rs)
return -ENOTTY; return -ENOTTY;
mon->suspend_cnt++; atomic_inc(&mon->suspend_cnt);
return 0; return 0;
} }
@ -3959,9 +3959,10 @@ void monitor_resume(Monitor *mon)
{ {
if (!mon->rs) if (!mon->rs)
return; return;
if (--mon->suspend_cnt == 0) if (atomic_dec_fetch(&mon->suspend_cnt) == 0) {
readline_show_prompt(mon->rs); readline_show_prompt(mon->rs);
} }
}
static QObject *get_qmp_greeting(Monitor *mon) static QObject *get_qmp_greeting(Monitor *mon)
{ {
@ -4025,19 +4026,19 @@ static void monitor_event(void *opaque, int event)
monitor_resume(mon); monitor_resume(mon);
monitor_flush(mon); monitor_flush(mon);
} else { } else {
mon->suspend_cnt = 0; atomic_mb_set(&mon->suspend_cnt, 0);
} }
break; break;
case CHR_EVENT_MUX_OUT: case CHR_EVENT_MUX_OUT:
if (mon->reset_seen) { if (mon->reset_seen) {
if (mon->suspend_cnt == 0) { if (atomic_mb_read(&mon->suspend_cnt) == 0) {
monitor_printf(mon, "\n"); monitor_printf(mon, "\n");
} }
monitor_flush(mon); monitor_flush(mon);
monitor_suspend(mon); monitor_suspend(mon);
} else { } else {
mon->suspend_cnt++; atomic_inc(&mon->suspend_cnt);
} }
qemu_mutex_lock(&mon->out_lock); qemu_mutex_lock(&mon->out_lock);
mon->mux_out = 1; mon->mux_out = 1;