[PATCH 1/3] cairo_rwlock: introduce rwl ock.
Zhigang Gong <[email protected]>
| Newsgroups | gmane.comp.lib.cairo |
|---|---|
| Message-ID | <[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 a normal lock. Signed-off-by: Zhigang Gong <[email protected]> --- build/configure.ac.pthread | 13 ++++ src/Makefile.sources | 4 + src/cairo-rwlock-impl-private.h | 135 +++++++++++++++++++++++++++++++++++++++ src/cairo-rwlock-private.h | 51 +++++++++++++++ src/cairo-rwlock-type-private.h | 89 +++++++++++++++++++++++++ src/cairo-rwlock.c | 56 ++++++++++++++++ 6 files changed, 348 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 create mode 100644 src/cairo-rwlock.c 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..198c276 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 \ @@ -181,6 +184,7 @@ cairo_sources = \ cairo-misc.c \ cairo-mono-scan-converter.c \ cairo-mutex.c \ + cairo-rwlock.c \ cairo-no-compositor.c \ cairo-observer.c \ cairo-output-stream.c \ diff --git a/src/cairo-rwlock-impl-private.h b/src/cairo-rwlock-impl-private.h new file mode 100644 index 0000000..67a8fc9 --- /dev/null +++ b/src/cairo-rwlock-impl-private.h @@ -0,0 +1,135 @@ +/* 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 + +/* A fully qualified no-operation statement */ +#define CAIRO_RWLOCK_IMPL_NOOP do {/*no-op*/} while (0) +/* 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 defined(_WIN32) /******************************************************/ + +#define WIN32_LEAN_AND_MEAN +/* We require Windows 2000 features such as ETO_PDY */ +#if !defined(WINVER) || (WINVER < 0x0500) +# define WINVER 0x0500 +#endif +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) +# define _WIN32_WINNT 0x0500 +#endif + +# include <windows.h> + + typedef CRITICAL_SECTION cairo_rwlock_impl_t; + +# define CAIRO_RWLOCK_IMPL_WIN32 1 +# define CAIRO_RWLOCK_IMPL_RDLOCK(rwlock) EnterCriticalSection (&(rwlock)) +# define CAIRO_RWLOCK_IMPL_WRLOCK(rwlock) EnterCriticalSection (&(rwlock)) +# define CAIRO_RWLOCK_IMPL_UNLOCK(rwlock) LeaveCriticalSection (&(rwlock)) +# define CAIRO_RWLOCK_IMPL_INIT(rwlock) InitializeCriticalSection (&(rwlock)) +# define CAIRO_RWLOCK_IMPL_FINI(rwlock) DeleteCriticalSection (&(rwlock)) +# define CAIRO_RWLOCK_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 } + +#elif defined __OS2__ /******************************************************/ + +# define INCL_BASE +# define INCL_PM +# include <os2.h> + + typedef HMTX cairo_rwlock_impl_t; + +# define CAIRO_RWLOCK_IMPL_OS2 1 +# define CAIRO_RWLOCK_IMPL_RDLOCK(rwlock) DosRequestMutexSem(rwlock, SEM_INDEFINITE_WAIT) +# define CAIRO_RWLOCK_IMPL_WRLOCK(rwlock) DosRequestMutexSem(rwlock, SEM_INDEFINITE_WAIT) +# define CAIRO_RWLOCK_IMPL_UNLOCK(rwlock) DosReleaseMutexSem(rwlock) +# define CAIRO_RWLOCK_IMPL_INIT(rwlock) DosCreateMutexSem (NULL, &(rwlock), 0L, FALSE) +# define CAIRO_RWLOCK_IMPL_FINI(rwlock) DosCloseMutexSem (rwlock) +# define CAIRO_RWLOCK_IMPL_NIL_INITIALIZER 0 + +#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/ + + typedef BLocker* cairo_rwlock_impl_t; + +# define CAIRO_RWLOCK_IMPL_BEOS 1 +# define CAIRO_RWLOCK_IMPL_RDLOCK(rwlock) (rwlock)->Lock() +# define CAIRO_RWLOCK_IMPL_WRLOCK(rwlock) (rwlock)->Lock() +# define CAIRO_RWLOCK_IMPL_UNLOCK(rwlock) (rwlock)->Unlock() +# define CAIRO_RWLOCK_IMPL_INIT(rwlock) (rwlock) = new BLocker() +# define CAIRO_RWLOCK_IMPL_FINI(rwlock) delete (rwlock) +# define CAIRO_RWLOCK_IMPL_NIL_INITIALIZER NULL + +#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 + +#else /**********************************************************************/ + +# error "XXX: No rwlock implementation found. Cairo will not work with multiple threads. Define CAIRO_NO_RWLOCK to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support." + +#endif + +#endif diff --git a/src/cairo-rwlock-private.h b/src/cairo-rwlock-private.h new file mode 100644 index 0000000..1ca361d --- /dev/null +++ b/src/cairo-rwlock-private.h @@ -0,0 +1,51 @@ +/* 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" + +CAIRO_BEGIN_DECLS + +cairo_private void _cairo_rwlock_initialize (void); +cairo_private void _cairo_rwlock_finalize (void); + +CAIRO_END_DECLS + +#endif diff --git a/src/cairo-rwlock-type-private.h b/src/cairo-rwlock-type-private.h new file mode 100644 index 0000000..f60fa6a --- /dev/null +++ b/src/cairo-rwlock-type-private.h @@ -0,0 +1,89 @@ +/* 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 + +#ifndef CAIRO_RWLOCK_IS_LOCKED +# define CAIRO_RWLOCK_IS_LOCKED(name) 1 +#endif +#ifndef CAIRO_RWLOCK_IS_UNLOCKED +# define CAIRO_RWLOCK_IS_UNLOCKED(name) 1 +#endif + +#endif diff --git a/src/cairo-rwlock.c b/src/cairo-rwlock.c new file mode 100644 index 0000000..492716e --- /dev/null +++ b/src/cairo-rwlock.c @@ -0,0 +1,56 @@ +/* cairo - a vector graphics library with display and print output + * + * 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. + * + * Contributor(s): + * Mathias Hasselmann <[email protected]> + */ + +#include "cairoint.h" + +#include "cairo-rwlock-private.h" + +static int _cairo_rwlock_initialized = 0; + +void _cairo_rwlock_initialize (void) +{ + if (_cairo_rwlock_initialized) + return; + + _cairo_rwlock_initialized = TRUE; + +} + +void _cairo_rwlock_finalize (void) +{ + if (!_cairo_rwlock_initialized) + return; + + _cairo_rwlock_initialized = FALSE; + +} -- 1.7.4.4 -- cairo mailing list [email protected] http://lists.cairographics.org/mailman/listinfo/cairo