[cairo] [PATCH V2 1/4] cairo_rwlock: introduce rwlock.

Zhigang Gong zhigang.gong at linux.intel.com
Mon May 28 06:09:22 PDT 2012


Here is a scenario which make us to introduce rwlock.
1. One thread(A) is rendering to a surface which has a snapshot attached.
2. Some other threads(B...) are replaying recording surfaces which has the
snapshot of the surface which is being rendered in thread 1.

If thread B already started the replaying, and already get the source
by using _cairo_surface_snapshot_source, then before the thread B finish
its accessing to the source surface, the thread A start to rendering to
the source surface. Although thread A will trigger a COW, but it's too
late, as thread B already got the original surface pointer, thus the
race ocurrs here, both B is reading and A is writing to the same area
concurrently.

To fix this issue, we need to use write lock at thread B, and use read
lock at thread B to avoid the possible race condtion.

Currently, we only implement pthread_rw_lock if the system supports
pthread. Otherwise, we degrade the rw_lock to a normal lock.

Signed-off-by: Zhigang Gong <zhigang.gong at linux.intel.com>
---
 build/configure.ac.pthread      |   13 ++++++
 src/Makefile.sources            |    3 +
 src/cairo-rwlock-impl-private.h |   90 +++++++++++++++++++++++++++++++++++++++
 src/cairo-rwlock-private.h      |   44 +++++++++++++++++++
 src/cairo-rwlock-type-private.h |   82 +++++++++++++++++++++++++++++++++++
 5 files changed, 232 insertions(+), 0 deletions(-)
 create mode 100644 src/cairo-rwlock-impl-private.h
 create mode 100644 src/cairo-rwlock-private.h
 create mode 100644 src/cairo-rwlock-type-private.h

diff --git a/build/configure.ac.pthread b/build/configure.ac.pthread
index 29c930d..72ed03a 100644
--- a/build/configure.ac.pthread
+++ b/build/configure.ac.pthread
@@ -76,6 +76,19 @@ int test_mutex_attr (void)
 	x |= pthread_mutex_destroy (&mutex);
 	x |= pthread_mutexattr_destroy (&attr);
 	return x;
+}
+
+pthread_rwlock_t test_rwlock_initializer = PTHREAD_RWLOCK_INITIALIZER;
+int test_rwlock (void)
+{
+	int x = 0;
+	pthread_rwlock_t rwlock;
+	x |= pthread_rwlock_init(&rwlock, NULL);
+	x |= pthread_rwlock_wrlock(&rwlock);
+	x |= pthread_rwlock_unlock(&rwlock);
+	x |= pthread_rwlock_rdlock(&rwlock);
+	x |= pthread_rwlock_unlock(&rwlock);
+	x |= pthread_rwlock_destroy(&rwlock);
 }])
 
 dnl -----------------------------------------------------------------------
diff --git a/src/Makefile.sources b/src/Makefile.sources
index f487fc1..b989e38 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -91,6 +91,9 @@ cairo_private = \
 	cairo-mutex-list-private.h \
 	cairo-mutex-private.h \
 	cairo-mutex-type-private.h \
+	cairo-rwlock-private.h \
+	cairo-rwlock-impl-private.h \
+	cairo-rwlock-type-private.h \
 	cairo-output-stream-private.h \
 	cairo-paginated-private.h \
 	cairo-paginated-surface-private.h \
