Revision | 1d95db745b78439e9eec0782eca9cc0d679d6224 (tree) |
---|---|
Zeit | 2019-06-18 15:14:17 |
Autor | Kevin Wolf <kwolf@redh...> |
Commiter | Markus Armbruster |
monitor: Split out monitor/monitor.c
Move the monitor core infrastructure from monitor/misc.c to
monitor/monitor.c. This is code that can be shared for all targets, so
compile it only once.
What remains in monitor/misc.c after this patch is mostly monitor
command implementations (which could move to hmp-cmds.c or qmp-cmds.c
later) and code that requires a system emulator or is even
target-dependent (including HMP command completion code).
The amount of function and particularly extern variables in
monitor_int.h is probably a bit larger than it needs to be, but this way
no non-trivial code modifications are needed. The interfaces between all
monitor parts can be cleaned up later.
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Message-Id: <20190613153405.24769-13-kwolf@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
[Superfluous #include dropped]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
@@ -1920,6 +1920,7 @@ M: Dr. David Alan Gilbert <dgilbert@redhat.com> | ||
1920 | 1920 | S: Maintained |
1921 | 1921 | F: monitor/monitor-internal.h |
1922 | 1922 | F: monitor/misc.c |
1923 | +F: monitor/monitor.c | |
1923 | 1924 | F: monitor/hmp* |
1924 | 1925 | F: hmp.h |
1925 | 1926 | F: hmp-commands*.hx |
@@ -2044,6 +2045,7 @@ S: Supported | ||
2044 | 2045 | F: monitor/monitor-internal.h |
2045 | 2046 | F: monitor/qmp* |
2046 | 2047 | F: monitor/misc.c |
2048 | +F: monitor/monitor.c | |
2047 | 2049 | F: docs/devel/*qmp-* |
2048 | 2050 | F: docs/interop/*qmp-* |
2049 | 2051 | F: scripts/qmp/ |
@@ -19,6 +19,7 @@ typedef struct MonitorHMP MonitorHMP; | ||
19 | 19 | bool monitor_cur_is_qmp(void); |
20 | 20 | |
21 | 21 | void monitor_init_globals(void); |
22 | +void monitor_init_globals_core(void); | |
22 | 23 | void monitor_init(Chardev *chr, int flags); |
23 | 24 | void monitor_cleanup(void); |
24 | 25 |
@@ -1,3 +1,3 @@ | ||
1 | 1 | obj-y += misc.o |
2 | -common-obj-y += qmp.o hmp.o | |
2 | +common-obj-y += monitor.o qmp.o hmp.o | |
3 | 3 | common-obj-y += qmp-cmds.o hmp-cmds.o |
@@ -54,7 +54,6 @@ | ||
54 | 54 | #include "qapi/qmp/qerror.h" |
55 | 55 | #include "qapi/qmp/qstring.h" |
56 | 56 | #include "qom/object_interfaces.h" |
57 | -#include "trace.h" | |
58 | 57 | #include "trace/control.h" |
59 | 58 | #include "monitor/hmp-target.h" |
60 | 59 | #ifdef CONFIG_TRACE_SIMPLE |
@@ -71,7 +70,6 @@ | ||
71 | 70 | #include "qapi/error.h" |
72 | 71 | #include "qapi/qmp-event.h" |
73 | 72 | #include "qapi/qapi-introspect.h" |
74 | -#include "sysemu/qtest.h" | |
75 | 73 | #include "sysemu/cpus.h" |
76 | 74 | #include "qemu/cutils.h" |
77 | 75 | #include "tcg/tcg.h" |
@@ -107,427 +105,15 @@ struct MonFdset { | ||
107 | 105 | QLIST_ENTRY(MonFdset) next; |
108 | 106 | }; |
109 | 107 | |
110 | -/* | |
111 | - * To prevent flooding clients, events can be throttled. The | |
112 | - * throttling is calculated globally, rather than per-Monitor | |
113 | - * instance. | |
114 | - */ | |
115 | -typedef struct MonitorQAPIEventState { | |
116 | - QAPIEvent event; /* Throttling state for this event type and... */ | |
117 | - QDict *data; /* ... data, see qapi_event_throttle_equal() */ | |
118 | - QEMUTimer *timer; /* Timer for handling delayed events */ | |
119 | - QDict *qdict; /* Delayed event (if any) */ | |
120 | -} MonitorQAPIEventState; | |
121 | - | |
122 | -typedef struct { | |
123 | - int64_t rate; /* Minimum time (in ns) between two events */ | |
124 | -} MonitorQAPIEventConf; | |
125 | - | |
126 | -/* Shared monitor I/O thread */ | |
127 | -IOThread *mon_iothread; | |
128 | - | |
129 | -/* Bottom half to dispatch the requests received from I/O thread */ | |
130 | -QEMUBH *qmp_dispatcher_bh; | |
131 | - | |
132 | 108 | /* QMP checker flags */ |
133 | 109 | #define QMP_ACCEPT_UNKNOWNS 1 |
134 | 110 | |
135 | -/* Protects mon_list, monitor_qapi_event_state, monitor_destroyed. */ | |
136 | -QemuMutex monitor_lock; | |
137 | -static GHashTable *monitor_qapi_event_state; | |
138 | -MonitorList mon_list; | |
139 | -static bool monitor_destroyed; | |
140 | - | |
141 | 111 | /* Protects mon_fdsets */ |
142 | 112 | static QemuMutex mon_fdsets_lock; |
143 | 113 | static QLIST_HEAD(, MonFdset) mon_fdsets; |
144 | 114 | |
145 | -int mon_refcount; | |
146 | - | |
147 | 115 | static HMPCommand hmp_info_cmds[]; |
148 | 116 | |
149 | -__thread Monitor *cur_mon; | |
150 | - | |
151 | -/** | |
152 | - * Is @mon is using readline? | |
153 | - * Note: not all HMP monitors use readline, e.g., gdbserver has a | |
154 | - * non-interactive HMP monitor, so readline is not used there. | |
155 | - */ | |
156 | -static inline bool monitor_uses_readline(const Monitor *mon) | |
157 | -{ | |
158 | - return mon->flags & MONITOR_USE_READLINE; | |
159 | -} | |
160 | - | |
161 | -static inline bool monitor_is_hmp_non_interactive(const Monitor *mon) | |
162 | -{ | |
163 | - return !monitor_is_qmp(mon) && !monitor_uses_readline(mon); | |
164 | -} | |
165 | - | |
166 | -/* | |
167 | - * Return the clock to use for recording an event's time. | |
168 | - * It's QEMU_CLOCK_REALTIME, except for qtests it's | |
169 | - * QEMU_CLOCK_VIRTUAL, to support testing rate limits. | |
170 | - * Beware: result is invalid before configure_accelerator(). | |
171 | - */ | |
172 | -static inline QEMUClockType monitor_get_event_clock(void) | |
173 | -{ | |
174 | - return qtest_enabled() ? QEMU_CLOCK_VIRTUAL : QEMU_CLOCK_REALTIME; | |
175 | -} | |
176 | - | |
177 | -/** | |
178 | - * Is the current monitor, if any, a QMP monitor? | |
179 | - */ | |
180 | -bool monitor_cur_is_qmp(void) | |
181 | -{ | |
182 | - return cur_mon && monitor_is_qmp(cur_mon); | |
183 | -} | |
184 | - | |
185 | -static void monitor_flush_locked(Monitor *mon); | |
186 | - | |
187 | -static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, | |
188 | - void *opaque) | |
189 | -{ | |
190 | - Monitor *mon = opaque; | |
191 | - | |
192 | - qemu_mutex_lock(&mon->mon_lock); | |
193 | - mon->out_watch = 0; | |
194 | - monitor_flush_locked(mon); | |
195 | - qemu_mutex_unlock(&mon->mon_lock); | |
196 | - return FALSE; | |
197 | -} | |
198 | - | |
199 | -/* Caller must hold mon->mon_lock */ | |
200 | -static void monitor_flush_locked(Monitor *mon) | |
201 | -{ | |
202 | - int rc; | |
203 | - size_t len; | |
204 | - const char *buf; | |
205 | - | |
206 | - if (mon->skip_flush) { | |
207 | - return; | |
208 | - } | |
209 | - | |
210 | - buf = qstring_get_str(mon->outbuf); | |
211 | - len = qstring_get_length(mon->outbuf); | |
212 | - | |
213 | - if (len && !mon->mux_out) { | |
214 | - rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len); | |
215 | - if ((rc < 0 && errno != EAGAIN) || (rc == len)) { | |
216 | - /* all flushed or error */ | |
217 | - qobject_unref(mon->outbuf); | |
218 | - mon->outbuf = qstring_new(); | |
219 | - return; | |
220 | - } | |
221 | - if (rc > 0) { | |
222 | - /* partial write */ | |
223 | - QString *tmp = qstring_from_str(buf + rc); | |
224 | - qobject_unref(mon->outbuf); | |
225 | - mon->outbuf = tmp; | |
226 | - } | |
227 | - if (mon->out_watch == 0) { | |
228 | - mon->out_watch = | |
229 | - qemu_chr_fe_add_watch(&mon->chr, G_IO_OUT | G_IO_HUP, | |
230 | - monitor_unblocked, mon); | |
231 | - } | |
232 | - } | |
233 | -} | |
234 | - | |
235 | -void monitor_flush(Monitor *mon) | |
236 | -{ | |
237 | - qemu_mutex_lock(&mon->mon_lock); | |
238 | - monitor_flush_locked(mon); | |
239 | - qemu_mutex_unlock(&mon->mon_lock); | |
240 | -} | |
241 | - | |
242 | -/* flush at every end of line */ | |
243 | -int monitor_puts(Monitor *mon, const char *str) | |
244 | -{ | |
245 | - int i; | |
246 | - char c; | |
247 | - | |
248 | - qemu_mutex_lock(&mon->mon_lock); | |
249 | - for (i = 0; str[i]; i++) { | |
250 | - c = str[i]; | |
251 | - if (c == '\n') { | |
252 | - qstring_append_chr(mon->outbuf, '\r'); | |
253 | - } | |
254 | - qstring_append_chr(mon->outbuf, c); | |
255 | - if (c == '\n') { | |
256 | - monitor_flush_locked(mon); | |
257 | - } | |
258 | - } | |
259 | - qemu_mutex_unlock(&mon->mon_lock); | |
260 | - | |
261 | - return i; | |
262 | -} | |
263 | - | |
264 | -int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) | |
265 | -{ | |
266 | - char *buf; | |
267 | - int n; | |
268 | - | |
269 | - if (!mon) | |
270 | - return -1; | |
271 | - | |
272 | - if (monitor_is_qmp(mon)) { | |
273 | - return -1; | |
274 | - } | |
275 | - | |
276 | - buf = g_strdup_vprintf(fmt, ap); | |
277 | - n = monitor_puts(mon, buf); | |
278 | - g_free(buf); | |
279 | - return n; | |
280 | -} | |
281 | - | |
282 | -int monitor_printf(Monitor *mon, const char *fmt, ...) | |
283 | -{ | |
284 | - int ret; | |
285 | - | |
286 | - va_list ap; | |
287 | - va_start(ap, fmt); | |
288 | - ret = monitor_vprintf(mon, fmt, ap); | |
289 | - va_end(ap); | |
290 | - return ret; | |
291 | -} | |
292 | - | |
293 | -static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = { | |
294 | - /* Limit guest-triggerable events to 1 per second */ | |
295 | - [QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS }, | |
296 | - [QAPI_EVENT_WATCHDOG] = { 1000 * SCALE_MS }, | |
297 | - [QAPI_EVENT_BALLOON_CHANGE] = { 1000 * SCALE_MS }, | |
298 | - [QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS }, | |
299 | - [QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS }, | |
300 | - [QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS }, | |
301 | -}; | |
302 | - | |
303 | -/* | |
304 | - * Broadcast an event to all monitors. | |
305 | - * @qdict is the event object. Its member "event" must match @event. | |
306 | - * Caller must hold monitor_lock. | |
307 | - */ | |
308 | -static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) | |
309 | -{ | |
310 | - Monitor *mon; | |
311 | - MonitorQMP *qmp_mon; | |
312 | - | |
313 | - trace_monitor_protocol_event_emit(event, qdict); | |
314 | - QTAILQ_FOREACH(mon, &mon_list, entry) { | |
315 | - if (!monitor_is_qmp(mon)) { | |
316 | - continue; | |
317 | - } | |
318 | - | |
319 | - qmp_mon = container_of(mon, MonitorQMP, common); | |
320 | - if (qmp_mon->commands != &qmp_cap_negotiation_commands) { | |
321 | - qmp_send_response(qmp_mon, qdict); | |
322 | - } | |
323 | - } | |
324 | -} | |
325 | - | |
326 | -static void monitor_qapi_event_handler(void *opaque); | |
327 | - | |
328 | -/* | |
329 | - * Queue a new event for emission to Monitor instances, | |
330 | - * applying any rate limiting if required. | |
331 | - */ | |
332 | -static void | |
333 | -monitor_qapi_event_queue_no_reenter(QAPIEvent event, QDict *qdict) | |
334 | -{ | |
335 | - MonitorQAPIEventConf *evconf; | |
336 | - MonitorQAPIEventState *evstate; | |
337 | - | |
338 | - assert(event < QAPI_EVENT__MAX); | |
339 | - evconf = &monitor_qapi_event_conf[event]; | |
340 | - trace_monitor_protocol_event_queue(event, qdict, evconf->rate); | |
341 | - | |
342 | - qemu_mutex_lock(&monitor_lock); | |
343 | - | |
344 | - if (!evconf->rate) { | |
345 | - /* Unthrottled event */ | |
346 | - monitor_qapi_event_emit(event, qdict); | |
347 | - } else { | |
348 | - QDict *data = qobject_to(QDict, qdict_get(qdict, "data")); | |
349 | - MonitorQAPIEventState key = { .event = event, .data = data }; | |
350 | - | |
351 | - evstate = g_hash_table_lookup(monitor_qapi_event_state, &key); | |
352 | - assert(!evstate || timer_pending(evstate->timer)); | |
353 | - | |
354 | - if (evstate) { | |
355 | - /* | |
356 | - * Timer is pending for (at least) evconf->rate ns after | |
357 | - * last send. Store event for sending when timer fires, | |
358 | - * replacing a prior stored event if any. | |
359 | - */ | |
360 | - qobject_unref(evstate->qdict); | |
361 | - evstate->qdict = qobject_ref(qdict); | |
362 | - } else { | |
363 | - /* | |
364 | - * Last send was (at least) evconf->rate ns ago. | |
365 | - * Send immediately, and arm the timer to call | |
366 | - * monitor_qapi_event_handler() in evconf->rate ns. Any | |
367 | - * events arriving before then will be delayed until then. | |
368 | - */ | |
369 | - int64_t now = qemu_clock_get_ns(monitor_get_event_clock()); | |
370 | - | |
371 | - monitor_qapi_event_emit(event, qdict); | |
372 | - | |
373 | - evstate = g_new(MonitorQAPIEventState, 1); | |
374 | - evstate->event = event; | |
375 | - evstate->data = qobject_ref(data); | |
376 | - evstate->qdict = NULL; | |
377 | - evstate->timer = timer_new_ns(monitor_get_event_clock(), | |
378 | - monitor_qapi_event_handler, | |
379 | - evstate); | |
380 | - g_hash_table_add(monitor_qapi_event_state, evstate); | |
381 | - timer_mod_ns(evstate->timer, now + evconf->rate); | |
382 | - } | |
383 | - } | |
384 | - | |
385 | - qemu_mutex_unlock(&monitor_lock); | |
386 | -} | |
387 | - | |
388 | -void qapi_event_emit(QAPIEvent event, QDict *qdict) | |
389 | -{ | |
390 | - /* | |
391 | - * monitor_qapi_event_queue_no_reenter() is not reentrant: it | |
392 | - * would deadlock on monitor_lock. Work around by queueing | |
393 | - * events in thread-local storage. | |
394 | - * TODO: remove this, make it re-enter safe. | |
395 | - */ | |
396 | - typedef struct MonitorQapiEvent { | |
397 | - QAPIEvent event; | |
398 | - QDict *qdict; | |
399 | - QSIMPLEQ_ENTRY(MonitorQapiEvent) entry; | |
400 | - } MonitorQapiEvent; | |
401 | - static __thread QSIMPLEQ_HEAD(, MonitorQapiEvent) event_queue; | |
402 | - static __thread bool reentered; | |
403 | - MonitorQapiEvent *ev; | |
404 | - | |
405 | - if (!reentered) { | |
406 | - QSIMPLEQ_INIT(&event_queue); | |
407 | - } | |
408 | - | |
409 | - ev = g_new(MonitorQapiEvent, 1); | |
410 | - ev->qdict = qobject_ref(qdict); | |
411 | - ev->event = event; | |
412 | - QSIMPLEQ_INSERT_TAIL(&event_queue, ev, entry); | |
413 | - if (reentered) { | |
414 | - return; | |
415 | - } | |
416 | - | |
417 | - reentered = true; | |
418 | - | |
419 | - while ((ev = QSIMPLEQ_FIRST(&event_queue)) != NULL) { | |
420 | - QSIMPLEQ_REMOVE_HEAD(&event_queue, entry); | |
421 | - monitor_qapi_event_queue_no_reenter(ev->event, ev->qdict); | |
422 | - qobject_unref(ev->qdict); | |
423 | - g_free(ev); | |
424 | - } | |
425 | - | |
426 | - reentered = false; | |
427 | -} | |
428 | - | |
429 | -/* | |
430 | - * This function runs evconf->rate ns after sending a throttled | |
431 | - * event. | |
432 | - * If another event has since been stored, send it. | |
433 | - */ | |
434 | -static void monitor_qapi_event_handler(void *opaque) | |
435 | -{ | |
436 | - MonitorQAPIEventState *evstate = opaque; | |
437 | - MonitorQAPIEventConf *evconf = &monitor_qapi_event_conf[evstate->event]; | |
438 | - | |
439 | - trace_monitor_protocol_event_handler(evstate->event, evstate->qdict); | |
440 | - qemu_mutex_lock(&monitor_lock); | |
441 | - | |
442 | - if (evstate->qdict) { | |
443 | - int64_t now = qemu_clock_get_ns(monitor_get_event_clock()); | |
444 | - | |
445 | - monitor_qapi_event_emit(evstate->event, evstate->qdict); | |
446 | - qobject_unref(evstate->qdict); | |
447 | - evstate->qdict = NULL; | |
448 | - timer_mod_ns(evstate->timer, now + evconf->rate); | |
449 | - } else { | |
450 | - g_hash_table_remove(monitor_qapi_event_state, evstate); | |
451 | - qobject_unref(evstate->data); | |
452 | - timer_free(evstate->timer); | |
453 | - g_free(evstate); | |
454 | - } | |
455 | - | |
456 | - qemu_mutex_unlock(&monitor_lock); | |
457 | -} | |
458 | - | |
459 | -static unsigned int qapi_event_throttle_hash(const void *key) | |
460 | -{ | |
461 | - const MonitorQAPIEventState *evstate = key; | |
462 | - unsigned int hash = evstate->event * 255; | |
463 | - | |
464 | - if (evstate->event == QAPI_EVENT_VSERPORT_CHANGE) { | |
465 | - hash += g_str_hash(qdict_get_str(evstate->data, "id")); | |
466 | - } | |
467 | - | |
468 | - if (evstate->event == QAPI_EVENT_QUORUM_REPORT_BAD) { | |
469 | - hash += g_str_hash(qdict_get_str(evstate->data, "node-name")); | |
470 | - } | |
471 | - | |
472 | - return hash; | |
473 | -} | |
474 | - | |
475 | -static gboolean qapi_event_throttle_equal(const void *a, const void *b) | |
476 | -{ | |
477 | - const MonitorQAPIEventState *eva = a; | |
478 | - const MonitorQAPIEventState *evb = b; | |
479 | - | |
480 | - if (eva->event != evb->event) { | |
481 | - return FALSE; | |
482 | - } | |
483 | - | |
484 | - if (eva->event == QAPI_EVENT_VSERPORT_CHANGE) { | |
485 | - return !strcmp(qdict_get_str(eva->data, "id"), | |
486 | - qdict_get_str(evb->data, "id")); | |
487 | - } | |
488 | - | |
489 | - if (eva->event == QAPI_EVENT_QUORUM_REPORT_BAD) { | |
490 | - return !strcmp(qdict_get_str(eva->data, "node-name"), | |
491 | - qdict_get_str(evb->data, "node-name")); | |
492 | - } | |
493 | - | |
494 | - return TRUE; | |
495 | -} | |
496 | - | |
497 | -static void monitor_qapi_event_init(void) | |
498 | -{ | |
499 | - monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash, | |
500 | - qapi_event_throttle_equal); | |
501 | -} | |
502 | - | |
503 | -static void monitor_iothread_init(void); | |
504 | - | |
505 | -void monitor_data_init(Monitor *mon, int flags, bool skip_flush, | |
506 | - bool use_io_thread) | |
507 | -{ | |
508 | - if (use_io_thread && !mon_iothread) { | |
509 | - monitor_iothread_init(); | |
510 | - } | |
511 | - qemu_mutex_init(&mon->mon_lock); | |
512 | - mon->outbuf = qstring_new(); | |
513 | - mon->skip_flush = skip_flush; | |
514 | - mon->use_io_thread = use_io_thread; | |
515 | - mon->flags = flags; | |
516 | -} | |
517 | - | |
518 | -static void monitor_data_destroy(Monitor *mon) | |
519 | -{ | |
520 | - g_free(mon->mon_cpu_path); | |
521 | - qemu_chr_fe_deinit(&mon->chr, false); | |
522 | - if (monitor_is_qmp(mon)) { | |
523 | - monitor_data_destroy_qmp(container_of(mon, MonitorQMP, common)); | |
524 | - } else { | |
525 | - readline_free(container_of(mon, MonitorHMP, common)->rs); | |
526 | - } | |
527 | - qobject_unref(mon->outbuf); | |
528 | - qemu_mutex_destroy(&mon->mon_lock); | |
529 | -} | |
530 | - | |
531 | 117 | char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index, |
532 | 118 | int64_t cpu_index, Error **errp) |
533 | 119 | { |
@@ -2728,67 +2314,6 @@ void loadvm_completion(ReadLineState *rs, int nb_args, const char *str) | ||
2728 | 2314 | } |
2729 | 2315 | } |
2730 | 2316 | |
2731 | -int monitor_can_read(void *opaque) | |
2732 | -{ | |
2733 | - Monitor *mon = opaque; | |
2734 | - | |
2735 | - return !atomic_mb_read(&mon->suspend_cnt); | |
2736 | -} | |
2737 | - | |
2738 | -int monitor_suspend(Monitor *mon) | |
2739 | -{ | |
2740 | - if (monitor_is_hmp_non_interactive(mon)) { | |
2741 | - return -ENOTTY; | |
2742 | - } | |
2743 | - | |
2744 | - atomic_inc(&mon->suspend_cnt); | |
2745 | - | |
2746 | - if (mon->use_io_thread) { | |
2747 | - /* | |
2748 | - * Kick I/O thread to make sure this takes effect. It'll be | |
2749 | - * evaluated again in prepare() of the watch object. | |
2750 | - */ | |
2751 | - aio_notify(iothread_get_aio_context(mon_iothread)); | |
2752 | - } | |
2753 | - | |
2754 | - trace_monitor_suspend(mon, 1); | |
2755 | - return 0; | |
2756 | -} | |
2757 | - | |
2758 | -static void monitor_accept_input(void *opaque) | |
2759 | -{ | |
2760 | - Monitor *mon = opaque; | |
2761 | - | |
2762 | - qemu_chr_fe_accept_input(&mon->chr); | |
2763 | -} | |
2764 | - | |
2765 | -void monitor_resume(Monitor *mon) | |
2766 | -{ | |
2767 | - if (monitor_is_hmp_non_interactive(mon)) { | |
2768 | - return; | |
2769 | - } | |
2770 | - | |
2771 | - if (atomic_dec_fetch(&mon->suspend_cnt) == 0) { | |
2772 | - AioContext *ctx; | |
2773 | - | |
2774 | - if (mon->use_io_thread) { | |
2775 | - ctx = iothread_get_aio_context(mon_iothread); | |
2776 | - } else { | |
2777 | - ctx = qemu_get_aio_context(); | |
2778 | - } | |
2779 | - | |
2780 | - if (!monitor_is_qmp(mon)) { | |
2781 | - MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common); | |
2782 | - assert(hmp_mon->rs); | |
2783 | - readline_show_prompt(hmp_mon->rs); | |
2784 | - } | |
2785 | - | |
2786 | - aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon); | |
2787 | - } | |
2788 | - | |
2789 | - trace_monitor_suspend(mon, -1); | |
2790 | -} | |
2791 | - | |
2792 | 2317 | static int |
2793 | 2318 | compare_mon_cmd(const void *a, const void *b) |
2794 | 2319 | { |
@@ -2806,135 +2331,14 @@ static void sortcmdlist(void) | ||
2806 | 2331 | compare_mon_cmd); |
2807 | 2332 | } |
2808 | 2333 | |
2809 | -static void monitor_iothread_init(void) | |
2810 | -{ | |
2811 | - mon_iothread = iothread_create("mon_iothread", &error_abort); | |
2812 | -} | |
2813 | - | |
2814 | 2334 | void monitor_init_globals(void) |
2815 | 2335 | { |
2336 | + monitor_init_globals_core(); | |
2816 | 2337 | monitor_init_qmp_commands(); |
2817 | - monitor_qapi_event_init(); | |
2818 | 2338 | sortcmdlist(); |
2819 | - qemu_mutex_init(&monitor_lock); | |
2820 | 2339 | qemu_mutex_init(&mon_fdsets_lock); |
2821 | - | |
2822 | - /* | |
2823 | - * The dispatcher BH must run in the main loop thread, since we | |
2824 | - * have commands assuming that context. It would be nice to get | |
2825 | - * rid of those assumptions. | |
2826 | - */ | |
2827 | - qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(), | |
2828 | - monitor_qmp_bh_dispatcher, | |
2829 | - NULL); | |
2830 | -} | |
2831 | - | |
2832 | -/* | |
2833 | - * Print to current monitor if we have one, else to stderr. | |
2834 | - */ | |
2835 | -int error_vprintf(const char *fmt, va_list ap) | |
2836 | -{ | |
2837 | - if (cur_mon && !monitor_cur_is_qmp()) { | |
2838 | - return monitor_vprintf(cur_mon, fmt, ap); | |
2839 | - } | |
2840 | - return vfprintf(stderr, fmt, ap); | |
2841 | -} | |
2842 | - | |
2843 | -int error_vprintf_unless_qmp(const char *fmt, va_list ap) | |
2844 | -{ | |
2845 | - if (!cur_mon) { | |
2846 | - return vfprintf(stderr, fmt, ap); | |
2847 | - } | |
2848 | - if (!monitor_cur_is_qmp()) { | |
2849 | - return monitor_vprintf(cur_mon, fmt, ap); | |
2850 | - } | |
2851 | - return -1; | |
2852 | -} | |
2853 | - | |
2854 | -void monitor_list_append(Monitor *mon) | |
2855 | -{ | |
2856 | - qemu_mutex_lock(&monitor_lock); | |
2857 | - /* | |
2858 | - * This prevents inserting new monitors during monitor_cleanup(). | |
2859 | - * A cleaner solution would involve the main thread telling other | |
2860 | - * threads to terminate, waiting for their termination. | |
2861 | - */ | |
2862 | - if (!monitor_destroyed) { | |
2863 | - QTAILQ_INSERT_HEAD(&mon_list, mon, entry); | |
2864 | - mon = NULL; | |
2865 | - } | |
2866 | - qemu_mutex_unlock(&monitor_lock); | |
2867 | - | |
2868 | - if (mon) { | |
2869 | - monitor_data_destroy(mon); | |
2870 | - g_free(mon); | |
2871 | - } | |
2872 | -} | |
2873 | - | |
2874 | -void monitor_init(Chardev *chr, int flags) | |
2875 | -{ | |
2876 | - if (flags & MONITOR_USE_CONTROL) { | |
2877 | - monitor_init_qmp(chr, flags); | |
2878 | - } else { | |
2879 | - monitor_init_hmp(chr, flags); | |
2880 | - } | |
2881 | 2340 | } |
2882 | 2341 | |
2883 | -void monitor_cleanup(void) | |
2884 | -{ | |
2885 | - /* | |
2886 | - * We need to explicitly stop the I/O thread (but not destroy it), | |
2887 | - * clean up the monitor resources, then destroy the I/O thread since | |
2888 | - * we need to unregister from chardev below in | |
2889 | - * monitor_data_destroy(), and chardev is not thread-safe yet | |
2890 | - */ | |
2891 | - if (mon_iothread) { | |
2892 | - iothread_stop(mon_iothread); | |
2893 | - } | |
2894 | - | |
2895 | - /* Flush output buffers and destroy monitors */ | |
2896 | - qemu_mutex_lock(&monitor_lock); | |
2897 | - monitor_destroyed = true; | |
2898 | - while (!QTAILQ_EMPTY(&mon_list)) { | |
2899 | - Monitor *mon = QTAILQ_FIRST(&mon_list); | |
2900 | - QTAILQ_REMOVE(&mon_list, mon, entry); | |
2901 | - /* Permit QAPI event emission from character frontend release */ | |
2902 | - qemu_mutex_unlock(&monitor_lock); | |
2903 | - monitor_flush(mon); | |
2904 | - monitor_data_destroy(mon); | |
2905 | - qemu_mutex_lock(&monitor_lock); | |
2906 | - g_free(mon); | |
2907 | - } | |
2908 | - qemu_mutex_unlock(&monitor_lock); | |
2909 | - | |
2910 | - /* QEMUBHs needs to be deleted before destroying the I/O thread */ | |
2911 | - qemu_bh_delete(qmp_dispatcher_bh); | |
2912 | - qmp_dispatcher_bh = NULL; | |
2913 | - if (mon_iothread) { | |
2914 | - iothread_destroy(mon_iothread); | |
2915 | - mon_iothread = NULL; | |
2916 | - } | |
2917 | -} | |
2918 | - | |
2919 | -QemuOptsList qemu_mon_opts = { | |
2920 | - .name = "mon", | |
2921 | - .implied_opt_name = "chardev", | |
2922 | - .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head), | |
2923 | - .desc = { | |
2924 | - { | |
2925 | - .name = "mode", | |
2926 | - .type = QEMU_OPT_STRING, | |
2927 | - },{ | |
2928 | - .name = "chardev", | |
2929 | - .type = QEMU_OPT_STRING, | |
2930 | - },{ | |
2931 | - .name = "pretty", | |
2932 | - .type = QEMU_OPT_BOOL, | |
2933 | - }, | |
2934 | - { /* end of list */ } | |
2935 | - }, | |
2936 | -}; | |
2937 | - | |
2938 | 2342 | HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) |
2939 | 2343 | { |
2940 | 2344 | MachineState *ms = MACHINE(qdev_get_machine()); |
@@ -167,6 +167,7 @@ void monitor_init_hmp(Chardev *chr, int flags); | ||
167 | 167 | int monitor_puts(Monitor *mon, const char *str); |
168 | 168 | void monitor_data_init(Monitor *mon, int flags, bool skip_flush, |
169 | 169 | bool use_io_thread); |
170 | +void monitor_data_destroy(Monitor *mon); | |
170 | 171 | int monitor_can_read(void *opaque); |
171 | 172 | void monitor_list_append(Monitor *mon); |
172 | 173 | void monitor_fdsets_cleanup(void); |
@@ -0,0 +1,633 @@ | ||
1 | +/* | |
2 | + * QEMU monitor | |
3 | + * | |
4 | + * Copyright (c) 2003-2004 Fabrice Bellard | |
5 | + * | |
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | + * of this software and associated documentation files (the "Software"), to deal | |
8 | + * in the Software without restriction, including without limitation the rights | |
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | + * copies of the Software, and to permit persons to whom the Software is | |
11 | + * furnished to do so, subject to the following conditions: | |
12 | + * | |
13 | + * The above copyright notice and this permission notice shall be included in | |
14 | + * all copies or substantial portions of the Software. | |
15 | + * | |
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | + * THE SOFTWARE. | |
23 | + */ | |
24 | + | |
25 | +#include "qemu/osdep.h" | |
26 | +#include "monitor-internal.h" | |
27 | +#include "qapi/error.h" | |
28 | +#include "qapi/qapi-emit-events.h" | |
29 | +#include "qapi/qmp/qdict.h" | |
30 | +#include "qapi/qmp/qstring.h" | |
31 | +#include "qemu/error-report.h" | |
32 | +#include "qemu/option.h" | |
33 | +#include "sysemu/qtest.h" | |
34 | +#include "trace.h" | |
35 | + | |
36 | +/* | |
37 | + * To prevent flooding clients, events can be throttled. The | |
38 | + * throttling is calculated globally, rather than per-Monitor | |
39 | + * instance. | |
40 | + */ | |
41 | +typedef struct MonitorQAPIEventState { | |
42 | + QAPIEvent event; /* Throttling state for this event type and... */ | |
43 | + QDict *data; /* ... data, see qapi_event_throttle_equal() */ | |
44 | + QEMUTimer *timer; /* Timer for handling delayed events */ | |
45 | + QDict *qdict; /* Delayed event (if any) */ | |
46 | +} MonitorQAPIEventState; | |
47 | + | |
48 | +typedef struct { | |
49 | + int64_t rate; /* Minimum time (in ns) between two events */ | |
50 | +} MonitorQAPIEventConf; | |
51 | + | |
52 | +/* Shared monitor I/O thread */ | |
53 | +IOThread *mon_iothread; | |
54 | + | |
55 | +/* Bottom half to dispatch the requests received from I/O thread */ | |
56 | +QEMUBH *qmp_dispatcher_bh; | |
57 | + | |
58 | +/* Protects mon_list, monitor_qapi_event_state, monitor_destroyed. */ | |
59 | +QemuMutex monitor_lock; | |
60 | +static GHashTable *monitor_qapi_event_state; | |
61 | + | |
62 | +MonitorList mon_list; | |
63 | +int mon_refcount; | |
64 | +static bool monitor_destroyed; | |
65 | + | |
66 | +__thread Monitor *cur_mon; | |
67 | + | |
68 | +/** | |
69 | + * Is the current monitor, if any, a QMP monitor? | |
70 | + */ | |
71 | +bool monitor_cur_is_qmp(void) | |
72 | +{ | |
73 | + return cur_mon && monitor_is_qmp(cur_mon); | |
74 | +} | |
75 | + | |
76 | +/** | |
77 | + * Is @mon is using readline? | |
78 | + * Note: not all HMP monitors use readline, e.g., gdbserver has a | |
79 | + * non-interactive HMP monitor, so readline is not used there. | |
80 | + */ | |
81 | +static inline bool monitor_uses_readline(const Monitor *mon) | |
82 | +{ | |
83 | + return mon->flags & MONITOR_USE_READLINE; | |
84 | +} | |
85 | + | |
86 | +static inline bool monitor_is_hmp_non_interactive(const Monitor *mon) | |
87 | +{ | |
88 | + return !monitor_is_qmp(mon) && !monitor_uses_readline(mon); | |
89 | +} | |
90 | + | |
91 | +static void monitor_flush_locked(Monitor *mon); | |
92 | + | |
93 | +static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond, | |
94 | + void *opaque) | |
95 | +{ | |
96 | + Monitor *mon = opaque; | |
97 | + | |
98 | + qemu_mutex_lock(&mon->mon_lock); | |
99 | + mon->out_watch = 0; | |
100 | + monitor_flush_locked(mon); | |
101 | + qemu_mutex_unlock(&mon->mon_lock); | |
102 | + return FALSE; | |
103 | +} | |
104 | + | |
105 | +/* Caller must hold mon->mon_lock */ | |
106 | +static void monitor_flush_locked(Monitor *mon) | |
107 | +{ | |
108 | + int rc; | |
109 | + size_t len; | |
110 | + const char *buf; | |
111 | + | |
112 | + if (mon->skip_flush) { | |
113 | + return; | |
114 | + } | |
115 | + | |
116 | + buf = qstring_get_str(mon->outbuf); | |
117 | + len = qstring_get_length(mon->outbuf); | |
118 | + | |
119 | + if (len && !mon->mux_out) { | |
120 | + rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len); | |
121 | + if ((rc < 0 && errno != EAGAIN) || (rc == len)) { | |
122 | + /* all flushed or error */ | |
123 | + qobject_unref(mon->outbuf); | |
124 | + mon->outbuf = qstring_new(); | |
125 | + return; | |
126 | + } | |
127 | + if (rc > 0) { | |
128 | + /* partial write */ | |
129 | + QString *tmp = qstring_from_str(buf + rc); | |
130 | + qobject_unref(mon->outbuf); | |
131 | + mon->outbuf = tmp; | |
132 | + } | |
133 | + if (mon->out_watch == 0) { | |
134 | + mon->out_watch = | |
135 | + qemu_chr_fe_add_watch(&mon->chr, G_IO_OUT | G_IO_HUP, | |
136 | + monitor_unblocked, mon); | |
137 | + } | |
138 | + } | |
139 | +} | |
140 | + | |
141 | +void monitor_flush(Monitor *mon) | |
142 | +{ | |
143 | + qemu_mutex_lock(&mon->mon_lock); | |
144 | + monitor_flush_locked(mon); | |
145 | + qemu_mutex_unlock(&mon->mon_lock); | |
146 | +} | |
147 | + | |
148 | +/* flush at every end of line */ | |
149 | +int monitor_puts(Monitor *mon, const char *str) | |
150 | +{ | |
151 | + int i; | |
152 | + char c; | |
153 | + | |
154 | + qemu_mutex_lock(&mon->mon_lock); | |
155 | + for (i = 0; str[i]; i++) { | |
156 | + c = str[i]; | |
157 | + if (c == '\n') { | |
158 | + qstring_append_chr(mon->outbuf, '\r'); | |
159 | + } | |
160 | + qstring_append_chr(mon->outbuf, c); | |
161 | + if (c == '\n') { | |
162 | + monitor_flush_locked(mon); | |
163 | + } | |
164 | + } | |
165 | + qemu_mutex_unlock(&mon->mon_lock); | |
166 | + | |
167 | + return i; | |
168 | +} | |
169 | + | |
170 | +int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) | |
171 | +{ | |
172 | + char *buf; | |
173 | + int n; | |
174 | + | |
175 | + if (!mon) { | |
176 | + return -1; | |
177 | + } | |
178 | + | |
179 | + if (monitor_is_qmp(mon)) { | |
180 | + return -1; | |
181 | + } | |
182 | + | |
183 | + buf = g_strdup_vprintf(fmt, ap); | |
184 | + n = monitor_puts(mon, buf); | |
185 | + g_free(buf); | |
186 | + return n; | |
187 | +} | |
188 | + | |
189 | +int monitor_printf(Monitor *mon, const char *fmt, ...) | |
190 | +{ | |
191 | + int ret; | |
192 | + | |
193 | + va_list ap; | |
194 | + va_start(ap, fmt); | |
195 | + ret = monitor_vprintf(mon, fmt, ap); | |
196 | + va_end(ap); | |
197 | + return ret; | |
198 | +} | |
199 | + | |
200 | +/* | |
201 | + * Print to current monitor if we have one, else to stderr. | |
202 | + */ | |
203 | +int error_vprintf(const char *fmt, va_list ap) | |
204 | +{ | |
205 | + if (cur_mon && !monitor_cur_is_qmp()) { | |
206 | + return monitor_vprintf(cur_mon, fmt, ap); | |
207 | + } | |
208 | + return vfprintf(stderr, fmt, ap); | |
209 | +} | |
210 | + | |
211 | +int error_vprintf_unless_qmp(const char *fmt, va_list ap) | |
212 | +{ | |
213 | + if (!cur_mon) { | |
214 | + return vfprintf(stderr, fmt, ap); | |
215 | + } | |
216 | + if (!monitor_cur_is_qmp()) { | |
217 | + return monitor_vprintf(cur_mon, fmt, ap); | |
218 | + } | |
219 | + return -1; | |
220 | +} | |
221 | + | |
222 | + | |
223 | +static MonitorQAPIEventConf monitor_qapi_event_conf[QAPI_EVENT__MAX] = { | |
224 | + /* Limit guest-triggerable events to 1 per second */ | |
225 | + [QAPI_EVENT_RTC_CHANGE] = { 1000 * SCALE_MS }, | |
226 | + [QAPI_EVENT_WATCHDOG] = { 1000 * SCALE_MS }, | |
227 | + [QAPI_EVENT_BALLOON_CHANGE] = { 1000 * SCALE_MS }, | |
228 | + [QAPI_EVENT_QUORUM_REPORT_BAD] = { 1000 * SCALE_MS }, | |
229 | + [QAPI_EVENT_QUORUM_FAILURE] = { 1000 * SCALE_MS }, | |
230 | + [QAPI_EVENT_VSERPORT_CHANGE] = { 1000 * SCALE_MS }, | |
231 | +}; | |
232 | + | |
233 | +/* | |
234 | + * Return the clock to use for recording an event's time. | |
235 | + * It's QEMU_CLOCK_REALTIME, except for qtests it's | |
236 | + * QEMU_CLOCK_VIRTUAL, to support testing rate limits. | |
237 | + * Beware: result is invalid before configure_accelerator(). | |
238 | + */ | |
239 | +static inline QEMUClockType monitor_get_event_clock(void) | |
240 | +{ | |
241 | + return qtest_enabled() ? QEMU_CLOCK_VIRTUAL : QEMU_CLOCK_REALTIME; | |
242 | +} | |
243 | + | |
244 | +/* | |
245 | + * Broadcast an event to all monitors. | |
246 | + * @qdict is the event object. Its member "event" must match @event. | |
247 | + * Caller must hold monitor_lock. | |
248 | + */ | |
249 | +static void monitor_qapi_event_emit(QAPIEvent event, QDict *qdict) | |
250 | +{ | |
251 | + Monitor *mon; | |
252 | + MonitorQMP *qmp_mon; | |
253 | + | |
254 | + trace_monitor_protocol_event_emit(event, qdict); | |
255 | + QTAILQ_FOREACH(mon, &mon_list, entry) { | |
256 | + if (!monitor_is_qmp(mon)) { | |
257 | + continue; | |
258 | + } | |
259 | + | |
260 | + qmp_mon = container_of(mon, MonitorQMP, common); | |
261 | + if (qmp_mon->commands != &qmp_cap_negotiation_commands) { | |
262 | + qmp_send_response(qmp_mon, qdict); | |
263 | + } | |
264 | + } | |
265 | +} | |
266 | + | |
267 | +static void monitor_qapi_event_handler(void *opaque); | |
268 | + | |
269 | +/* | |
270 | + * Queue a new event for emission to Monitor instances, | |
271 | + * applying any rate limiting if required. | |
272 | + */ | |
273 | +static void | |
274 | +monitor_qapi_event_queue_no_reenter(QAPIEvent event, QDict *qdict) | |
275 | +{ | |
276 | + MonitorQAPIEventConf *evconf; | |
277 | + MonitorQAPIEventState *evstate; | |
278 | + | |
279 | + assert(event < QAPI_EVENT__MAX); | |
280 | + evconf = &monitor_qapi_event_conf[event]; | |
281 | + trace_monitor_protocol_event_queue(event, qdict, evconf->rate); | |
282 | + | |
283 | + qemu_mutex_lock(&monitor_lock); | |
284 | + | |
285 | + if (!evconf->rate) { | |
286 | + /* Unthrottled event */ | |
287 | + monitor_qapi_event_emit(event, qdict); | |
288 | + } else { | |
289 | + QDict *data = qobject_to(QDict, qdict_get(qdict, "data")); | |
290 | + MonitorQAPIEventState key = { .event = event, .data = data }; | |
291 | + | |
292 | + evstate = g_hash_table_lookup(monitor_qapi_event_state, &key); | |
293 | + assert(!evstate || timer_pending(evstate->timer)); | |
294 | + | |
295 | + if (evstate) { | |
296 | + /* | |
297 | + * Timer is pending for (at least) evconf->rate ns after | |
298 | + * last send. Store event for sending when timer fires, | |
299 | + * replacing a prior stored event if any. | |
300 | + */ | |
301 | + qobject_unref(evstate->qdict); | |
302 | + evstate->qdict = qobject_ref(qdict); | |
303 | + } else { | |
304 | + /* | |
305 | + * Last send was (at least) evconf->rate ns ago. | |
306 | + * Send immediately, and arm the timer to call | |
307 | + * monitor_qapi_event_handler() in evconf->rate ns. Any | |
308 | + * events arriving before then will be delayed until then. | |
309 | + */ | |
310 | + int64_t now = qemu_clock_get_ns(monitor_get_event_clock()); | |
311 | + | |
312 | + monitor_qapi_event_emit(event, qdict); | |
313 | + | |
314 | + evstate = g_new(MonitorQAPIEventState, 1); | |
315 | + evstate->event = event; | |
316 | + evstate->data = qobject_ref(data); | |
317 | + evstate->qdict = NULL; | |
318 | + evstate->timer = timer_new_ns(monitor_get_event_clock(), | |
319 | + monitor_qapi_event_handler, | |
320 | + evstate); | |
321 | + g_hash_table_add(monitor_qapi_event_state, evstate); | |
322 | + timer_mod_ns(evstate->timer, now + evconf->rate); | |
323 | + } | |
324 | + } | |
325 | + | |
326 | + qemu_mutex_unlock(&monitor_lock); | |
327 | +} | |
328 | + | |
329 | +void qapi_event_emit(QAPIEvent event, QDict *qdict) | |
330 | +{ | |
331 | + /* | |
332 | + * monitor_qapi_event_queue_no_reenter() is not reentrant: it | |
333 | + * would deadlock on monitor_lock. Work around by queueing | |
334 | + * events in thread-local storage. | |
335 | + * TODO: remove this, make it re-enter safe. | |
336 | + */ | |
337 | + typedef struct MonitorQapiEvent { | |
338 | + QAPIEvent event; | |
339 | + QDict *qdict; | |
340 | + QSIMPLEQ_ENTRY(MonitorQapiEvent) entry; | |
341 | + } MonitorQapiEvent; | |
342 | + static __thread QSIMPLEQ_HEAD(, MonitorQapiEvent) event_queue; | |
343 | + static __thread bool reentered; | |
344 | + MonitorQapiEvent *ev; | |
345 | + | |
346 | + if (!reentered) { | |
347 | + QSIMPLEQ_INIT(&event_queue); | |
348 | + } | |
349 | + | |
350 | + ev = g_new(MonitorQapiEvent, 1); | |
351 | + ev->qdict = qobject_ref(qdict); | |
352 | + ev->event = event; | |
353 | + QSIMPLEQ_INSERT_TAIL(&event_queue, ev, entry); | |
354 | + if (reentered) { | |
355 | + return; | |
356 | + } | |
357 | + | |
358 | + reentered = true; | |
359 | + | |
360 | + while ((ev = QSIMPLEQ_FIRST(&event_queue)) != NULL) { | |
361 | + QSIMPLEQ_REMOVE_HEAD(&event_queue, entry); | |
362 | + monitor_qapi_event_queue_no_reenter(ev->event, ev->qdict); | |
363 | + qobject_unref(ev->qdict); | |
364 | + g_free(ev); | |
365 | + } | |
366 | + | |
367 | + reentered = false; | |
368 | +} | |
369 | + | |
370 | +/* | |
371 | + * This function runs evconf->rate ns after sending a throttled | |
372 | + * event. | |
373 | + * If another event has since been stored, send it. | |
374 | + */ | |
375 | +static void monitor_qapi_event_handler(void *opaque) | |
376 | +{ | |
377 | + MonitorQAPIEventState *evstate = opaque; | |
378 | + MonitorQAPIEventConf *evconf = &monitor_qapi_event_conf[evstate->event]; | |
379 | + | |
380 | + trace_monitor_protocol_event_handler(evstate->event, evstate->qdict); | |
381 | + qemu_mutex_lock(&monitor_lock); | |
382 | + | |
383 | + if (evstate->qdict) { | |
384 | + int64_t now = qemu_clock_get_ns(monitor_get_event_clock()); | |
385 | + | |
386 | + monitor_qapi_event_emit(evstate->event, evstate->qdict); | |
387 | + qobject_unref(evstate->qdict); | |
388 | + evstate->qdict = NULL; | |
389 | + timer_mod_ns(evstate->timer, now + evconf->rate); | |
390 | + } else { | |
391 | + g_hash_table_remove(monitor_qapi_event_state, evstate); | |
392 | + qobject_unref(evstate->data); | |
393 | + timer_free(evstate->timer); | |
394 | + g_free(evstate); | |
395 | + } | |
396 | + | |
397 | + qemu_mutex_unlock(&monitor_lock); | |
398 | +} | |
399 | + | |
400 | +static unsigned int qapi_event_throttle_hash(const void *key) | |
401 | +{ | |
402 | + const MonitorQAPIEventState *evstate = key; | |
403 | + unsigned int hash = evstate->event * 255; | |
404 | + | |
405 | + if (evstate->event == QAPI_EVENT_VSERPORT_CHANGE) { | |
406 | + hash += g_str_hash(qdict_get_str(evstate->data, "id")); | |
407 | + } | |
408 | + | |
409 | + if (evstate->event == QAPI_EVENT_QUORUM_REPORT_BAD) { | |
410 | + hash += g_str_hash(qdict_get_str(evstate->data, "node-name")); | |
411 | + } | |
412 | + | |
413 | + return hash; | |
414 | +} | |
415 | + | |
416 | +static gboolean qapi_event_throttle_equal(const void *a, const void *b) | |
417 | +{ | |
418 | + const MonitorQAPIEventState *eva = a; | |
419 | + const MonitorQAPIEventState *evb = b; | |
420 | + | |
421 | + if (eva->event != evb->event) { | |
422 | + return FALSE; | |
423 | + } | |
424 | + | |
425 | + if (eva->event == QAPI_EVENT_VSERPORT_CHANGE) { | |
426 | + return !strcmp(qdict_get_str(eva->data, "id"), | |
427 | + qdict_get_str(evb->data, "id")); | |
428 | + } | |
429 | + | |
430 | + if (eva->event == QAPI_EVENT_QUORUM_REPORT_BAD) { | |
431 | + return !strcmp(qdict_get_str(eva->data, "node-name"), | |
432 | + qdict_get_str(evb->data, "node-name")); | |
433 | + } | |
434 | + | |
435 | + return TRUE; | |
436 | +} | |
437 | + | |
438 | +int monitor_suspend(Monitor *mon) | |
439 | +{ | |
440 | + if (monitor_is_hmp_non_interactive(mon)) { | |
441 | + return -ENOTTY; | |
442 | + } | |
443 | + | |
444 | + atomic_inc(&mon->suspend_cnt); | |
445 | + | |
446 | + if (mon->use_io_thread) { | |
447 | + /* | |
448 | + * Kick I/O thread to make sure this takes effect. It'll be | |
449 | + * evaluated again in prepare() of the watch object. | |
450 | + */ | |
451 | + aio_notify(iothread_get_aio_context(mon_iothread)); | |
452 | + } | |
453 | + | |
454 | + trace_monitor_suspend(mon, 1); | |
455 | + return 0; | |
456 | +} | |
457 | + | |
458 | +static void monitor_accept_input(void *opaque) | |
459 | +{ | |
460 | + Monitor *mon = opaque; | |
461 | + | |
462 | + qemu_chr_fe_accept_input(&mon->chr); | |
463 | +} | |
464 | + | |
465 | +void monitor_resume(Monitor *mon) | |
466 | +{ | |
467 | + if (monitor_is_hmp_non_interactive(mon)) { | |
468 | + return; | |
469 | + } | |
470 | + | |
471 | + if (atomic_dec_fetch(&mon->suspend_cnt) == 0) { | |
472 | + AioContext *ctx; | |
473 | + | |
474 | + if (mon->use_io_thread) { | |
475 | + ctx = iothread_get_aio_context(mon_iothread); | |
476 | + } else { | |
477 | + ctx = qemu_get_aio_context(); | |
478 | + } | |
479 | + | |
480 | + if (!monitor_is_qmp(mon)) { | |
481 | + MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common); | |
482 | + assert(hmp_mon->rs); | |
483 | + readline_show_prompt(hmp_mon->rs); | |
484 | + } | |
485 | + | |
486 | + aio_bh_schedule_oneshot(ctx, monitor_accept_input, mon); | |
487 | + } | |
488 | + | |
489 | + trace_monitor_suspend(mon, -1); | |
490 | +} | |
491 | + | |
492 | +int monitor_can_read(void *opaque) | |
493 | +{ | |
494 | + Monitor *mon = opaque; | |
495 | + | |
496 | + return !atomic_mb_read(&mon->suspend_cnt); | |
497 | +} | |
498 | + | |
499 | +void monitor_list_append(Monitor *mon) | |
500 | +{ | |
501 | + qemu_mutex_lock(&monitor_lock); | |
502 | + /* | |
503 | + * This prevents inserting new monitors during monitor_cleanup(). | |
504 | + * A cleaner solution would involve the main thread telling other | |
505 | + * threads to terminate, waiting for their termination. | |
506 | + */ | |
507 | + if (!monitor_destroyed) { | |
508 | + QTAILQ_INSERT_HEAD(&mon_list, mon, entry); | |
509 | + mon = NULL; | |
510 | + } | |
511 | + qemu_mutex_unlock(&monitor_lock); | |
512 | + | |
513 | + if (mon) { | |
514 | + monitor_data_destroy(mon); | |
515 | + g_free(mon); | |
516 | + } | |
517 | +} | |
518 | + | |
519 | +static void monitor_iothread_init(void) | |
520 | +{ | |
521 | + mon_iothread = iothread_create("mon_iothread", &error_abort); | |
522 | +} | |
523 | + | |
524 | +void monitor_data_init(Monitor *mon, int flags, bool skip_flush, | |
525 | + bool use_io_thread) | |
526 | +{ | |
527 | + if (use_io_thread && !mon_iothread) { | |
528 | + monitor_iothread_init(); | |
529 | + } | |
530 | + qemu_mutex_init(&mon->mon_lock); | |
531 | + mon->outbuf = qstring_new(); | |
532 | + mon->skip_flush = skip_flush; | |
533 | + mon->use_io_thread = use_io_thread; | |
534 | + mon->flags = flags; | |
535 | +} | |
536 | + | |
537 | +void monitor_data_destroy(Monitor *mon) | |
538 | +{ | |
539 | + g_free(mon->mon_cpu_path); | |
540 | + qemu_chr_fe_deinit(&mon->chr, false); | |
541 | + if (monitor_is_qmp(mon)) { | |
542 | + monitor_data_destroy_qmp(container_of(mon, MonitorQMP, common)); | |
543 | + } else { | |
544 | + readline_free(container_of(mon, MonitorHMP, common)->rs); | |
545 | + } | |
546 | + qobject_unref(mon->outbuf); | |
547 | + qemu_mutex_destroy(&mon->mon_lock); | |
548 | +} | |
549 | + | |
550 | +void monitor_init(Chardev *chr, int flags) | |
551 | +{ | |
552 | + if (flags & MONITOR_USE_CONTROL) { | |
553 | + monitor_init_qmp(chr, flags); | |
554 | + } else { | |
555 | + monitor_init_hmp(chr, flags); | |
556 | + } | |
557 | +} | |
558 | + | |
559 | +void monitor_cleanup(void) | |
560 | +{ | |
561 | + /* | |
562 | + * We need to explicitly stop the I/O thread (but not destroy it), | |
563 | + * clean up the monitor resources, then destroy the I/O thread since | |
564 | + * we need to unregister from chardev below in | |
565 | + * monitor_data_destroy(), and chardev is not thread-safe yet | |
566 | + */ | |
567 | + if (mon_iothread) { | |
568 | + iothread_stop(mon_iothread); | |
569 | + } | |
570 | + | |
571 | + /* Flush output buffers and destroy monitors */ | |
572 | + qemu_mutex_lock(&monitor_lock); | |
573 | + monitor_destroyed = true; | |
574 | + while (!QTAILQ_EMPTY(&mon_list)) { | |
575 | + Monitor *mon = QTAILQ_FIRST(&mon_list); | |
576 | + QTAILQ_REMOVE(&mon_list, mon, entry); | |
577 | + /* Permit QAPI event emission from character frontend release */ | |
578 | + qemu_mutex_unlock(&monitor_lock); | |
579 | + monitor_flush(mon); | |
580 | + monitor_data_destroy(mon); | |
581 | + qemu_mutex_lock(&monitor_lock); | |
582 | + g_free(mon); | |
583 | + } | |
584 | + qemu_mutex_unlock(&monitor_lock); | |
585 | + | |
586 | + /* QEMUBHs needs to be deleted before destroying the I/O thread */ | |
587 | + qemu_bh_delete(qmp_dispatcher_bh); | |
588 | + qmp_dispatcher_bh = NULL; | |
589 | + if (mon_iothread) { | |
590 | + iothread_destroy(mon_iothread); | |
591 | + mon_iothread = NULL; | |
592 | + } | |
593 | +} | |
594 | + | |
595 | +static void monitor_qapi_event_init(void) | |
596 | +{ | |
597 | + monitor_qapi_event_state = g_hash_table_new(qapi_event_throttle_hash, | |
598 | + qapi_event_throttle_equal); | |
599 | +} | |
600 | + | |
601 | +void monitor_init_globals_core(void) | |
602 | +{ | |
603 | + monitor_qapi_event_init(); | |
604 | + qemu_mutex_init(&monitor_lock); | |
605 | + | |
606 | + /* | |
607 | + * The dispatcher BH must run in the main loop thread, since we | |
608 | + * have commands assuming that context. It would be nice to get | |
609 | + * rid of those assumptions. | |
610 | + */ | |
611 | + qmp_dispatcher_bh = aio_bh_new(iohandler_get_aio_context(), | |
612 | + monitor_qmp_bh_dispatcher, | |
613 | + NULL); | |
614 | +} | |
615 | + | |
616 | +QemuOptsList qemu_mon_opts = { | |
617 | + .name = "mon", | |
618 | + .implied_opt_name = "chardev", | |
619 | + .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head), | |
620 | + .desc = { | |
621 | + { | |
622 | + .name = "mode", | |
623 | + .type = QEMU_OPT_STRING, | |
624 | + },{ | |
625 | + .name = "chardev", | |
626 | + .type = QEMU_OPT_STRING, | |
627 | + },{ | |
628 | + .name = "pretty", | |
629 | + .type = QEMU_OPT_BOOL, | |
630 | + }, | |
631 | + { /* end of list */ } | |
632 | + }, | |
633 | +}; |
@@ -3,7 +3,7 @@ | ||
3 | 3 | # hmp.c |
4 | 4 | handle_hmp_command(void *mon, const char *cmdline) "mon %p cmdline: %s" |
5 | 5 | |
6 | -# misc.c | |
6 | +# monitor.c | |
7 | 7 | monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p" |
8 | 8 | monitor_protocol_event_emit(uint32_t event, void *data) "event=%d data=%p" |
9 | 9 | monitor_protocol_event_queue(uint32_t event, void *qdict, uint64_t rate) "event=%d data=%p rate=%" PRId64 |