[libvirt] [PATCH 2/3] virobject: Introduce virObjectRWLockable
Pavel Hrdina
phrdina at redhat.com
Mon Jul 24 13:13:33 UTC 2017
On Wed, Jul 19, 2017 at 04:31:49PM +0200, Michal Privoznik wrote:
> Up until now we only had virObjectLockable which uses mutexes for
> mutually excluding each other in critical section. Well, this is
> not enough. Future work will require RW locks so we might as well
> have virObjectRWLockable which is introduced here.
>
> Moreover, polymorphism is introduced to our code for the first
> time. Yay! More specifically, virObjectLock will grab a write
> lock, virObjectLockRead will grab a read lock then (what a
> surprise right?). This has great advantage that an object can be
> made derived from virObjectRWLockable in a single line and still
> continue functioning properly (mutexes can be viewed as grabbing
> write locks only). Then just those critical sections that can
> grab a read lock need fixing. Therefore the resulting change is
> going to be way smaller.
>
> In order to avoid writer starvation, the object initializes RW
> lock that prefers writers.
>
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
> src/libvirt_private.syms | 3 +
> src/util/virobject.c | 144 ++++++++++++++++++++++++++++++++++++-----------
> src/util/virobject.h | 16 ++++++
> 3 files changed, 131 insertions(+), 32 deletions(-)
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index a792e00c8..f9df35583 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -2282,6 +2282,7 @@ virNumaSetupMemoryPolicy;
> # util/virobject.h
> virClassForObject;
> virClassForObjectLockable;
> +virClassForObjectRWLockable;
> virClassIsDerivedFrom;
> virClassName;
> virClassNew;
> @@ -2292,8 +2293,10 @@ virObjectListFree;
> virObjectListFreeCount;
> virObjectLock;
> virObjectLockableNew;
> +virObjectLockRead;
> virObjectNew;
> virObjectRef;
> +virObjectRWLockableNew;
> virObjectUnlock;
> virObjectUnref;
>
> diff --git a/src/util/virobject.c b/src/util/virobject.c
> index 34805d34a..3e7a0719e 100644
> --- a/src/util/virobject.c
> +++ b/src/util/virobject.c
> @@ -49,8 +49,10 @@ struct _virClass {
>
> static virClassPtr virObjectClass;
> static virClassPtr virObjectLockableClass;
> +static virClassPtr virObjectRWLockableClass;
>
> static void virObjectLockableDispose(void *anyobj);
> +static void virObjectRWLockableDispose(void *anyobj);
>
> static int
> virObjectOnceInit(void)
> @@ -67,6 +69,12 @@ virObjectOnceInit(void)
> virObjectLockableDispose)))
> return -1;
>
> + if (!(virObjectRWLockableClass = virClassNew(virObjectClass,
> + "virObjectRWLockable",
> + sizeof(virObjectRWLockable),
> + virObjectRWLockableDispose)))
> + return -1;
> +
> return 0;
> }
>
> @@ -103,6 +111,20 @@ virClassForObjectLockable(void)
> }
>
>
> +/**
> + * virClassForObjectRWLockable:
> + *
> + * Returns the class instance for the virObjectRWLockable type
> + */
> +virClassPtr
> +virClassForObjectRWLockable(void)
> +{
> + if (virObjectInitialize() < 0)
> + return NULL;
> +
> + return virObjectRWLockableClass;
> +}
> +
There should be two empty lines.
> /**
> * virClassNew:
> * @parent: the parent class
> @@ -237,6 +259,32 @@ virObjectLockableNew(virClassPtr klass)
> }
>
>
> +void *
> +virObjectRWLockableNew(virClassPtr klass)
> +{
> + virObjectRWLockablePtr obj;
> +
> + if (!virClassIsDerivedFrom(klass, virClassForObjectRWLockable())) {
> + virReportInvalidArg(klass,
> + _("Class %s must derive from virObjectRWLockable"),
> + virClassName(klass));
> + return NULL;
> + }
> +
> + if (!(obj = virObjectNew(klass)))
> + return NULL;
> +
> + if (virRWLockInitPreferWriter(&obj->lock) < 0) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Unable to initialize RW lock"));
> + virObjectUnref(obj);
> + return NULL;
> + }
> +
> + return obj;
> +}
> +
> +
> static void
> virObjectLockableDispose(void *anyobj)
> {
> @@ -246,6 +294,15 @@ virObjectLockableDispose(void *anyobj)
> }
>
>
> +static void
> +virObjectRWLockableDispose(void *anyobj)
> +{
> + virObjectRWLockablePtr obj = anyobj;
> +
> + virRWLockDestroy(&obj->lock);
> +}
> +
> +
> /**
> * virObjectUnref:
> * @anyobj: any instance of virObjectPtr
> @@ -309,28 +366,13 @@ virObjectRef(void *anyobj)
> }
>
>
> -static virObjectLockablePtr
> -virObjectGetLockableObj(void *anyobj)
> -{
> - virObjectPtr obj;
> -
> - if (virObjectIsClass(anyobj, virObjectLockableClass))
> - return anyobj;
> -
> - obj = anyobj;
> - VIR_WARN("Object %p (%s) is not a virObjectLockable instance",
> - anyobj, obj ? obj->klass->name : "(unknown)");
> -
> - return NULL;
> -}
> -
> -
> /**
> * virObjectLock:
> - * @anyobj: any instance of virObjectLockablePtr
> + * @anyobj: any instance of virObjectLockable or virObjectRWLockable
> *
> - * Acquire a lock on @anyobj. The lock must be
> - * released by virObjectUnlock.
> + * Acquire a lock on @anyobj. The lock must be released by
> + * virObjectUnlock. In case the passed object is instance of
> + * virObjectRWLockable a write lock is acquired.
> *
> * The caller is expected to have acquired a reference
> * on the object before locking it (eg virObjectRef).
> @@ -340,31 +382,69 @@ virObjectGetLockableObj(void *anyobj)
> void
> virObjectLock(void *anyobj)
> {
> - virObjectLockablePtr obj = virObjectGetLockableObj(anyobj);
> + if (virObjectIsClass(anyobj, virObjectLockableClass)) {
> + virObjectLockablePtr obj = anyobj;
> + virMutexLock(&obj->lock);
> + } else if (virObjectIsClass(anyobj, virObjectRWLockableClass)) {
> + virObjectRWLockablePtr obj = anyobj;
> + virRWLockWrite(&obj->lock);
> + } else {
> + virObjectPtr obj = anyobj;
> + VIR_WARN("Object %p (%s) is not a virObjectLockable "
> + "nor virObjectRWLockable instance",
> + anyobj, obj ? obj->klass->name : "(unknown)");
> + }
> +}
>
> - if (!obj)
> - return;
>
> - virMutexLock(&obj->lock);
> +/**
> + * virObjectLockRead:
> + * @anyobj: any instance of virObjectRWLockablePtr
s/virObjectRWLockablePtr/virObjectRWLockable/
Reviewed-by: Pavel Hrdina <phrdina at redhat.com>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20170724/268dbe3b/attachment-0001.sig>
More information about the libvir-list
mailing list