memory: gst_memory_share may fail to exclusively lock the parent memory

Now that locking exclusively dows not always succeed, we need to signal
the failure case from gst_memory_init.

Rather than introducing an API or funcionality change to gst_memory_init,
workaround by checking exclusivity in the calling code.

https://bugzilla.gnome.org/show_bug.cgi?id=750172
This commit is contained in:
Matthew Waters 2015-06-02 16:14:50 +10:00
parent eb71ee4040
commit e9c15d5321
2 changed files with 28 additions and 0 deletions

View file

@ -123,6 +123,7 @@ gst_memory_init (GstMemory * mem, GstMemoryFlags flags,
mem->allocator = gst_object_ref (allocator);
if (parent) {
/* FIXME 2.0: this can fail if the memory is already write locked */
gst_memory_lock (parent, GST_LOCK_FLAG_EXCLUSIVE);
gst_memory_ref (parent);
}
@ -387,8 +388,28 @@ gst_memory_share (GstMemory * mem, gssize offset, gssize size)
g_return_val_if_fail (!GST_MEMORY_FLAG_IS_SET (mem, GST_MEMORY_FLAG_NO_SHARE),
NULL);
/* whether we can lock the memory exclusively */
/* in order to maintain backwards compatibility by not requiring subclasses
* to lock the memory themselves and propagate the possible failure in their
* mem_share implementation */
/* FIXME 2.0: remove and fix gst_memory_init() and/or all memory subclasses
* to propagate this failure case */
if (!gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE))
return NULL;
/* double lock to ensure we are not mapped writable without an
* exclusive lock. */
if (!gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE)) {
gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
return NULL;
}
shared = mem->allocator->mem_share (mem, offset, size);
/* unlocking before calling the subclass would be racy */
gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
gst_memory_unlock (mem, GST_LOCK_FLAG_EXCLUSIVE);
return shared;
}

View file

@ -88,6 +88,13 @@ GST_START_TEST (test_submemory)
/* clean up */
gst_memory_unref (sub);
gst_memory_unmap (memory, &info);
/* test write map + share failure */
fail_unless (gst_memory_map (memory, &info, GST_MAP_WRITE));
sub = gst_memory_share (memory, 0, 4);
fail_unless (sub == NULL, "share with a write map succeeded");
gst_memory_unmap (memory, &info);
gst_memory_unref (memory);
}