[cairo-commit] 4 commits - src/cairo-mutex.c src/cairo-mutex-impl-private.h src/cairo-mutex-private.h src/cairo-mutex-type-private.h src/cairo-xlib-surface.c src/Makefile.am util/backtrace-symbols.c

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue May 27 02:20:34 PDT 2008


 src/Makefile.am                |    1 
 src/cairo-mutex-impl-private.h |  226 ++++++++++++++++++++++++++++++++++
 src/cairo-mutex-private.h      |  129 +------------------
 src/cairo-mutex-type-private.h |  269 +++++++++++++++++++----------------------
 src/cairo-mutex.c              |   18 +-
 src/cairo-xlib-surface.c       |   72 ++++++++++
 util/backtrace-symbols.c       |   18 ++
 7 files changed, 459 insertions(+), 274 deletions(-)

New commits:
commit 626edfc333b77604b6955c12ae111d14c174034c
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon May 26 20:28:23 2008 -0400

    [cairo-mutex] Prepare mutex infrastructure for adding mutex debugging facilities
    
    Essentially renaming cairo-mutex-type-private.h to cairo-mutex-impl-private.h
    and changing all its namespace from cairo_mutex to cairo_mutex_impl.
    cairo-mutex-type-private.h then does all the sanity checks on the
    implementation that used to be in cairo-mutex-private.h.  Plus, defines macros
    for the cairo-mutex namespace to map to the cairo-mutex-impl namespace.  This
    extra mapping layer allows for add debugging facilities.

diff --git a/src/Makefile.am b/src/Makefile.am
index c52a7a0..de080e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -36,6 +36,7 @@ cairo_base_sources =				\
 	cairo-matrix.c				\
 	cairo-mutex.c				\
 	cairo-mutex-private.h			\
+	cairo-mutex-impl-private.h		\
 	cairo-mutex-type-private.h		\
 	cairo-path.c				\
 	cairo-path-private.h			\
diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h
new file mode 100644
index 0000000..6905566
--- /dev/null
+++ b/src/cairo-mutex-impl-private.h
@@ -0,0 +1,226 @@
+/* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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):
+ *	Carl D. Worth <cworth at cworth.org>
+ *	Mathias Hasselmann <mathias.hasselmann at gmx.de>
+ *	Behdad Esfahbod <behdad at behdad.org>
+ */
+
+#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
+#define CAIRO_MUTEX_IMPL_PRIVATE_H
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <cairo-features.h>
+
+CAIRO_BEGIN_DECLS
+
+
+/* A fully qualified no-operation statement */
+#define CAIRO_MUTEX_IMPL_NOOP	do {/*no-op*/} while (0)
+/* And one that evaluates it's argument once */
+#define CAIRO_MUTEX_IMPL_NOOP1(expr)        do { if (expr) ; } while (0)
+
+
+/* Cairo mutex implementation:
+ *
+ * Any new mutex implementation needs to do the following:
+ *
+ * - Condition on the right header or feature.  Headers are
+ *   preferred as eg. you still can use win32 mutex implementation
+ *   on a win32 system even if you do not compile the win32
+ *   surface/backend.
+ *
+ * - typedef #cairo_mutex_impl_t to the proper mutex type on your target
+ *   system.  Note that you may or may not need to use a pointer,
+ *   depending on what kinds of initialization your mutex
+ *   implementation supports.  No trailing semicolon needed.
+ *   You should be able to compile the following snippet (don't try
+ *   running it):
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex;
+ *   </programlisting>
+ *
+ * - #define CAIRO_MUTEX_IMPL_LOCK(mutex) and CAIRO_MUTEX_IMPL_UNLOCK(mutex) to
+ *   proper statement to lock/unlock the mutex object passed in.
+ *   You can (and should) assume that the mutex is already
+ *   initialized, and is-not-already-locked/is-locked,
+ *   respectively.  Use the "do { ... } while (0)" idiom if necessary.
+ *   No trailing semicolons are needed (in any macro you define here).
+ *   You should be able to compile the following snippet:
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex;
+ *
+ *      if (1)
+ *          CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
+ *      else
+ *          CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
+ *
+ * - #define %CAIRO_MUTEX_IMPL_NIL_INITIALIZER to something that can
+ *   initialize the #cairo_mutex_impl_t type you defined.  Most of the
+ *   time one of 0, %NULL, or {} works.  At this point
+ *   you should be able to compile the following snippet:
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;
+ *
+ *      if (1)
+ *          CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
+ *      else
+ *          CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
+ *
+ * - If the above code is not enough to initialize a mutex on
+ *   your platform, #define CAIRO_MUTEX_IMPL_INIT(mutex) to statement
+ *   to initialize the mutex (allocate resources, etc).  Such that
+ *   you should be able to compile AND RUN the following snippet:
+ *
+ *   <programlisting>
+ *	cairo_mutex_impl_t _cairo_some_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;
+ *
+ *      CAIRO_MUTEX_IMPL_INIT (_cairo_some_mutex);
+ *
+ *      if (1)
+ *          CAIRO_MUTEX_IMPL_LOCK (_cairo_some_mutex);
+ *      else
+ *          CAIRO_MUTEX_IMPL_UNLOCK (_cairo_some_mutex);
+ *   </programlisting>
+ *
+ * - If you define CAIRO_MUTEX_IMPL_INIT(mutex), cairo will use it to
+ *   initialize all static mutex'es.  If for any reason that should
+ *   not happen (eg. %CAIRO_MUTEX_IMPL_INIT is just a faster way than
+ *   what cairo does using %CAIRO_MUTEX_IMPL_NIL_INITIALIZER), then
+ *   <programlisting>
+ *      #define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
+ *   </programlisting>
+ *
+ * - If your system supports freeing a mutex object (deallocating
+ *   resources, etc), then #define CAIRO_MUTEX_IMPL_FINI(mutex) to do
+ *   that.
+ *
+ * - If you define CAIRO_MUTEX_IMPL_FINI(mutex), cairo will use it to
+ *   define a finalizer function to finalize all static mutex'es.
+ *   However, it's up to you to call CAIRO_MUTEX_IMPL_FINALIZE() at
+ *   proper places, eg. when the system is unloading the cairo library.
+ *   So, if for any reason finalizing static mutex'es is not needed
+ *   (eg. you never call CAIRO_MUTEX_IMPL_FINALIZE()), then
+ *   <programlisting>
+ *      #define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+ *   </programlisting>
+ *
+ * - That is all.  If for any reason you think the above API is
+ *   not enough to implement #cairo_mutex_impl_t on your system, please
+ *   stop and write to the cairo mailing list about it.  DO NOT
+ *   poke around cairo-mutex-private.h for possible solutions.
+ */
+
+#ifndef CAIRO_MUTEX_TYPE_PRIVATE_H
+#error "Do not include cairo-mutex-impl-private.h directly.  Include cairo-mutex-type-private.h instead."
+#endif
+
+#if CAIRO_NO_MUTEX
+
+/* No mutexes */
+
+  typedef int cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
+
+#elif HAVE_PTHREAD_H /*******************************************************/
+
+# include <pthread.h>
+
+  typedef pthread_mutex_t cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
+# define CAIRO_MUTEX_IMPL_FINI(mutex) pthread_mutex_destroy (&(mutex))
+# define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+#elif HAVE_WINDOWS_H /*******************************************************/
+
+# include <windows.h>
+
+  typedef CRITICAL_SECTION cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
+
+#elif defined __OS2__ /******************************************************/
+
+# define INCL_BASE
+# define INCL_PM
+# include <os2.h>
+
+  typedef HMTX cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) DosReleaseMutexSem(mutex)
+# define CAIRO_MUTEX_IMPL_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
+# define CAIRO_MUTEX_IMPL_FINI(mutex) DosCloseMutexSem (mutex)
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
+
+#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
+
+  typedef BLocker* cairo_mutex_impl_t;
+
+# define CAIRO_MUTEX_IMPL_LOCK(mutex) (mutex)->Lock()
+# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) (mutex)->Unlock()
+# define CAIRO_MUTEX_IMPL_INIT(mutex) (mutex) = new BLocker()
+# define CAIRO_MUTEX_IMPL_FINI(mutex) delete (mutex)
+# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER NULL
+
+#else /**********************************************************************/
+
+# error "XXX: No mutex implementation found.  Cairo will not work with multiple threads.  Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
+
+
+#endif
+
+CAIRO_END_DECLS
+
+#endif
diff --git a/src/cairo-mutex-private.h b/src/cairo-mutex-private.h
index 64afd64..61b87d7 100644
--- a/src/cairo-mutex-private.h
+++ b/src/cairo-mutex-private.h
@@ -41,136 +41,27 @@
 #ifndef CAIRO_MUTEX_PRIVATE_H
 #define CAIRO_MUTEX_PRIVATE_H
 
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <cairo-features.h>
-
-#include "cairo-compiler-private.h"
 #include "cairo-mutex-type-private.h"
 
