mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-22 05:30:24 +00:00
Subject: DM: virtio-heci: Use atomic_xchange in client get/put
With rare probability, the two threads may try to get&put client together. For client getting, the subsequent thread will get one destroyed client. For client putting, it will cause acrn-dm get crashed due to assert be triggered in virtio_heci_client_put. Signed-off-by: Long Liu <long.liu@intel.com> Reviewed-by: Shuo Liu <shuo.a.liu@intel.com> Reviewed-by: Yu Wang <yu1.wang@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
df2d925a27
commit
5ed3dbf93c
@ -211,8 +211,23 @@ err_to_native_heci_resno(int err)
|
|||||||
static struct virtio_heci_client *
|
static struct virtio_heci_client *
|
||||||
virtio_heci_client_get(struct virtio_heci_client *client)
|
virtio_heci_client_get(struct virtio_heci_client *client)
|
||||||
{
|
{
|
||||||
if (__sync_fetch_and_add(&client->ref, 1) == 0)
|
int new, val;
|
||||||
return NULL;
|
|
||||||
|
/*
|
||||||
|
* The active_clients be protected by list_mutex
|
||||||
|
* so the client never be null
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
val = *(volatile int *)&client->ref;
|
||||||
|
if (val == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
new = val + 1;
|
||||||
|
|
||||||
|
/* check for overflow */
|
||||||
|
assert(new > 0);
|
||||||
|
|
||||||
|
} while (!__sync_bool_compare_and_swap(&client->ref, val, new));
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,8 +235,18 @@ static void
|
|||||||
virtio_heci_client_put(struct virtio_heci *vheci,
|
virtio_heci_client_put(struct virtio_heci *vheci,
|
||||||
struct virtio_heci_client *client)
|
struct virtio_heci_client *client)
|
||||||
{
|
{
|
||||||
assert(client->ref > 0);
|
int new, val;
|
||||||
if (__sync_sub_and_fetch(&client->ref, 1) == 0)
|
|
||||||
|
do {
|
||||||
|
val = *(volatile int *)&client->ref;
|
||||||
|
if (val == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
new = val - 1;
|
||||||
|
|
||||||
|
} while (!__sync_bool_compare_and_swap(&client->ref, val, new));
|
||||||
|
|
||||||
|
if (client->ref == 0)
|
||||||
virtio_heci_destroy_client(vheci, client);
|
virtio_heci_destroy_client(vheci, client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user