Commit b6b3ccfd authored by Alex Bennée's avatar Alex Bennée Committed by Paolo Bonzini
Browse files

qom/object: update class cache atomically



The idiom CPU_GET_CLASS(cpu) is fairly extensively used in various
threads and trips of ThreadSanitizer due to the fact it updates
obj->class->object_cast_cache behind the scenes. As this is just a
fast-path cache there is no need to lock updates.

However to ensure defined C11 behaviour across threads we need to use
the plain atomic_read/set primitives and keep the sanitizer happy.

Signed-off-by: default avatarAlex Bennée <alex.bennee@linaro.org>
Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20160930213106.20186-7-alex.bennee@linaro.org>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent f96a8cc3
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -614,7 +614,7 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename,
    Object *inst;

    for (i = 0; obj && i < OBJECT_CLASS_CAST_CACHE; i++) {
        if (obj->class->object_cast_cache[i] == typename) {
        if (atomic_read(&obj->class->object_cast_cache[i]) == typename) {
            goto out;
        }
    }
@@ -631,10 +631,10 @@ Object *object_dynamic_cast_assert(Object *obj, const char *typename,

    if (obj && obj == inst) {
        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
            obj->class->object_cast_cache[i - 1] =
                    obj->class->object_cast_cache[i];
            atomic_set(&obj->class->object_cast_cache[i - 1],
                       atomic_read(&obj->class->object_cast_cache[i]));
        }
        obj->class->object_cast_cache[i - 1] = typename;
        atomic_set(&obj->class->object_cast_cache[i - 1], typename);
    }

out:
@@ -704,7 +704,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
    int i;

    for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) {
        if (class->class_cast_cache[i] == typename) {
        if (atomic_read(&class->class_cast_cache[i]) == typename) {
            ret = class;
            goto out;
        }
@@ -725,9 +725,10 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class,
#ifdef CONFIG_QOM_CAST_DEBUG
    if (class && ret == class) {
        for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) {
            class->class_cast_cache[i - 1] = class->class_cast_cache[i];
            atomic_set(&class->class_cast_cache[i - 1],
                       atomic_read(&class->class_cast_cache[i]));
        }
        class->class_cast_cache[i - 1] = typename;
        atomic_set(&class->class_cast_cache[i - 1], typename);
    }
out:
#endif