-/* Only the following three are mandatory at this point */
-#ifndef CAIRO_MUTEX_LOCK
-# error "CAIRO_MUTEX_LOCK not defined.  Check cairo-mutex-type-private.h."
-#endif
-#ifndef CAIRO_MUTEX_UNLOCK
-# error "CAIRO_MUTEX_UNLOCK not defined.  Check cairo-mutex-type-private.h."
-#endif
-#ifndef CAIRO_MUTEX_NIL_INITIALIZER
-# error "CAIRO_MUTEX_NIL_INITIALIZER not defined.  Check cairo-mutex-type-private.h."
-#endif
-
 CAIRO_BEGIN_DECLS
 
-
-#define CAIRO_MUTEX_DECLARE(mutex) extern cairo_mutex_t mutex
-#include "cairo-mutex-list-private.h"
-#undef CAIRO_MUTEX_DECLARE
-
-
-/* make sure implementations don't fool us: we decide these ourself */
-#undef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
-#undef _CAIRO_MUTEX_USE_STATIC_FINALIZER
-
-
-#ifdef CAIRO_MUTEX_INIT
-
-/* If %CAIRO_MUTEX_INIT is defined, we may need to initialize all
- * static mutex'es. */
-# ifndef CAIRO_MUTEX_INITIALIZE
-#  define CAIRO_MUTEX_INITIALIZE() do {	\
-       if (!_cairo_mutex_initialized)	\
-           _cairo_mutex_initialize ();	\
-   } while(0)
-
-   cairo_private void _cairo_mutex_initialize (void);
-
-   /* and make sure we implement the above */
-#  define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 1
-# endif /* CAIRO_MUTEX_INITIALIZE */
-
-#else /* no CAIRO_MUTEX_INIT */
-
-/* Otherwise we probably don't need to initialize static mutex'es, */
-# ifndef CAIRO_MUTEX_INITIALIZE
-#  define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# endif /* CAIRO_MUTEX_INITIALIZE */
-
-/* and dynamic ones can be initialized using the static initializer. */
-# define CAIRO_MUTEX_INIT(mutex) do {				\
-      cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_NIL_INITIALIZER;	\
-      memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex));	\
-  } while (0)
-
-#endif /* CAIRO_MUTEX_INIT */
-
-
-#ifdef CAIRO_MUTEX_FINI
-
-/* If %CAIRO_MUTEX_FINI is defined, we may need to finalize all
- * static mutex'es. */
-# ifndef CAIRO_MUTEX_FINALIZE
-#  define CAIRO_MUTEX_FINALIZE() do {	\
-       if (_cairo_mutex_initialized)	\
-           _cairo_mutex_finalize ();	\
-   } while(0)
-
-   cairo_private void _cairo_mutex_finalize (void);
-
-   /* and make sure we implement the above */
-#  define _CAIRO_MUTEX_USE_STATIC_FINALIZER 1
-# endif /* CAIRO_MUTEX_FINALIZE */
-
-#else /* no CAIRO_MUTEX_FINI */
-
-/* Otherwise we probably don't need to finalize static mutex'es, */
-# ifndef CAIRO_MUTEX_FINALIZE
-#  define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
-# endif /* CAIRO_MUTEX_FINALIZE */
-
-/* neither do the dynamic ones. */
-# define CAIRO_MUTEX_FINI(mutex)	CAIRO_MUTEX_NOOP1(mutex)
-
-#endif /* CAIRO_MUTEX_FINI */
-
-
-#ifndef _CAIRO_MUTEX_USE_STATIC_INITIALIZER
-#define _CAIRO_MUTEX_USE_STATIC_INITIALIZER 0
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+cairo_private void _cairo_mutex_initialize (void);
 #endif
-#ifndef _CAIRO_MUTEX_USE_STATIC_FINALIZER
-#define _CAIRO_MUTEX_USE_STATIC_FINALIZER 0
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
+cairo_private void _cairo_mutex_finalize (void);
 #endif
-
 /* only if using static initializer and/or finalizer define the boolean */
-#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
   cairo_private extern cairo_bool_t _cairo_mutex_initialized;
 #endif
 
+/* Finally, extern the static mutexes and undef */
 
-CAIRO_END_DECLS
+#define CAIRO_MUTEX_DECLARE(mutex) cairo_private extern cairo_mutex_t mutex
+#include "cairo-mutex-list-private.h"
+#undef CAIRO_MUTEX_DECLARE
 
