diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 70c1591074495e856a9f66dabc52ef281922517e..1ace1a1822495209652e6f1ba4e472023738597d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1770,13 +1770,17 @@ virNodeSuspendGetTargetMask; # virobject.h virClassForObject; +virClassForObjectLockable; virClassIsDerivedFrom; virClassName; virClassNew; virObjectFreeCallback; virObjectIsClass; +virObjectLock; +virObjectLockableNew; virObjectNew; virObjectRef; +virObjectUnlock; virObjectUnref; diff --git a/src/util/virobject.c b/src/util/virobject.c index 5f44ab2d6d5b6632d61d641ae02d7ce18a482a1c..838b5cd46872c05ff18c8a77970eef1c8d49854f 100644 --- a/src/util/virobject.c +++ b/src/util/virobject.c @@ -43,6 +43,9 @@ struct _virClass { }; static virClassPtr virObjectClass; +static virClassPtr virObjectLockableClass; + +static void virObjectLockableDispose(void *anyobj); static int virObjectOnceInit(void) { @@ -52,6 +55,12 @@ static int virObjectOnceInit(void) NULL))) return -1; + if (!(virObjectLockableClass = virClassNew(virObjectClass, + "virObjectLockable", + sizeof(virObjectLockable), + virObjectLockableDispose))) + return -1; + return 0; } @@ -72,6 +81,20 @@ virClassPtr virClassForObject(void) } +/** + * virClassForObjectLockable: + * + * Returns the class instance for the virObjectLockable type + */ +virClassPtr virClassForObjectLockable(void) +{ + if (!virObjectInitialize() < 0) + return NULL; + + return virObjectLockableClass; +} + + /** * virClassNew: * @parent: the parent class @@ -180,6 +203,38 @@ void *virObjectNew(virClassPtr klass) } +void *virObjectLockableNew(virClassPtr klass) +{ + virObjectLockablePtr obj; + + if (!virClassIsDerivedFrom(klass, virClassForObjectLockable())) { + virReportInvalidArg(klass, + _("Class %s must derive from virObjectLockable"), + virClassName(klass)); + return NULL; + } + + if (!(obj = virObjectNew(klass))) + return NULL; + + if (virMutexInit(&obj->lock) < 0) { + virReportSystemError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to initialize mutex")); + virObjectUnref(obj); + return NULL; + } + + return obj; +} + + +static void virObjectLockableDispose(void *anyobj) +{ + virObjectLockablePtr obj = anyobj; + + virMutexDestroy(&obj->lock); +} + /** * virObjectUnref: * @anyobj: any instance of virObjectPtr @@ -209,8 +264,6 @@ bool virObjectUnref(void *anyobj) klass = klass->parent; } - virMutexDestroy(&obj->lock); - /* Clear & poison object */ memset(obj, 0, obj->klass->objectSize); obj->magic = 0xDEADBEEF; @@ -243,6 +296,53 @@ void *virObjectRef(void *anyobj) } +/** + * virObjectLock: + * @anyobj: any instance of virObjectLockablePtr + * + * Acquire a lock on @anyobj. The lock must be + * released by virObjectUnlock. + * + * The caller is expected to have acquired a reference + * on the object before locking it (eg virObjectRef). + * The object must be unlocked before releasing this + * reference. + */ +void virObjectLock(void *anyobj) +{ + virObjectLockablePtr obj = anyobj; + + if (!virObjectIsClass(obj, virObjectLockableClass)) { + VIR_WARN("Object %p (%s) is not a virObjectLockable instance", + obj, obj ? obj->parent.klass->name : "(unknown)"); + return; + } + + virMutexLock(&obj->lock); +} + + +/** + * virObjectUnlock: + * @anyobj: any instance of virObjectLockablePtr + * + * Release a lock on @anyobj. The lock must have been + * acquired by virObjectLock. + */ +void virObjectUnlock(void *anyobj) +{ + virObjectLockablePtr obj = anyobj; + + if (!virObjectIsClass(obj, virObjectLockableClass)) { + VIR_WARN("Object %p (%s) is not a virObjectLockable instance", + obj, obj ? obj->parent.klass->name : "(unknown)"); + return; + } + + virMutexUnlock(&obj->lock); +} + + /** * virObjectIsClass: * @anyobj: any instance of virObjectPtr diff --git a/src/util/virobject.h b/src/util/virobject.h index afeb4f56266bb2eed7eea7bb5801e05a532a7c51..bb72a25bc37e56f20ad57289567f7fdc5e5d43d4 100644 --- a/src/util/virobject.h +++ b/src/util/virobject.h @@ -23,6 +23,7 @@ # define __VIR_OBJECT_H__ # include "internal.h" +# include "virthread.h" typedef struct _virClass virClass; typedef virClass *virClassPtr; @@ -30,6 +31,9 @@ typedef virClass *virClassPtr; typedef struct _virObject virObject; typedef virObject *virObjectPtr; +typedef struct _virObjectLockable virObjectLockable; +typedef virObjectLockable *virObjectLockablePtr; + typedef void (*virObjectDisposeCallback)(void *obj); struct _virObject { @@ -38,7 +42,14 @@ struct _virObject { virClassPtr klass; }; +struct _virObjectLockable { + virObject parent; + virMutex lock; +}; + + virClassPtr virClassForObject(void); +virClassPtr virClassForObjectLockable(void); virClassPtr virClassNew(virClassPtr parent, const char *name, @@ -64,4 +75,13 @@ bool virObjectIsClass(void *obj, void virObjectFreeCallback(void *opaque); +void *virObjectLockableNew(virClassPtr klass) + ATTRIBUTE_NONNULL(1); + +void virObjectLock(void *lockableobj) + ATTRIBUTE_NONNULL(1); +void virObjectUnlock(void *lockableobj) + ATTRIBUTE_NONNULL(1); + + #endif /* __VIR_OBJECT_H */