diff --git a/src/cairo-rwlock-impl-private.h b/src/cairo-rwlock-impl-private.h
new file mode 100644
index 0000000..3299be1
--- /dev/null
+++ b/src/cairo-rwlock-impl-private.h
@@ -0,0 +1,90 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005,2007 Red Hat, Inc.
+ * Copyright © 2007 Mathias Hasselmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * 	Zhigang Gong <zhigang.gong at linux.intel.com>
+ */
+
+#ifndef CAIRO_RWLOCK_IMPL_PRIVATE_H
+#define CAIRO_RWLOCK_IMPL_PRIVATE_H
+#include "cairo.h"
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* And one that evaluates its argument once */
+#define CAIRO_RWLOCK_IMPL_NOOP1(expr)        do { (void)(expr); } while (0)
+/* Note: 'if (expr) {}' is an alternative to '(void)(expr);' that will 'use' the
+ * result of __attribute__((warn_used_result)) functions. */
+
+#if CAIRO_NO_RWLOCK
+
+/* No rwlocks */
+
+  typedef int cairo_rwlock_impl_t;
+
+# define CAIRO_RWLOCK_IMPL_NO 1
+# define CAIRO_RWLOCK_IMPL_LOCK(rwlock) CAIRO_RWLOCK_IMPL_NOOP1(rwlock)
+# define CAIRO_RWLOCK_IMPL_UNLOCK(rwlock) CAIRO_RWLOCK_IMPL_NOOP1(rwlock)
+# define CAIRO_RWLOCK_IMPL_NIL_INITIALIZER 0
+
+#elif !CAIRO_HAS_PTHREAD /* use mutex as rwlock ********/
+#warn "Has no pthread support, use mutex as rwlock, may cause deadlock."
+  typedef cairo_mutex_t cairo_rwlock_impl_t;
+
+# define CAIRO_RWLOCK_IMPL_MUTEX 1
+# define CAIRO_RWLOCK_IMPL_INIT(rwlock) CAIRO_MUTEX_INIT (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_RDLOCK(rwlock) CAIRO_MUTEX_LOCK (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_WRLOCK(rwlock) CAIRO_MUTEX_LOCK (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_UNLOCK(rwlock) CAIRO_MUTEX_UNLOCK (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_FINI(rwlock) CAIROMUTEX_FINI (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_NIL_INITIALIZER CAIRO_MUTEX_NIL_INITIALIZER
+
+#elif CAIRO_HAS_PTHREAD /* and finally if there are no native rwlocks ********/
+
+# include <pthread.h>
+  typedef pthread_rwlock_t cairo_rwlock_impl_t;
+
+# define CAIRO_RWLOCK_IMPL_PTHREAD 1
+# define CAIRO_RWLOCK_IMPL_INIT(rwlock) pthread_rwlock_init (&(rwlock), NULL)
+# define CAIRO_RWLOCK_IMPL_RDLOCK(rwlock) pthread_rwlock_rdlock (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_WRLOCK(rwlock) pthread_rwlock_wrlock (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_UNLOCK(rwlock) pthread_rwlock_unlock (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_FINI(rwlock) pthread_rwlock_destroy (&(rwlock))
+# define CAIRO_RWLOCK_IMPL_NIL_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+
+#endif
+
+#endif
diff --git a/src/cairo-rwlock-private.h b/src/cairo-rwlock-private.h
new file mode 100644
index 0000000..fde3ce8
--- /dev/null
+++ b/src/cairo-rwlock-private.h
@@ -0,0 +1,44 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005,2007 Red Hat, Inc.
+ * Copyright © 2007 Mathias Hasselmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * 	Zhigang Gong <zhigang.gong at linux.intel.com>
+ */
+
+#ifndef CAIRO_RWLOCK_PRIVATE_H
+#define CAIRO_RWLOCK_PRIVATE_H
+
+#include "cairo-rwlock-type-private.h"
+
+#endif
diff --git a/src/cairo-rwlock-type-private.h b/src/cairo-rwlock-type-private.h
new file mode 100644
index 0000000..afeac9c
--- /dev/null
+++ b/src/cairo-rwlock-type-private.h
@@ -0,0 +1,82 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2002 University of Southern California
+ * Copyright © 2005,2007 Red Hat, Inc.
+ * Copyright © 2007 Mathias Hasselmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is University of Southern
+ * California.
+ *
+ * Contributor(s):
+ * 	Zhigang Gong <zhigang.gong at linux.intel.com>
+ */
+
+#ifndef CAIRO_RWLOCK_TYPE_PRIVATE_H
+#define CAIRO_RWLOCK_TYPE_PRIVATE_H
+
+#include "cairo-compiler-private.h"
+#include "cairo-rwlock-impl-private.h"
+
+/* Only the following four are mandatory at this point */
+#ifndef CAIRO_RWLOCK_IMPL_RDLOCK
+# error "CAIRO_RWLOCK_IMPL_RDLOCK not defined.  Check cairo-rwlock-impl-private.h."
+#endif
+#ifndef CAIRO_RWLOCK_IMPL_WRLOCK
+# error "CAIRO_RWLOCK_IMPL_WRLOCK not defined.  Check cairo-rwlock-impl-private.h."
+#endif
+#ifndef CAIRO_RWLOCK_IMPL_UNLOCK
+# error "CAIRO_RWLOCK_IMPL_UNLOCK not defined.  Check cairo-rwlock-impl-private.h."
+#endif
+#ifndef CAIRO_RWLOCK_IMPL_NIL_INITIALIZER
+# error "CAIRO_RWLOCK_IMPL_NIL_INITIALIZER not defined.  Check cairo-rwlock-impl-private.h."
+#endif
+
+
+/* Make sure everything we want is defined */
+#ifndef CAIRO_RWLOCK_IMPL_INIT
+# error "CAIRO_RWLOCK_IMPL_INIT not defined"
+#endif
+#ifndef CAIRO_RWLOCK_IMPL_FINI
+# error "CAIRO_RWLOCK_IMPL_FINI not defined"
+#endif
+#ifndef CAIRO_RWLOCK_IMPL_NIL_INITIALIZER
+# error "CAIRO_RWLOCK_IMPL_NIL_INITIALIZER not defined"
+#endif
+
+/* Public interface. */
+
+# define cairo_rwlock_t			cairo_rwlock_impl_t
+
+#define CAIRO_RWLOCK_RDLOCK		CAIRO_RWLOCK_IMPL_RDLOCK
+#define CAIRO_RWLOCK_WRLOCK		CAIRO_RWLOCK_IMPL_WRLOCK
+#define CAIRO_RWLOCK_UNLOCK		CAIRO_RWLOCK_IMPL_UNLOCK
+#define CAIRO_RWLOCK_INIT		CAIRO_RWLOCK_IMPL_INIT
+#define CAIRO_RWLOCK_FINI		CAIRO_RWLOCK_IMPL_FINI
+#define CAIRO_RWLOCK_NIL_INITIALIZER	CAIRO_RWLOCK_IMPL_NIL_INITIALIZER
+
+#endif
-- 
1.7.4.4



More information about the cairo mailing list