-/* Make sure everything we want is defined */
-#ifndef CAIRO_MUTEX_INITIALIZE
-# error "CAIRO_MUTEX_INITIALIZE not defined"
-#endif
-#ifndef CAIRO_MUTEX_FINALIZE
-# error "CAIRO_MUTEX_FINALIZE not defined"
-#endif
-#ifndef CAIRO_MUTEX_LOCK
-# error "CAIRO_MUTEX_LOCK not defined"
-#endif
-#ifndef CAIRO_MUTEX_UNLOCK
-# error "CAIRO_MUTEX_UNLOCK not defined"
-#endif
-#ifndef CAIRO_MUTEX_INIT
-# error "CAIRO_MUTEX_INIT not defined"
-#endif
-#ifndef CAIRO_MUTEX_FINI
-# error "CAIRO_MUTEX_FINI not defined"
-#endif
-#ifndef CAIRO_MUTEX_NIL_INITIALIZER
-# error "CAIRO_MUTEX_NIL_INITIALIZER not defined"
-#endif
+CAIRO_END_DECLS
 
 #endif
diff --git a/src/cairo-mutex-type-private.h b/src/cairo-mutex-type-private.h
index f68afb7..3dc5f49 100644
--- a/src/cairo-mutex-type-private.h
+++ b/src/cairo-mutex-type-private.h
@@ -47,176 +47,161 @@
 
 #include <cairo-features.h>
 
-CAIRO_BEGIN_DECLS
+#include "cairo-compiler-private.h"
+#include "cairo-mutex-impl-private.h"
 
+/* Only the following three are mandatory at this point */
+#ifndef CAIRO_MUTEX_IMPL_LOCK
+# error "CAIRO_MUTEX_IMPL_LOCK not defined.  Check cairo-mutex-impl-private.h."
+#endif
+#ifndef CAIRO_MUTEX_IMPL_UNLOCK
+# error "CAIRO_MUTEX_IMPL_UNLOCK not defined.  Check cairo-mutex-impl-private.h."
+#endif
+#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
+# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined.  Check cairo-mutex-impl-private.h."
+#endif
 
-/* A fully qualified no-operation statement */
-#define CAIRO_MUTEX_NOOP	do {/*no-op*/} while (0)
-/* And one that evaluates it's argument once */
-#define CAIRO_MUTEX_NOOP1(expr)        do { if (expr) ; } while (0)
 
+/* make sure implementations don't fool us: we decide these ourself */
+#undef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+#undef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 
-/* Cairo mutex implementation:
- *
- * Any new mutex implementation needs to do the following:
- *
- * - Condition on the right header or feature.  Headers are
- *   preferred as eg. you still can use win32 mutex implementation
- *   on a win32 system even if you do not compile the win32
- *   surface/backend.
- *
- * - typedef #cairo_mutex_t to the proper mutex type on your target
- *   system.  Note that you may or may not need to use a pointer,
- *   depending on what kinds of initialization your mutex
- *   implementation supports.  No trailing semicolon needed.
- *   You should be able to compile the following snippet (don't try
- *   running it):
- *
- *   <programlisting>
- *	cairo_mutex_t _cairo_some_mutex;
- *   </programlisting>
- *
- * - #define CAIRO_MUTEX_LOCK(mutex) and CAIRO_MUTEX_UNLOCK(mutex) to
- *   proper statement to lock/unlock the mutex object passed in.
- *   You can (and should) assume that the mutex is already
- *   initialized, and is-not-already-locked/is-locked,
- *   respectively.  Use the "do { ... } while (0)" idiom if necessary.
- *   No trailing semicolons are needed (in any macro you define here).
- *   You should be able to compile the following snippet:
- *
- *   <programlisting>
- *	cairo_mutex_t _cairo_some_mutex;
- *
- *      if (1)
- *          CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- *      else
- *          CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- *   </programlisting>
- *
- * - #define %CAIRO_MUTEX_NIL_INITIALIZER to something that can
- *   initialize the #cairo_mutex_t type you defined.  Most of the
- *   time one of 0, %NULL, or {} works.  At this point
- *   you should be able to compile the following snippet:
- *
- *   <programlisting>
- *	cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
- *
- *      if (1)
- *          CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- *      else
- *          CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- *   </programlisting>
- *
- * - If the above code is not enough to initialize a mutex on
- *   your platform, #define CAIRO_MUTEX_INIT(mutex) to statement
- *   to initialize the mutex (allocate resources, etc).  Such that
- *   you should be able to compile AND RUN the following snippet:
- *
- *   <programlisting>
- *	cairo_mutex_t _cairo_some_mutex = CAIRO_MUTEX_NIL_INITIALIZER;
- *
- *      CAIRO_MUTEX_INIT (_cairo_some_mutex);
- *
- *      if (1)
- *          CAIRO_MUTEX_LOCK (_cairo_some_mutex);
- *      else
- *          CAIRO_MUTEX_UNLOCK (_cairo_some_mutex);
- *   </programlisting>
- *
- * - If you define CAIRO_MUTEX_INIT(mutex), cairo will use it to
- *   initialize all static mutex'es.  If for any reason that should
- *   not happen (eg. %CAIRO_MUTEX_INIT is just a faster way than
- *   what cairo does using %CAIRO_MUTEX_NIL_INITIALIZER), then
- *   <programlisting>
- *      #define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
- *   </programlisting>
- *
- * - If your system supports freeing a mutex object (deallocating
- *   resources, etc), then #define CAIRO_MUTEX_FINI(mutex) to do
- *   that.
- *
- * - If you define CAIRO_MUTEX_FINI(mutex), cairo will use it to
- *   define a finalizer function to finalize all static mutex'es.
- *   However, it's up to you to call CAIRO_MUTEX_FINALIZE() at
- *   proper places, eg. when the system is unloading the cairo library.
- *   So, if for any reason finalizing static mutex'es is not needed
- *   (eg. you never call CAIRO_MUTEX_FINALIZE()), then
- *   <programlisting>
- *      #define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
- *   </programlisting>
- *
- * - That is all.  If for any reason you think the above API is
- *   not enough to implement #cairo_mutex_t on your system, please
- *   stop and write to the cairo mailing list about it.  DO NOT
- *   poke around cairo-mutex-private.h for possible solutions.
- */
 
