dm: mei: Use compare and swap primitive for refcnt.

Simple atomic add/dec do no guarantee reference count full
synchronization without a lock. Compare and swap operations
are required for correct implementation.

Tracked-On: #1875
Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Acked-by: Yin Fengwei <fengwei.yin@intel.com>
This commit is contained in:
Tomas Winkler 2018-11-22 10:14:47 +02:00 committed by lijinxia
parent b1047224aa
commit 580579a392
1 changed files with 30 additions and 4 deletions

View File

@ -140,16 +140,43 @@ struct refcnt {
int count;
};
static inline void
static inline int atomic_read(const struct refcnt *ref)
{
return *(volatile int *)&ref->count;
}
static inline int
refcnt_get(const struct refcnt *ref)
{
__sync_add_and_fetch((int *)&ref->count, 1);
int new, val;
do {
val = atomic_read(ref);
if (val == 0)
return 0;
new = val + 1;
/* check for overflow */
assert(new > 0);
} while (!__sync_bool_compare_and_swap((int *)&ref->count, val, new));
return new;
}
static inline void
refcnt_put(const struct refcnt *ref)
{
if (__sync_sub_and_fetch((int *)&ref->count, 1) == 0)
int new, val;
do {
val = atomic_read(ref);
if (val == 0)
return;
new = val - 1;
} while (!__sync_bool_compare_and_swap((int *)&ref->count, val, new));
if (new == 0)
ref->destroy(ref);
}
@ -803,7 +830,6 @@ static int vmei_me_client_scan_list(struct virtio_mei *vmei)
if (ent->d_type == DT_DIR &&
is_prefix("mei::", ent->d_name, DEV_NAME_SIZE)) {
struct mei_client_properties props;
memset(&props, 0, sizeof(props));