util/async: add a human-readable name to BHs for debugging
It can be difficult to debug issues with BHs in production environments. Although BHs can usually be identified by looking up their ->cb() function pointer, this requires debug information for the program. It is also not possible to print human-readable diagnostics about BHs because they have no identifier. This patch adds a name to each BH. The name is not unique per instance but differentiates between cb() functions, which is usually enough. It's done by changing aio_bh_new() and friends to macros that stringify cb. The next patch will use the name field when reporting leaked BHs. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Message-Id: <20210414200247.917496-2-stefanha@redhat.com>
This commit is contained in:
parent
711c0418c8
commit
0f08586c71
@ -292,19 +292,44 @@ void aio_context_acquire(AioContext *ctx);
|
|||||||
void aio_context_release(AioContext *ctx);
|
void aio_context_release(AioContext *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run
|
* aio_bh_schedule_oneshot_full: Allocate a new bottom half structure that will
|
||||||
* only once and as soon as possible.
|
* run only once and as soon as possible.
|
||||||
|
*
|
||||||
|
* @name: A human-readable identifier for debugging purposes.
|
||||||
*/
|
*/
|
||||||
void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
|
void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aio_bh_new: Allocate a new bottom half structure.
|
* aio_bh_schedule_oneshot: Allocate a new bottom half structure that will run
|
||||||
|
* only once and as soon as possible.
|
||||||
|
*
|
||||||
|
* A convenience wrapper for aio_bh_schedule_oneshot_full() that uses cb as the
|
||||||
|
* name string.
|
||||||
|
*/
|
||||||
|
#define aio_bh_schedule_oneshot(ctx, cb, opaque) \
|
||||||
|
aio_bh_schedule_oneshot_full((ctx), (cb), (opaque), (stringify(cb)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aio_bh_new_full: Allocate a new bottom half structure.
|
||||||
*
|
*
|
||||||
* Bottom halves are lightweight callbacks whose invocation is guaranteed
|
* Bottom halves are lightweight callbacks whose invocation is guaranteed
|
||||||
* to be wait-free, thread-safe and signal-safe. The #QEMUBH structure
|
* to be wait-free, thread-safe and signal-safe. The #QEMUBH structure
|
||||||
* is opaque and must be allocated prior to its use.
|
* is opaque and must be allocated prior to its use.
|
||||||
|
*
|
||||||
|
* @name: A human-readable identifier for debugging purposes.
|
||||||
*/
|
*/
|
||||||
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque);
|
QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aio_bh_new: Allocate a new bottom half structure
|
||||||
|
*
|
||||||
|
* A convenience wrapper for aio_bh_new_full() that uses the cb as the name
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
#define aio_bh_new(ctx, cb, opaque) \
|
||||||
|
aio_bh_new_full((ctx), (cb), (opaque), (stringify(cb)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* aio_notify: Force processing of pending events.
|
* aio_notify: Force processing of pending events.
|
||||||
|
@ -294,7 +294,9 @@ void qemu_cond_timedwait_iothread(QemuCond *cond, int ms);
|
|||||||
|
|
||||||
void qemu_fd_register(int fd);
|
void qemu_fd_register(int fd);
|
||||||
|
|
||||||
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque);
|
#define qemu_bh_new(cb, opaque) \
|
||||||
|
qemu_bh_new_full((cb), (opaque), (stringify(cb)))
|
||||||
|
QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name);
|
||||||
void qemu_bh_schedule_idle(QEMUBH *bh);
|
void qemu_bh_schedule_idle(QEMUBH *bh);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -108,7 +108,7 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
|
|||||||
return deadline;
|
return deadline;
|
||||||
}
|
}
|
||||||
|
|
||||||
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
|
QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
|
||||||
{
|
{
|
||||||
QEMUBH *bh = g_new(QEMUBH, 1);
|
QEMUBH *bh = g_new(QEMUBH, 1);
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ enum {
|
|||||||
|
|
||||||
struct QEMUBH {
|
struct QEMUBH {
|
||||||
AioContext *ctx;
|
AioContext *ctx;
|
||||||
|
const char *name;
|
||||||
QEMUBHFunc *cb;
|
QEMUBHFunc *cb;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
QSLIST_ENTRY(QEMUBH) next;
|
QSLIST_ENTRY(QEMUBH) next;
|
||||||
@ -107,7 +108,8 @@ static QEMUBH *aio_bh_dequeue(BHList *head, unsigned *flags)
|
|||||||
return bh;
|
return bh;
|
||||||
}
|
}
|
||||||
|
|
||||||
void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
|
void aio_bh_schedule_oneshot_full(AioContext *ctx, QEMUBHFunc *cb,
|
||||||
|
void *opaque, const char *name)
|
||||||
{
|
{
|
||||||
QEMUBH *bh;
|
QEMUBH *bh;
|
||||||
bh = g_new(QEMUBH, 1);
|
bh = g_new(QEMUBH, 1);
|
||||||
@ -115,11 +117,13 @@ void aio_bh_schedule_oneshot(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
|
|||||||
.ctx = ctx,
|
.ctx = ctx,
|
||||||
.cb = cb,
|
.cb = cb,
|
||||||
.opaque = opaque,
|
.opaque = opaque,
|
||||||
|
.name = name,
|
||||||
};
|
};
|
||||||
aio_bh_enqueue(bh, BH_SCHEDULED | BH_ONESHOT);
|
aio_bh_enqueue(bh, BH_SCHEDULED | BH_ONESHOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
|
QEMUBH *aio_bh_new_full(AioContext *ctx, QEMUBHFunc *cb, void *opaque,
|
||||||
|
const char *name)
|
||||||
{
|
{
|
||||||
QEMUBH *bh;
|
QEMUBH *bh;
|
||||||
bh = g_new(QEMUBH, 1);
|
bh = g_new(QEMUBH, 1);
|
||||||
@ -127,6 +131,7 @@ QEMUBH *aio_bh_new(AioContext *ctx, QEMUBHFunc *cb, void *opaque)
|
|||||||
.ctx = ctx,
|
.ctx = ctx,
|
||||||
.cb = cb,
|
.cb = cb,
|
||||||
.opaque = opaque,
|
.opaque = opaque,
|
||||||
|
.name = name,
|
||||||
};
|
};
|
||||||
return bh;
|
return bh;
|
||||||
}
|
}
|
||||||
|
@ -544,9 +544,9 @@ void main_loop_wait(int nonblocking)
|
|||||||
|
|
||||||
/* Functions to operate on the main QEMU AioContext. */
|
/* Functions to operate on the main QEMU AioContext. */
|
||||||
|
|
||||||
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
|
QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name)
|
||||||
{
|
{
|
||||||
return aio_bh_new(qemu_aio_context, cb, opaque);
|
return aio_bh_new_full(qemu_aio_context, cb, opaque, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user