-#if CAIRO_NO_MUTEX
+#ifdef CAIRO_MUTEX_IMPL_INIT
 
-/* No mutexes */
+/* If %CAIRO_MUTEX_IMPL_INIT is defined, we may need to initialize all
+ * static mutex'es. */
+# ifndef CAIRO_MUTEX_IMPL_INITIALIZE
+#  define CAIRO_MUTEX_IMPL_INITIALIZE() do {	\
+       if (!_cairo_mutex_initialized)	\
+           _cairo_mutex_initialize ();	\
+   } while(0)
 
-  typedef int cairo_mutex_t;
+   /* and make sure we implement the above */
+#  define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 1
+# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
 
-# define CAIRO_MUTEX_INITIALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_LOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
-# define CAIRO_MUTEX_UNLOCK(mutex) CAIRO_MUTEX_NOOP1(mutex)
-# define CAIRO_MUTEX_NIL_INITIALIZER 0
+#else /* no CAIRO_MUTEX_IMPL_INIT */
 
-#elif HAVE_PTHREAD_H /*******************************************************/
+/* Otherwise we probably don't need to initialize static mutex'es, */
+# ifndef CAIRO_MUTEX_IMPL_INITIALIZE
+#  define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
+# endif /* CAIRO_MUTEX_IMPL_INITIALIZE */
 
-# include <pthread.h>
+/* and dynamic ones can be initialized using the static initializer. */
+# define CAIRO_MUTEX_IMPL_INIT(mutex) do {				\
+      cairo_mutex_t _tmp_mutex = CAIRO_MUTEX_IMPL_NIL_INITIALIZER;	\
+      memcpy (&(mutex), &_tmp_mutex, sizeof (_tmp_mutex));	\
+  } while (0)
 
-  typedef pthread_mutex_t cairo_mutex_t;
+#endif /* CAIRO_MUTEX_IMPL_INIT */
 
-# define CAIRO_MUTEX_LOCK(mutex) pthread_mutex_lock (&(mutex))
-# define CAIRO_MUTEX_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
-# define CAIRO_MUTEX_FINI(mutex) pthread_mutex_destroy (&(mutex))
-# define CAIRO_MUTEX_FINALIZE() CAIRO_MUTEX_NOOP
-# define CAIRO_MUTEX_NIL_INITIALIZER PTHREAD_MUTEX_INITIALIZER
 
-#elif HAVE_WINDOWS_H /*******************************************************/
+#ifdef CAIRO_MUTEX_IMPL_FINI
 
-# include <windows.h>
+/* If %CAIRO_MUTEX_IMPL_FINI is defined, we may need to finalize all
+ * static mutex'es. */
+# ifndef CAIRO_MUTEX_IMPL_FINALIZE
+#  define CAIRO_MUTEX_IMPL_FINALIZE() do {	\
+       if (_cairo_mutex_initialized)	\
+           _cairo_mutex_finalize ();	\
+   } while(0)
 
