diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c index d9934b5b9c0748acd1681abfd472aba13447dd18..a22b155b6f98ab0341219394fb209a1c3ec2e7f2 100644 --- a/hw/qdev-properties-system.c +++ b/hw/qdev-properties-system.c @@ -123,11 +123,10 @@ static int parse_chr(DeviceState *dev, const char *str, void **ptr) if (chr == NULL) { return -ENOENT; } - if (chr->avail_connections < 1) { + if (qemu_chr_fe_claim(chr) != 0) { return -EEXIST; } *ptr = chr; - --chr->avail_connections; return 0; } @@ -140,7 +139,7 @@ static void release_chr(Object *obj, const char *name, void *opaque) if (chr) { qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL); - ++chr->avail_connections; + qemu_chr_fe_release(chr); } } diff --git a/include/char/char.h b/include/char/char.h index 32c9999113a08a28157a41a23b97db75eb9a4727..9d1ea46117b3e8ae23a5efc5fb1351bddad0167e 100644 --- a/include/char/char.h +++ b/include/char/char.h @@ -202,6 +202,35 @@ int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg); */ int qemu_chr_fe_get_msgfd(CharDriverState *s); +/** + * @qemu_chr_fe_claim: + * + * Claim a backend before using it, should be called before calling + * qemu_chr_add_handlers(). + * + * Returns: -1 if the backend is already in use by another frontend, 0 on + * success. + */ +int qemu_chr_fe_claim(CharDriverState *s); + +/** + * @qemu_chr_fe_claim_no_fail: + * + * Like qemu_chr_fe_claim, but will exit qemu with an error when the + * backend is already in use. + */ +void qemu_chr_fe_claim_no_fail(CharDriverState *s); + +/** + * @qemu_chr_fe_claim: + * + * Release a backend for use by another frontend. + * + * Returns: -1 if the backend is already in use by another frontend, 0 on + * success. + */ +void qemu_chr_fe_release(CharDriverState *s); + /** * @qemu_chr_be_can_write: * diff --git a/qemu-char.c b/qemu-char.c index 505a773330fda0e4a08f75f659726c010049daed..100f9a968ccdc9dbc2af34c95236ae12cffffcd8 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -3452,6 +3452,29 @@ int qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond, return tag; } +int qemu_chr_fe_claim(CharDriverState *s) +{ + if (s->avail_connections < 1) { + return -1; + } + s->avail_connections--; + return 0; +} + +void qemu_chr_fe_claim_no_fail(CharDriverState *s) +{ + if (qemu_chr_fe_claim(s) != 0) { + fprintf(stderr, "%s: error chardev \"%s\" already used\n", + __func__, s->label); + exit(1); + } +} + +void qemu_chr_fe_release(CharDriverState *s) +{ + s->avail_connections++; +} + void qemu_chr_delete(CharDriverState *chr) { QTAILQ_REMOVE(&chardevs, chr, next);