miniobject: disallow a double write/exclusive lock
authorMatthew Waters <matthew@centricular.com>
Sun, 31 May 2015 11:25:23 +0000 (21:25 +1000)
committerMatthew Waters <matthew@centricular.com>
Wed, 3 Jun 2015 10:41:44 +0000 (20:41 +1000)
gst_memory_lock (mem, WRITE | EXCLUSIVE);
gst_memory_lock (mem, WRITE | EXCLUSIVE);

Succeeds when the part-miniobject.txt design doc suggests that this should fail:

  "A gst_mini_object_lock() can fail when a WRITE lock is requested and
  the exclusive counter is > 1. Indeed a GstMiniObject object with an
  exclusive counter 1 is locked EXCLUSIVELY by at least 2 objects and is
  therefore not writable."

https://bugzilla.gnome.org/show_bug.cgi?id=750172

gst/gstminiobject.c
tests/check/gst/gstmemory.c

index d65bd02..9486dad 100644 (file)
@@ -193,11 +193,13 @@ gst_mini_object_lock (GstMiniObject * object, GstLockFlags flags)
       access_mode &= ~GST_LOCK_FLAG_EXCLUSIVE;
     }
 
-    if (access_mode) {
-      /* shared counter > 1 and write access is not allowed */
-      if (access_mode & GST_LOCK_FLAG_WRITE && IS_SHARED (state))
-        goto lock_failed;
+    /* shared counter > 1 and write access is not allowed */
+    if (((state & GST_LOCK_FLAG_WRITE) != 0
+            || (access_mode & GST_LOCK_FLAG_WRITE) != 0)
+        && IS_SHARED (newstate))
+      goto lock_failed;
 
+    if (access_mode) {
       if ((state & LOCK_FLAG_MASK) == 0) {
         /* nothing mapped, set access_mode */
         newstate |= access_mode;
index 56b3020..d1964da 100644 (file)
@@ -550,6 +550,43 @@ GST_START_TEST (test_alloc_params)
 
 GST_END_TEST;
 
+GST_START_TEST (test_lock)
+{
+  GstMemory *mem;
+
+  mem = gst_allocator_alloc (NULL, 10, NULL);
+  fail_unless (mem != NULL);
+
+  /* test exclusivity */
+  fail_unless (gst_memory_lock (mem, GST_MAP_WRITE | GST_LOCK_FLAG_EXCLUSIVE));
+  fail_if (gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE));
+  fail_unless (gst_memory_lock (mem, GST_MAP_WRITE));
+  gst_memory_unlock (mem, GST_MAP_WRITE | GST_LOCK_FLAG_EXCLUSIVE);
+  gst_memory_unlock (mem, GST_MAP_WRITE);
+
+  /* no lock here */
+
+  fail_unless (gst_memory_lock (mem, GST_MAP_READ | GST_LOCK_FLAG_EXCLUSIVE));
+  fail_unless (gst_memory_lock (mem, GST_MAP_READ | GST_LOCK_FLAG_EXCLUSIVE));
+  gst_memory_unlock (mem, GST_MAP_READ | GST_LOCK_FLAG_EXCLUSIVE);
+  gst_memory_unlock (mem, GST_MAP_READ | GST_LOCK_FLAG_EXCLUSIVE);
+
+  /* no lock here */
+
+  fail_unless (gst_memory_lock (mem,
+          GST_MAP_READWRITE | GST_LOCK_FLAG_EXCLUSIVE));
+  fail_unless (gst_memory_lock (mem, GST_MAP_READ));
+  fail_if (gst_memory_lock (mem, GST_MAP_READ | GST_LOCK_FLAG_EXCLUSIVE));
+  fail_if (gst_memory_lock (mem, GST_LOCK_FLAG_EXCLUSIVE));
+  fail_unless (gst_memory_lock (mem, GST_MAP_WRITE));
+  gst_memory_unlock (mem, GST_MAP_WRITE);
+  gst_memory_unlock (mem, GST_MAP_READ);
+  gst_memory_unlock (mem, GST_MAP_READWRITE | GST_LOCK_FLAG_EXCLUSIVE);
+
+  gst_memory_unref (mem);
+}
+
+GST_END_TEST;
 
 static Suite *
 gst_memory_suite (void)
@@ -569,6 +606,7 @@ gst_memory_suite (void)
   tcase_add_test (tc_chain, test_map_nested);
   tcase_add_test (tc_chain, test_map_resize);
   tcase_add_test (tc_chain, test_alloc_params);
+  tcase_add_test (tc_chain, test_lock);
 
   return s;
 }