Skip to content

Commit 5ed3dbf

Browse files
liudlongjren1
authored andcommitted
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>
1 parent df2d925 commit 5ed3dbf

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

devicemodel/hw/pci/virtio/virtio_heci.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,17 +211,42 @@ err_to_native_heci_resno(int err)
211211
static struct virtio_heci_client *
212212
virtio_heci_client_get(struct virtio_heci_client *client)
213213
{
214-
if (__sync_fetch_and_add(&client->ref, 1) == 0)
215-
return NULL;
214+
int new, val;
215+
216+
/*
217+
* The active_clients be protected by list_mutex
218+
* so the client never be null
219+
*/
220+
do {
221+
val = *(volatile int *)&client->ref;
222+
if (val == 0)
223+
return NULL;
224+
225+
new = val + 1;
226+
227+
/* check for overflow */
228+
assert(new > 0);
229+
230+
} while (!__sync_bool_compare_and_swap(&client->ref, val, new));
216231
return client;
217232
}
218233

219234
static void
220235
virtio_heci_client_put(struct virtio_heci *vheci,
221236
struct virtio_heci_client *client)
222237
{
223-
assert(client->ref > 0);
224-
if (__sync_sub_and_fetch(&client->ref, 1) == 0)
238+
int new, val;
239+
240+
do {
241+
val = *(volatile int *)&client->ref;
242+
if (val == 0)
243+
return;
244+
245+
new = val - 1;
246+
247+
} while (!__sync_bool_compare_and_swap(&client->ref, val, new));
248+
249+
if (client->ref == 0)
225250
virtio_heci_destroy_client(vheci, client);
226251
}
227252

0 commit comments

Comments
 (0)