]> xenbits.xensource.com Git - people/dariof/libvirt.git/commitdiff
object: require maximal alignment in base class
authorEric Blake <eblake@redhat.com>
Thu, 12 Dec 2013 23:01:15 +0000 (16:01 -0700)
committerEric Blake <eblake@redhat.com>
Fri, 13 Dec 2013 12:59:38 +0000 (05:59 -0700)
Recent changes to events (commit 8a29ffcf) resulted in new compile
failures on some targets (such as ARM OMAP5):
conf/domain_event.c: In function 'virDomainEventDispatchDefaultFunc':
conf/domain_event.c:1198:30: error: cast increases required alignment of
target type [-Werror=cast-align]
conf/domain_event.c:1314:34: error: cast increases required alignment of
target type [-Werror=cast-align]
cc1: all warnings being treated as errors

The error is due to alignment; the base class is merely aligned
to the worst of 'int' and 'void*', while the child class must
be aligned to a 'long long'.  The solution is to include a
'long long' (and for good measure, a function pointer) in the
base class to ensure correct alignment regardless of what a
child class may add, but to wrap the inclusion in a union so
as to not incur any wasted space.  On a typical x86_64 platform,
the base class remains 16 bytes; on i686, the base class remains
12 bytes; and on the impacted ARM platform, the base class grows
from 12 bytes to 16 bytes due to the increase of alignment from
4 to 8 bytes.

Reported by Michele Paolino and others.

* src/util/virobject.h (_virObject): Use a union to ensure that
subclasses never have stricter alignment than the parent.
* src/util/virobject.c (virObjectNew, virObjectUnref)
(virObjectRef): Adjust clients.
* src/libvirt.c (virConnectRef, virDomainRef, virNetworkRef)
(virInterfaceRef, virStoragePoolRef, virStorageVolRef)
(virNodeDeviceRef, virSecretRef, virStreamRef, virNWFilterRef)
(virDomainSnapshotRef): Likewise.
* src/qemu/qemu_monitor.c (qemuMonitorOpenInternal)
(qemuMonitorClose): Likewise.

Signed-off-by: Eric Blake <eblake@redhat.com>
src/libvirt.c
src/qemu/qemu_monitor.c
src/util/virobject.c
src/util/virobject.h

index f01de83455a7c7a3f244f30189e5f568d7013175..d15d6179cb0f60fe151f29d43cb4c5c22bec4f73 100644 (file)
@@ -1563,7 +1563,7 @@ virConnectRef(virConnectPtr conn)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("conn=%p refs=%d", conn, conn->object.refs);
+    VIR_DEBUG("conn=%p refs=%d", conn, conn->object.u.s.refs);
     virObjectRef(conn);
     return 0;
 }
@@ -2469,7 +2469,7 @@ virDomainRef(virDomainPtr domain)
         return -1;
     }
 
-    VIR_DOMAIN_DEBUG(domain, "refs=%d", domain->object.refs);
+    VIR_DOMAIN_DEBUG(domain, "refs=%d", domain->object.u.s.refs);
     virObjectRef(domain);
     return 0;
 }
@@ -11977,7 +11977,7 @@ virNetworkRef(virNetworkPtr network)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("network=%p refs=%d", network, network->object.refs);
+    VIR_DEBUG("network=%p refs=%d", network, network->object.u.s.refs);
     virObjectRef(network);
     return 0;
 }
@@ -12921,7 +12921,7 @@ virInterfaceRef(virInterfacePtr iface)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("iface=%p refs=%d", iface, iface->object.refs);
+    VIR_DEBUG("iface=%p refs=%d", iface, iface->object.u.s.refs);
     virObjectRef(iface);
     return 0;
 }
@@ -13980,7 +13980,7 @@ virStoragePoolRef(virStoragePoolPtr pool)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("pool=%p refs=%d", pool, pool->object.refs);
+    VIR_DEBUG("pool=%p refs=%d", pool, pool->object.u.s.refs);
     virObjectRef(pool);
     return 0;
 }
@@ -15101,7 +15101,7 @@ virStorageVolRef(virStorageVolPtr vol)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("vol=%p refs=%d", vol, vol->object.refs);
+    VIR_DEBUG("vol=%p refs=%d", vol, vol->object.u.s.refs);
     virObjectRef(vol);
     return 0;
 }
@@ -15792,7 +15792,7 @@ virNodeDeviceRef(virNodeDevicePtr dev)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("dev=%p refs=%d", dev, dev->object.refs);
+    VIR_DEBUG("dev=%p refs=%d", dev, dev->object.u.s.refs);
     virObjectRef(dev);
     return 0;
 }
@@ -16900,7 +16900,7 @@ virSecretRef(virSecretPtr secret)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("secret=%p refs=%d", secret, secret->object.refs);
+    VIR_DEBUG("secret=%p refs=%d", secret, secret->object.u.s.refs);
     virObjectRef(secret);
     return 0;
 }