-  typedef CRITICAL_SECTION cairo_mutex_t;
+   /* and make sure we implement the above */
+#  define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 1
+# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
 
-# define CAIRO_MUTEX_LOCK(mutex) EnterCriticalSection (&(mutex))
-# define CAIRO_MUTEX_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
-# define CAIRO_MUTEX_INIT(mutex) InitializeCriticalSection (&(mutex))
-# define CAIRO_MUTEX_FINI(mutex) DeleteCriticalSection (&(mutex))
-# define CAIRO_MUTEX_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
+#else /* no CAIRO_MUTEX_IMPL_FINI */
 
-#elif defined __OS2__ /******************************************************/
+/* Otherwise we probably don't need to finalize static mutex'es, */
+# ifndef CAIRO_MUTEX_IMPL_FINALIZE
+#  define CAIRO_MUTEX_IMPL_FINALIZE() CAIRO_MUTEX_IMPL_NOOP
+# endif /* CAIRO_MUTEX_IMPL_FINALIZE */
 
-# define INCL_BASE
-# define INCL_PM
-# include <os2.h>
+/* neither do the dynamic ones. */
+# define CAIRO_MUTEX_IMPL_FINI(mutex)	CAIRO_MUTEX_IMPL_NOOP1(mutex)
 
-  typedef HMTX cairo_mutex_t;
+#endif /* CAIRO_MUTEX_IMPL_FINI */
 
-# define CAIRO_MUTEX_LOCK(mutex) DosRequestMutexSem(mutex, SEM_INDEFINITE_WAIT)
-# define CAIRO_MUTEX_UNLOCK(mutex) DosReleaseMutexSem(mutex)
-# define CAIRO_MUTEX_INIT(mutex) DosCreateMutexSem (NULL, &(mutex), 0L, FALSE)
-# define CAIRO_MUTEX_FINI(mutex) DosCloseMutexSem (mutex)
-# define CAIRO_MUTEX_NIL_INITIALIZER 0
 
-#elif CAIRO_HAS_BEOS_SURFACE /***********************************************/
+#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+#define _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER 0
+#endif
+#ifndef _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
+#define _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER 0
+#endif
 
-  typedef BLocker* cairo_mutex_t;
 
-# define CAIRO_MUTEX_LOCK(mutex) (mutex)->Lock()
-# define CAIRO_MUTEX_UNLOCK(mutex) (mutex)->Unlock()
-# define CAIRO_MUTEX_INIT(mutex) (mutex) = new BLocker()
-# define CAIRO_MUTEX_FINI(mutex) delete (mutex)
-# define CAIRO_MUTEX_NIL_INITIALIZER NULL
+/* Make sure everything we want is defined */
+#ifndef CAIRO_MUTEX_IMPL_INITIALIZE
+# error "CAIRO_MUTEX_IMPL_INITIALIZE not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_FINALIZE
+# error "CAIRO_MUTEX_IMPL_FINALIZE not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_LOCK
+# error "CAIRO_MUTEX_IMPL_LOCK not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_UNLOCK
+# error "CAIRO_MUTEX_IMPL_UNLOCK not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_INIT
+# error "CAIRO_MUTEX_IMPL_INIT not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_FINI
+# error "CAIRO_MUTEX_IMPL_FINI not defined"
+#endif
+#ifndef CAIRO_MUTEX_IMPL_NIL_INITIALIZER
+# error "CAIRO_MUTEX_IMPL_NIL_INITIALIZER not defined"
+#endif
 
-#else /**********************************************************************/
 
-# error "XXX: No mutex implementation found.  Cairo will not work with multiple threads.  Define CAIRO_NO_MUTEX to 1 to acknowledge and accept this limitation and compile cairo without thread-safety support."
+/* Public interface. */
 
+/* By default it simply uses the implementation provided.
+ * But we can provide for debugging features by overriding them */
 
+#ifndef CAIRO_MUTEX_DEBUG
+typedef cairo_mutex_impl_t cairo_mutex_t;
+#else
+# define cairo_mutex_t			cairo_mutex_impl_t
 #endif
 
