[PATCH 1/4] cairo_rwlock: introduce rwl ock.

[email protected]
Newsgroups gmane.comp.lib.cairo
Message-ID <[email protected]>
From: Zhigang Gong <[email protected]>

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 mutex lock. Please
be noted, use mutex as rwlock may cause deadlock when replaying
recording surface.

Signed-off-by: Zhigang Gong <[email protected]>
---
 build/configure.ac.pthread      |   14 ++++++
 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, 233 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..95e7303 100644
--- a/build/configure.ac.pthread
+++ b/build/configure.ac.pthread
@@ -76,6 +76,20 @@ 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);
+	return x;
 }])
 
 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..53aa6c5
--- /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 <[email protected]>
+ */
+
+#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 ********/
+#include "cairo-mutex-private.h"
+  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) CAIRO_MUTEX_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 <[email protected]>
+ */
+
+#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 <[email protected]>
+ */
+
+#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

-- 
cairo mailing list
[email protected]
http://lists.cairographics.org/mailman/listinfo/cairo
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.