@@ -16994,7 +16994,7 @@ virStreamRef(virStreamPtr stream)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("stream=%p refs=%d", stream, stream->object.refs);
+    VIR_DEBUG("stream=%p refs=%d", stream, stream->object.u.s.refs);
     virObjectRef(stream);
     return 0;
 }
@@ -18400,7 +18400,7 @@ virNWFilterRef(virNWFilterPtr nwfilter)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("nwfilter=%p refs=%d", nwfilter, nwfilter->object.refs);
+    VIR_DEBUG("nwfilter=%p refs=%d", nwfilter, nwfilter->object.u.s.refs);
     virObjectRef(nwfilter);
     return 0;
 }
@@ -20699,7 +20699,7 @@ virDomainSnapshotRef(virDomainSnapshotPtr snapshot)
         virDispatchError(NULL);
         return -1;
     }
-    VIR_DEBUG("snapshot=%p, refs=%d", snapshot, snapshot->object.refs);
+    VIR_DEBUG("snapshot=%p, refs=%d", snapshot, snapshot->object.u.s.refs);
     virObjectRef(snapshot);
     return 0;
 }
index 1514715d0e46e0b022f1d9bd823cf53d550d6937..1fa14921cba9dcac4cad2775ce4da9999de7bd26 100644 (file)
@@ -821,7 +821,7 @@ qemuMonitorOpenInternal(virDomainObjPtr vm,
 
     PROBE(QEMU_MONITOR_NEW,
           "mon=%p refs=%d fd=%d",
-          mon, mon->parent.parent.refs, mon->fd);
+          mon, mon->parent.parent.u.s.refs, mon->fd);
     virObjectUnlock(mon);
 
     return mon;
@@ -893,7 +893,7 @@ void qemuMonitorClose(qemuMonitorPtr mon)
 
     virObjectLock(mon);
     PROBE(QEMU_MONITOR_CLOSE,
-          "mon=%p refs=%d", mon, mon->parent.parent.refs);
+          "mon=%p refs=%d", mon, mon->parent.parent.u.s.refs);
 
     if (mon->fd >= 0) {
         if (mon->watch) {
index 61b541369abc5407856c951742b2497a0f356c72..4f83bc1cb5aa2efd8b9e92ec08830ff3f7b6fb72 100644 (file)
@@ -192,9 +192,9 @@ void *virObjectNew(virClassPtr klass)
                       klass->objectSize - sizeof(virObject)) < 0)
         return NULL;
 
-    obj->magic = klass->magic;
+    obj->u.s.magic = klass->magic;
     obj->klass = klass;
-    virAtomicIntSet(&obj->refs, 1);
+    virAtomicIntSet(&obj->u.s.refs, 1);
 
     PROBE(OBJECT_NEW, "obj=%p classname=%s", obj, obj->klass->name);
 
@@ -252,7 +252,7 @@ bool virObjectUnref(void *anyobj)
     if (!obj)
         return false;
 
-    bool lastRef = virAtomicIntDecAndTest(&obj->refs);
+    bool lastRef = virAtomicIntDecAndTest(&obj->u.s.refs);
     PROBE(OBJECT_UNREF, "obj=%p", obj);
     if (lastRef) {
         PROBE(OBJECT_DISPOSE, "obj=%p", obj);
@@ -265,7 +265,7 @@ bool virObjectUnref(void *anyobj)
 
         /* Clear & poison object */
         memset(obj, 0, obj->klass->objectSize);
-        obj->magic = 0xDEADBEEF;
+        obj->u.s.magic = 0xDEADBEEF;
         obj->klass = (void*)0xDEADBEEF;
         VIR_FREE(obj);
     }
@@ -289,7 +289,7 @@ void *virObjectRef(void *anyobj)
 
     if (!obj)
         return NULL;
-    virAtomicIntInc(&obj->refs);
+    virAtomicIntInc(&obj->u.s.refs);
     PROBE(OBJECT_REF, "obj=%p", obj);
     return anyobj;
 }
index 3a08f10d050def5e909d21f48de1dee470307223..d571b5cedc18860283c3048ad857eded3d4f4d43 100644 (file)
@@ -36,9 +36,21 @@ typedef virObjectLockable *virObjectLockablePtr;
 
 typedef void (*virObjectDisposeCallback)(void *obj);
 
+/* Most code should not play with the contents of this struct; however,
+ * the struct itself is public so that it can be embedded as the first
+ * field of a subclassed object.  */
 struct _virObject {
-    unsigned int magic;
-    int refs;
+    /* Ensure correct alignment of this and all subclasses, even on
+     * platforms where 'long long' or function pointers have stricter
+     * requirements than 'void *'.  */
+    union {
+        long long dummy_align1;
+        void (*dummy_align2) (void);
+        struct {
+            unsigned int magic;
+            int refs;
+        } s;
+    } u;
     virClassPtr klass;
 };