util: Introduce and use virObjectRWLockWrite

Instead of making virObjectLock be the entry point for two
different types of locks, let's create a virObjectRWLockWrite API
which will only handle the virObjectRWLockableClass objects.

Use the new virObjectRWLockWrite for the virdomainobjlist code
in order to handle the Add, Remove, Rename, and Load operations
that need to be very synchronous.

Signed-off-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
John Ferlan 2017-07-28 10:06:55 -04:00
parent 99a72b3eb4
commit 908b33644e
4 changed files with 41 additions and 5 deletions

View File

@ -327,7 +327,7 @@ virDomainObjPtr virDomainObjListAdd(virDomainObjListPtr doms,
{
virDomainObjPtr ret;
virObjectLock(doms);
virObjectRWLockWrite(doms);
ret = virDomainObjListAddLocked(doms, def, xmlopt, flags, oldDef);
virObjectUnlock(doms);
return ret;
@ -349,7 +349,7 @@ void virDomainObjListRemove(virDomainObjListPtr doms,
virObjectRef(dom);
virObjectUnlock(dom);
virObjectLock(doms);
virObjectRWLockWrite(doms);
virObjectLock(dom);
virHashRemoveEntry(doms->objs, uuidstr);
virHashRemoveEntry(doms->objsName, dom->def->name);
@ -394,7 +394,7 @@ virDomainObjListRename(virDomainObjListPtr doms,
* hold a lock on dom but not refcount it. */
virObjectRef(dom);
virObjectUnlock(dom);
virObjectLock(doms);
virObjectRWLockWrite(doms);
virObjectLock(dom);
virObjectUnref(dom);
@ -573,7 +573,7 @@ virDomainObjListLoadAllConfigs(virDomainObjListPtr doms,
if ((rc = virDirOpenIfExists(&dir, configDir)) <= 0)
return rc;
virObjectLock(doms);
virObjectRWLockWrite(doms);
while ((ret = virDirRead(dir, &entry, configDir)) > 0) {
virDomainObjPtr dom;

View File

@ -2312,6 +2312,7 @@ virObjectNew;
virObjectRef;
virObjectRWLockableNew;
virObjectRWLockRead;
virObjectRWLockWrite;
virObjectUnlock;
virObjectUnref;

View File

@ -429,12 +429,43 @@ virObjectRWLockRead(void *anyobj)
}
/**
* virObjectRWLockWrite:
* @anyobj: any instance of virObjectRWLockable
*
* Acquire a write 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.
*
* NB: It's possible to return without the lock if
* @anyobj was invalid - this has been considered
* a programming error rather than something that
* should be checked.
*/
void
virObjectRWLockWrite(void *anyobj)
{
if (virObjectIsClass(anyobj, virObjectRWLockableClass)) {
virObjectRWLockablePtr obj = anyobj;
virRWLockWrite(&obj->lock);
} else {
virObjectPtr obj = anyobj;
VIR_WARN("Object %p (%s) is not a virObjectRWLockable instance",
anyobj, obj ? obj->klass->name : "(unknown)");
}
}
/**
* virObjectUnlock:
* @anyobj: any instance of virObjectLockable or virObjectRWLockable
*
* Release a lock on @anyobj. The lock must have been acquired by
* virObjectLock or virObjectRWLockRead.
* virObjectLock, virObjectRWLockRead, or virObjectRWLockWrite.
*/
void
virObjectUnlock(void *anyobj)

View File

@ -128,6 +128,10 @@ void
virObjectRWLockRead(void *lockableobj)
ATTRIBUTE_NONNULL(1);
void
virObjectRWLockWrite(void *lockableobj)
ATTRIBUTE_NONNULL(1);
void
virObjectUnlock(void *lockableobj)
ATTRIBUTE_NONNULL(1);