-CAIRO_END_DECLS
+#define CAIRO_MUTEX_INITIALIZE		CAIRO_MUTEX_IMPL_INITIALIZE
+#define CAIRO_MUTEX_FINALIZE		CAIRO_MUTEX_IMPL_FINALIZE
+#define CAIRO_MUTEX_LOCK		CAIRO_MUTEX_IMPL_LOCK
+#define CAIRO_MUTEX_UNLOCK		CAIRO_MUTEX_IMPL_UNLOCK
+#define CAIRO_MUTEX_INIT		CAIRO_MUTEX_IMPL_INIT
+#define CAIRO_MUTEX_FINI		CAIRO_MUTEX_IMPL_FINI
+#define CAIRO_MUTEX_NIL_INITIALIZER	CAIRO_MUTEX_IMPL_NIL_INITIALIZER
+
+
+
+/* Debugging support */
+
+#ifdef CAIRO_MUTEX_DEBUG
+
+# undef CAIRO_MUTEX_LOCK
+# undef CAIRO_MUTEX_UNLOCK
+# define CAIRO_MUTEX_LOCK(mutex)	CAIRO_MUTEX_LOG_OP(mutex, "LOCK",   CAIRO_MUTEX_IMPL_LOCK)
+# define CAIRO_MUTEX_UNLOCK(mutex)	CAIRO_MUTEX_LOG_OP(mutex, "UNLOCK", CAIRO_MUTEX_IMPL_UNLOCK)
+
+#define CAIRO_MUTEX_LOG_OP(mutex, msg, op) \
+	do { cairo_mutex_t *__m = &(mutex); CAIRO_MUTEX_LOG(__m, msg); op(*__m); } while (0)
+
+
+#include <execinfo.h>
+#define CAIRO_MUTEX_LOG(mutex, msg) CAIRO_MUTEX_LOG0(mutex, CAIRO_MUTEX_DEBUG, msg)
+#define CAIRO_MUTEX_LOG0(mutex, which, msg) if (mutex == &which) CAIRO_MUTEX_LOG1(mutex, which, msg)
+#define CAIRO_MUTEX_LOG1(mutex, which, msg) \
+	do {	\
+		void *buffer[10];	\
+		int nptrs;	\
+		fprintf (stderr, "" #which " %s\n", msg);	\
+		nptrs = backtrace(buffer, ARRAY_LENGTH (buffer));	\
+		backtrace_symbols_fd (buffer, nptrs, 2);	\
+	} while (0)
+
+#endif /* CAIRO_MUTEX_DEBUG */
 
 #endif
diff --git a/src/cairo-mutex.c b/src/cairo-mutex.c
index 88aaf0d..5149ee8 100644
--- a/src/cairo-mutex.c
+++ b/src/cairo-mutex.c
@@ -33,25 +33,27 @@
 
 #include "cairoint.h"
 
+#include "cairo-mutex-private.h"
+
 #define CAIRO_MUTEX_DECLARE(mutex) cairo_mutex_t mutex = CAIRO_MUTEX_NIL_INITIALIZER
 #include "cairo-mutex-list-private.h"
 #undef   CAIRO_MUTEX_DECLARE
 
-#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_USE_STATIC_FINALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER || _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 
-# if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
-#  define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE FALSE
+# if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
+#  define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE FALSE
 # else
-#  define _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE TRUE
+#  define _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE TRUE
 # endif
 
-cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE;
+cairo_bool_t _cairo_mutex_initialized = _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE;
 
-# undef _CAIRO_MUTEX_INITIALIZED_DEFAULT_VALUE
+# undef _CAIRO_MUTEX_IMPL_INITIALIZED_DEFAULT_VALUE
 
 #endif
 
-#if _CAIRO_MUTEX_USE_STATIC_INITIALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_INITIALIZER
 void _cairo_mutex_initialize (void)
 {
     if (_cairo_mutex_initialized)
@@ -65,7 +67,7 @@ void _cairo_mutex_initialize (void)
 }
 #endif
 
-#if _CAIRO_MUTEX_USE_STATIC_FINALIZER
+#if _CAIRO_MUTEX_IMPL_USE_STATIC_FINALIZER
 void _cairo_mutex_finalize (void)
 {
     if (!_cairo_mutex_initialized)
commit 07fef4f4802639a2cb16284841635d1bcc9b8e8f
Author: Ginn Chen <ginn.chen at sun.com>
Date:   Tue May 27 04:44:08 2008 -0400

    [cairo-xlib] Implement _cairo_xlib_surface_solid_fill_rectangles() (#11529)

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 17d511c..662f4ad 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1615,11 +1615,66 @@ _cairo_xlib_surface_composite (cairo_operator_t		op,
 }
 
 static cairo_int_status_t
+_cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t    *surface,
+					   const cairo_color_t     *color,
+					   cairo_rectangle_int_t   *rects,
+					   int			   num_rects)
+{
+    XGCValues gcv;
+    int a_width=0, r_width=0, g_width=0, b_width=0;
+    int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
+    int a = color->alpha_short >> 8;
+    int r = color->red_short >> 8;
+    int g = color->green_short >> 8;
+    int b = color->blue_short >> 8;
+    int i;
+
+    if (surface->visual->class == TrueColor) {
+	_characterize_field (surface->a_mask, &a_width, &a_shift);
+	_characterize_field (surface->r_mask, &r_width, &r_shift);
+	_characterize_field (surface->g_mask, &g_width, &g_shift);
+	_characterize_field (surface->b_mask, &b_width, &b_shift);
+	gcv.foreground = (_field_from_8 (a, a_width, a_shift) |
+			  _field_from_8 (r, r_width, r_shift) |
+			  _field_from_8 (g, g_width, g_shift) |
+			  _field_from_8 (b, b_width, b_shift));
+    } else {
+	cairo_xlib_visual_info_t *visual_info;
+	cairo_int_status_t status;
+
+	status = _cairo_xlib_screen_get_visual_info (surface->screen_info,
+						     surface->visual,
+						     &visual_info);
+	if (status)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	gcv.foreground =
+	    visual_info->rgb333_to_pseudocolor[_field_from_8 (r, 3, 6) |
+					       _field_from_8 (g, 3, 3) |
+					       _field_from_8 (b, 3, 0)];
+    }
+
+    GC xgc = XCreateGC (surface->dpy, surface->drawable, GCForeground,
+			&gcv);
+    if (!xgc)
+	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+    for (i = 0; i < num_rects; i++) {
+	XFillRectangle (surface->dpy, surface->drawable, xgc,
+			rects[i].x, rects[i].y,
+			rects[i].width, rects[i].height);
+    }
+    XFreeGC(surface->dpy, xgc);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
 _cairo_xlib_surface_fill_rectangles (void		     *abstract_surface,
 				     cairo_operator_t	      op,
 				     const cairo_color_t     *color,
 				     cairo_rectangle_int_t   *rects,
-				     int			      num_rects)
+				     int		      num_rects)
 {
     cairo_xlib_surface_t *surface = abstract_surface;
     XRenderColor render_color;
@@ -1629,8 +1684,15 @@ _cairo_xlib_surface_fill_rectangles (void		     *abstract_surface,
 
     _cairo_xlib_display_notify (surface->screen_info->display);
 
-    if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface))
+    if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface)) {
+	if (op == CAIRO_OPERATOR_CLEAR ||
+	   ((op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER) &&
+	    CAIRO_COLOR_IS_OPAQUE(color))) {
+	    return _cairo_xlib_surface_solid_fill_rectangles(surface, color,
+							     rects, num_rects);
+	}
 	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
 
     render_color.red   = color->red_short;
     render_color.green = color->green_short;
commit f90b155b5a59211bed7502b537dbf207b3d4bf5e
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Tue May 27 04:41:03 2008 -0400

    [cairo-xlib] Delay using fallback if xrender is not available
    
    So we can use XCopyArea when Render is not available.  Based on patch by
    Ginn Chen.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index ec66c4d..17d511c 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1407,6 +1407,9 @@ _recategorize_composite_operation (cairo_xlib_surface_t	      *dst,
     if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
 	return DO_UNSUPPORTED;
 
+    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
+	return DO_UNSUPPORTED;
+
     return DO_RENDER;
 }
 
@@ -1475,9 +1478,6 @@ _cairo_xlib_surface_composite (cairo_operator_t		op,
 
     _cairo_xlib_display_notify (dst->screen_info->display);
 
-    if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
     operation = _categorize_composite_operation (dst, op, src_pattern,
 						 mask_pattern != NULL);
     if (operation == DO_UNSUPPORTED)
commit 30a16df29ba434d298d0c8d9dbb70c1b0a398f35
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon May 26 19:56:09 2008 -0400

    [util/backtrace-symbols] Implement backtrace_symbols_fd()

diff --git a/util/backtrace-symbols.c b/util/backtrace-symbols.c
index e6ac256..1365b83 100644
--- a/util/backtrace-symbols.c
+++ b/util/backtrace-symbols.c
@@ -359,3 +359,21 @@ char **backtrace_symbols(void *const *buffer, int size)
 
 	return final;
 }
+
+void
+backtrace_symbols_fd(void *const *buffer, int size, int fd)
+{
+        int j;
+        char **strings;
+
+        strings = backtrace_symbols(buffer, size);
+        if (strings == NULL) {
+		perror("backtrace_symbols");
+		exit(EXIT_FAILURE);
+        }
+
+        for (j = 0; j < size; j++)
+		printf("%s\n", strings[j]);
+
+        free(strings);
+}


More information about the cairo-commit mailing list