[Fontconfig] fontconfig: Branch 'wip/threadsafe' - 16 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Sun Oct 7 14:47:15 PDT 2012
COPYING | 1
configure.ac | 38 ++++++
m4/ax_pthread.m4 | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/Makefile.am | 2
src/fcarch.c | 2
src/fcatomic.c | 3
src/fcatomic.h | 123 +++++++++++++++++++++
src/fccache.c | 40 +++----
src/fccfg.c | 87 +++++++++++----
src/fccharset.c | 25 ++--
src/fcdbg.c | 20 +--
src/fcdefault.c | 88 +++++++++++----
src/fcformat.c | 2
src/fcfreetype.c | 3
src/fcfs.c | 1
src/fcinit.c | 29 +----
src/fcint.h | 39 +++++-
src/fclang.c | 43 ++++---
src/fclist.c | 1
src/fcmatch.c | 4
src/fcmatrix.c | 2
src/fcmutex.h | 126 ++++++++++++++++++++++
src/fcname.c | 4
src/fcobjs.c | 2
src/fcpat.c | 19 +--
src/fcstr.c | 39 +++---
src/fcxml.c | 4
27 files changed, 864 insertions(+), 192 deletions(-)
New commits:
commit fc45f436a3e73bae025cd565638f8898ab5102a3
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 17:46:12 2012 -0400
Minor
diff --git a/src/fccfg.c b/src/fccfg.c
index ecff6d1..4fc6f36 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -1702,7 +1702,7 @@ FcConfigSubstitute (FcConfig *config,
# define WIN32_EXTRA_LEAN
# include <windows.h>
-static FcChar8 fontconfig_path[1000] = "";
+static FcChar8 fontconfig_path[1000] = ""; /* MT-dontcare */
# if (defined (PIC) || defined (DLL_EXPORT))
@@ -1879,7 +1879,7 @@ FcConfigFreePath (FcChar8 **path)
free (path);
}
-static FcBool _FcConfigHomeEnabled = FcTrue;
+static FcBool _FcConfigHomeEnabled = FcTrue; /* MT-goodenough */
FcChar8 *
FcConfigHome (void)
commit 98b81e0b2a1b10c070ec2b74ca7b254b2e055575
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 17:42:18 2012 -0400
Make FcCacheIsMmapSafe() threadsafe
diff --git a/src/fccache.c b/src/fccache.c
index 8c449a9..bf50f56 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -57,26 +57,32 @@ static void MD5Transform(FcChar32 buf[4], FcChar32 in[16]);
static FcBool
FcCacheIsMmapSafe (int fd)
{
- static FcBool is_initialized = FcFalse;
- static FcBool is_env_available = FcFalse;
- static FcBool use_mmap = FcFalse;
+ enum {
+ MMAP_NOT_INITIALIZED = 0,
+ MMAP_USE,
+ MMAP_DONT_USE,
+ MMAP_CHECK_FS,
+ } status;
+ static void *static_status;
- if (!is_initialized)
- {
- const char *env;
+ status = (int) fc_atomic_ptr_get (&static_status);
- env = getenv ("FONTCONFIG_USE_MMAP");
- if (env)
- {
- if (FcNameBool ((const FcChar8 *)env, &use_mmap))
- is_env_available = FcTrue;
- }
- is_initialized = FcTrue;
+ if (status == MMAP_NOT_INITIALIZED)
+ {
+ const char *env = getenv ("FONTCONFIG_USE_MMAP");
+ FcBool use;
+ if (env && FcNameBool ((const FcChar8 *) env, &use))
+ status = use ? MMAP_USE : MMAP_DONT_USE;
+ else
+ status = MMAP_CHECK_FS;
+ fc_atomic_ptr_cmpexch (&static_status, NULL, (void *) status);
}
- if (is_env_available)
- return use_mmap;
- return FcIsFsMmapSafe (fd);
+ if (status == MMAP_CHECK_FS)
+ return FcIsFsMmapSafe (fd);
+ else
+ return status == MMAP_USE;
+
}
static const char bin2hex[] = { '0', '1', '2', '3',
commit 6fd40c71fa138ce6e90136dd0c1dbea4284c8956
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 17:41:58 2012 -0400
Fix FcDefaultFini()
Oops.
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 00caee3..88e6142 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -110,12 +110,12 @@ FcDefaultFini (void)
FcStrSet *langs;
lang = fc_atomic_ptr_get (&default_lang);
- if (fc_atomic_ptr_cmpexch (&default_lang, lang, NULL)) {
+ if (lang && fc_atomic_ptr_cmpexch (&default_lang, lang, NULL)) {
free (lang);
}
langs = fc_atomic_ptr_get (&default_langs);
- if (fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
+ if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
FcRefInit (&langs->ref, 1);
FcStrSetDestroy (langs);
}
commit 9ea420ea0ff230e2a7131dbb67c68a0180507863
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 17:29:45 2012 -0400
Minor
diff --git a/src/fcinit.c b/src/fcinit.c
index ecb28e4..ea24ec9 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -159,8 +159,7 @@ FcInitReinitialize (void)
config = FcInitLoadConfigAndFonts ();
if (!config)
return FcFalse;
- FcConfigSetCurrent (config);
- return FcTrue;
+ return FcConfigSetCurrent (config);
}
FcBool
commit e16aa7370aa13482bd5259fd45804a5fb6564029
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 17:02:50 2012 -0400
Make default-FcConfig threadsafe
diff --git a/src/fccfg.c b/src/fccfg.c
index 97f595a..ecff6d1 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -22,6 +22,8 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/* Objects MT-safe for readonly access. */
+
#include "fcint.h"
#include <dirent.h>
#include <sys/types.h>
@@ -36,29 +38,40 @@
#define R_OK 4
#endif
-static FcConfig *_fcConfig;
+static FcConfig *_fcConfig; /* MT-safe */
-FcBool
-FcConfigInit (void)
+static FcConfig *
+FcConfigEnsure (void)
{
FcConfig *config;
-
- if (_fcConfig)
- return FcTrue;
- config = FcInitLoadConfigAndFonts ();
+retry:
+ config = fc_atomic_ptr_get (&_fcConfig);
if (!config)
- return FcFalse;
- FcConfigSetCurrent (config);
- if (FcDebug() & FC_DBG_MEMORY)
- FcMemReport ();
- return FcTrue;
+ {
+ config = FcInitLoadConfigAndFonts ();
+ if (FcDebug() & FC_DBG_MEMORY)
+ FcMemReport ();
+
+ if (!fc_atomic_ptr_cmpexch (&_fcConfig, NULL, config)) {
+ FcConfigDestroy (config);
+ goto retry;
+ }
+ }
+ return config;
+}
+
+FcBool
+FcConfigInit (void)
+{
+ return FcConfigEnsure ? FcTrue : FcFalse;
}
void
FcConfigFini (void)
{
- if (_fcConfig)
- FcConfigDestroy (_fcConfig);
+ FcConfig *cfg = fc_atomic_ptr_get (&_fcConfig);
+ if (cfg && fc_atomic_ptr_cmpexch (&_fcConfig, cfg, NULL))
+ FcConfigDestroy (cfg);
}
@@ -263,8 +276,7 @@ FcConfigDestroy (FcConfig *config)
if (FcRefDec (&config->ref) != 1)
return;
- if (config == _fcConfig)
- _fcConfig = 0;
+ fc_atomic_ptr_cmpexch (&_fcConfig, config, NULL);
FcStrSetDestroy (config->configDirs);
FcStrSetDestroy (config->fontDirs);
@@ -419,25 +431,31 @@ FcConfigBuildFonts (FcConfig *config)
FcBool
FcConfigSetCurrent (FcConfig *config)
{
- if (config == _fcConfig)
+ FcConfig *cfg;
+
+retry:
+ cfg = fc_atomic_ptr_get (&_fcConfig);
+
+ if (config == cfg)
return FcTrue;
if (!config->fonts)
if (!FcConfigBuildFonts (config))
return FcFalse;
- if (_fcConfig)
- FcConfigDestroy (_fcConfig);
- _fcConfig = config;
+ if (!fc_atomic_ptr_cmpexch (&_fcConfig, cfg, config))
+ goto retry;
+
+ if (cfg)
+ FcConfigDestroy (cfg);
+
return FcTrue;
}
FcConfig *
FcConfigGetCurrent (void)
{
- if (!_fcConfig)
- FcConfigInit ();
- return _fcConfig;
+ return FcConfigEnsure ();
}
FcBool
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 6c4eed2..00caee3 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -118,7 +118,6 @@ FcDefaultFini (void)
if (fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
FcRefInit (&langs->ref, 1);
FcStrSetDestroy (langs);
- langs = NULL;
}
}
commit baa5e7c3c94a2b5b1785b2177aafa1eba316fae8
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 16:42:36 2012 -0400
Minor
diff --git a/src/fccfg.c b/src/fccfg.c
index 7ad0da5..97f595a 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -436,8 +436,7 @@ FcConfig *
FcConfigGetCurrent (void)
{
if (!_fcConfig)
- if (!FcConfigInit ())
- return 0;
+ FcConfigInit ();
return _fcConfig;
}
commit eea5a914375e97b979c5cc247b95b3977f02329b
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 16:37:03 2012 -0400
Refactor; contain default config in fccfg.c
diff --git a/src/fccfg.c b/src/fccfg.c
index 7090090..7ad0da5 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -36,7 +36,31 @@
#define R_OK 4
#endif
-FcConfig *_fcConfig;
+static FcConfig *_fcConfig;
+
+FcBool
+FcConfigInit (void)
+{
+ FcConfig *config;
+
+ if (_fcConfig)
+ return FcTrue;
+ config = FcInitLoadConfigAndFonts ();
+ if (!config)
+ return FcFalse;
+ FcConfigSetCurrent (config);
+ if (FcDebug() & FC_DBG_MEMORY)
+ FcMemReport ();
+ return FcTrue;
+}
+
+void
+FcConfigFini (void)
+{
+ if (_fcConfig)
+ FcConfigDestroy (_fcConfig);
+}
+
FcConfig *
FcConfigCreate (void)
@@ -412,7 +436,7 @@ FcConfig *
FcConfigGetCurrent (void)
{
if (!_fcConfig)
- if (!FcInit ())
+ if (!FcConfigInit ())
return 0;
return _fcConfig;
}
diff --git a/src/fcinit.c b/src/fcinit.c
index f6919ed..ecb28e4 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -132,17 +132,7 @@ FcInitLoadConfigAndFonts (void)
FcBool
FcInit (void)
{
- FcConfig *config;
-
- if (_fcConfig)
- return FcTrue;
- config = FcInitLoadConfigAndFonts ();
- if (!config)
- return FcFalse;
- FcConfigSetCurrent (config);
- if (FcDebug() & FC_DBG_MEMORY)
- FcMemReport ();
- return FcTrue;
+ return FcConfigInit ();
}
/*
@@ -151,9 +141,7 @@ FcInit (void)
void
FcFini (void)
{
- if (_fcConfig)
- FcConfigDestroy (_fcConfig);
-
+ FcConfigFini ();
FcCacheFini ();
FcDefaultFini ();
if (FcDebug() & FC_DBG_MEMORY)
diff --git a/src/fcint.h b/src/fcint.h
index 8b2225b..795784c 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -528,8 +528,6 @@ struct _FcConfig {
FcExprPage *expr_pool; /* pool of FcExpr's */
};
-extern FcPrivate FcConfig *_fcConfig;
-
typedef struct _FcFileTime {
time_t time;
FcBool set;
@@ -592,6 +590,12 @@ FcDirCacheReference (FcCache *cache, int nref);
/* fccfg.c */
+FcPrivate FcBool
+FcConfigInit (void);
+
+FcPrivate void
+FcConfigFini (void);
+
FcPrivate FcChar8 *
FcConfigXdgCacheHome (void);
diff --git a/src/fcxml.c b/src/fcxml.c
index 5edc867..befcf50 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -1068,7 +1068,7 @@ FcPStackPop (FcConfigParse *parse)
}
static FcBool
-FcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
+FcConfigParseInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
{
parse->pstack = 0;
parse->pstack_static_used = 0;
@@ -2932,7 +2932,7 @@ FcConfigParseAndLoad (FcConfig *config,
if (!p)
goto bail1;
- if (!FcConfigInit (&parse, name, config, p))
+ if (!FcConfigParseInit (&parse, name, config, p))
goto bail2;
#ifndef ENABLE_LIBXML2
commit 1ea981331bcd7e7913c1cdd76a66fef52816dda2
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 16:26:53 2012 -0400
Make FcDefaultFini() threadsafe
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 3066f13..6c4eed2 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -106,14 +106,19 @@ retry:
void
FcDefaultFini (void)
{
- if (default_lang) {
- free (default_lang);
- default_lang = NULL;
+ FcChar8 *lang;
+ FcStrSet *langs;
+
+ lang = fc_atomic_ptr_get (&default_lang);
+ if (fc_atomic_ptr_cmpexch (&default_lang, lang, NULL)) {
+ free (lang);
}
- if (default_langs) {
- FcRefInit (&default_langs->ref, 1);
- FcStrSetDestroy (default_langs);
- default_langs = NULL;
+
+ langs = fc_atomic_ptr_get (&default_langs);
+ if (fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
+ FcRefInit (&langs->ref, 1);
+ FcStrSetDestroy (langs);
+ langs = NULL;
}
}
commit 180b4203d781e93f2bc322240353bd36d4f65df1
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 16:09:35 2012 -0400
Make FcInitDebug() idempotent
diff --git a/src/fcdbg.c b/src/fcdbg.c
index ba1c35b..aa519e4 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -430,15 +430,17 @@ int FcDebugVal;
void
FcInitDebug (void)
{
- char *e;
+ if (!FcDebugVal) {
+ char *e;
- e = getenv ("FC_DEBUG");
- if (e)
- {
- printf ("FC_DEBUG=%s\n", e);
- FcDebugVal = atoi (e);
- if (FcDebugVal < 0)
- FcDebugVal = 0;
+ e = getenv ("FC_DEBUG");
+ if (e)
+ {
+ printf ("FC_DEBUG=%s\n", e);
+ FcDebugVal = atoi (e);
+ if (FcDebugVal < 0)
+ FcDebugVal = 0;
+ }
}
}
#define __fcdbg__
commit 13d3438ba6a62cadeed2874ffb6da5f318c2a0e6
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 16:07:57 2012 -0400
Mark some vars as MT-dontcare
diff --git a/src/fcinit.c b/src/fcinit.c
index f4ba31d..f6919ed 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -239,12 +239,12 @@ static struct {
{ "sharedstr" },
};
-static int FcAllocCount, FcAllocMem;
-static int FcFreeCount, FcFreeMem;
+static int FcAllocCount, FcAllocMem; /* MT-dontcare */
+static int FcFreeCount, FcFreeMem; /* MT-dontcare */
-static int FcMemNotice = 1*1024*1024;
+static const int FcMemNotice = 1*1024*1024;
-static int FcAllocNotify, FcFreeNotify;
+static int FcAllocNotify, FcFreeNotify; /* MT-dontcare */
void
FcMemReport (void)
commit 8e9ec4c5014372223a138ffc5a8816d018db4059
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 16:04:49 2012 -0400
Remove unused macro
diff --git a/src/fcstr.c b/src/fcstr.c
index d1d3be6..866beb7 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -78,8 +78,6 @@ FcStrFree (FcChar8 *s)
#define FcCaseFoldUpperCount(cf) \
((cf)->method == FC_CASE_FOLD_FULL ? 1 : (cf)->count)
-#define FC_STR_CANON_BUF_LEN 1024
-
typedef struct _FcCaseWalker {
const FcChar8 *read;
const FcChar8 *src;
commit afbf466854bd1d6e2dee2998cd66c82b6dda4e66
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 15:52:25 2012 -0400
Make FcGetDefaultLang and FcGetDefaultLangs thread-safe
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 2b26bce..3066f13 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -24,6 +24,8 @@
#include "fcint.h"
+/* MT-safe */
+
static const struct {
FcObject field;
FcBool value;
@@ -31,7 +33,6 @@ static const struct {
{ FC_HINTING_OBJECT, FcTrue }, /* !FT_LOAD_NO_HINTING */
{ FC_VERTICAL_LAYOUT_OBJECT, FcFalse }, /* FC_LOAD_VERTICAL_LAYOUT */
{ FC_AUTOHINT_OBJECT, FcFalse }, /* FC_LOAD_FORCE_AUTOHINT */
- /* XXX: FC_GLOBAL_ADVANCE is deprecated */
{ FC_GLOBAL_ADVANCE_OBJECT, FcTrue }, /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
{ FC_EMBEDDED_BITMAP_OBJECT, FcTrue }, /* !FC_LOAD_NO_BITMAP */
{ FC_DECORATIVE_OBJECT, FcFalse },
@@ -39,45 +40,81 @@ static const struct {
#define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
+FcStrSet *default_langs;
+
FcStrSet *
FcGetDefaultLangs (void)
{
- FcStrSet *result = FcStrSetCreate ();
- char *langs;
-
- langs = getenv ("FC_LANG");
- if (!langs || !langs[0])
- langs = getenv ("LC_ALL");
- if (!langs || !langs[0])
- langs = getenv ("LC_CTYPE");
- if (!langs || !langs[0])
- langs = getenv ("LANG");
- if (langs && langs[0])
+ FcStrSet *result;
+retry:
+ result = (FcStrSet *) fc_atomic_ptr_get (&default_langs);
+ if (!result)
{
- if (!FcStrSetAddLangs (result, langs))
+ char *langs;
+
+ result = FcStrSetCreate ();
+
+ langs = getenv ("FC_LANG");
+ if (!langs || !langs[0])
+ langs = getenv ("LC_ALL");
+ if (!langs || !langs[0])
+ langs = getenv ("LC_CTYPE");
+ if (!langs || !langs[0])
+ langs = getenv ("LANG");
+ if (langs && langs[0])
+ {
+ if (!FcStrSetAddLangs (result, langs))
+ FcStrSetAdd (result, (const FcChar8 *) "en");
+ }
+ else
FcStrSetAdd (result, (const FcChar8 *) "en");
+
+ FcRefSetConst (&result->ref);
+ if (!fc_atomic_ptr_cmpexch (&default_langs, NULL, result)) {
+ FcRefInit (&result->ref, 1);
+ FcStrSetDestroy (result);
+ goto retry;
+ }
}
- else
- FcStrSetAdd (result, (const FcChar8 *) "en");
return result;
}
+static FcChar8 *default_lang; /* MT-safe */
+
FcChar8 *
FcGetDefaultLang (void)
{
- static FcChar8 lang_local[128] = {0};
- FcStrSet *langs;
-
- if (!lang_local[0])
+ FcChar8 *lang;
+retry:
+ lang = fc_atomic_ptr_get (&default_lang);
+ if (!lang)
{
- langs = FcGetDefaultLangs ();
- strncpy ((char *)lang_local, (const char *)langs->strs[0], 127);
- lang_local[127] = 0;
+ FcStrSet *langs = FcGetDefaultLangs ();
+ lang = (FcChar8 *) strdup ((const char *) langs->strs[0]);
FcStrSetDestroy (langs);
+
+ if (!fc_atomic_ptr_cmpexch (&default_lang, NULL, lang)) {
+ free (lang);
+ goto retry;
+ }
}
- return lang_local;
+ return lang;
+}
+
+void
+FcDefaultFini (void)
+{
+ if (default_lang) {
+ free (default_lang);
+ default_lang = NULL;
+ }
+ if (default_langs) {
+ FcRefInit (&default_langs->ref, 1);
+ FcStrSetDestroy (default_langs);
+ default_langs = NULL;
+ }
}
void
diff --git a/src/fcinit.c b/src/fcinit.c
index 69b17ff..f4ba31d 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -155,6 +155,7 @@ FcFini (void)
FcConfigDestroy (_fcConfig);
FcCacheFini ();
+ FcDefaultFini ();
if (FcDebug() & FC_DBG_MEMORY)
FcMemReport ();
}
diff --git a/src/fcint.h b/src/fcint.h
index a4ca8a9..8b2225b 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -780,6 +780,9 @@ FcInitDebug (void);
FcPrivate FcChar8 *
FcGetDefaultLang (void);
+FcPrivate void
+FcDefaultFini (void);
+
/* fcdir.c */
FcPrivate FcBool
diff --git a/src/fcstr.c b/src/fcstr.c
index 842f85c..d1d3be6 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -1245,6 +1245,10 @@ FcStrSetDestroy (FcStrSet *set)
{
int i;
+ /* We rely on this in FcGetDefaultLangs for caching. */
+ if (FcRefIsConst (&set->ref))
+ return;
+
if (FcRefDec (&set->ref) != 1)
return;
commit 336916dce0ef11ed08d61b6dd24e8b8de0c0d36c
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 15:35:47 2012 -0400
Minor include cleanup
diff --git a/src/fcarch.c b/src/fcarch.c
index 44548fc..c79f051 100644
--- a/src/fcarch.c
+++ b/src/fcarch.c
@@ -21,8 +21,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <stdio.h>
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
diff --git a/src/fcatomic.c b/src/fcatomic.c
index 350744a..46217d5 100644
--- a/src/fcatomic.c
+++ b/src/fcatomic.c
@@ -51,9 +51,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <time.h>
#ifdef _WIN32
#define mkdir(path,mode) _mkdir(path)
diff --git a/src/fccache.c b/src/fccache.c
index 81985df..8c449a9 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -25,8 +25,6 @@
#endif
#include "fcint.h"
#include "fcarch.h"
-#include <stdio.h>
-#include <stdlib.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
diff --git a/src/fccharset.c b/src/fccharset.c
index a03e546..f6d2194 100644
--- a/src/fccharset.c
+++ b/src/fccharset.c
@@ -23,7 +23,6 @@
*/
#include "fcint.h"
-#include <stdlib.h>
/* #define CHECK */
diff --git a/src/fcdbg.c b/src/fcdbg.c
index a1ed2b2..ba1c35b 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -23,8 +23,6 @@
*/
#include "fcint.h"
-#include <stdio.h>
-#include <stdlib.h>
static void
_FcValuePrint (const FcValue v)
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 8ad1b1e..2b26bce 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -23,7 +23,6 @@
*/
#include "fcint.h"
-#include <string.h>
static const struct {
FcObject field;
diff --git a/src/fcformat.c b/src/fcformat.c
index 8eef7bb..10f9a18 100644
--- a/src/fcformat.c
+++ b/src/fcformat.c
@@ -23,8 +23,6 @@
*/
#include "fcint.h"
-#include <stdlib.h>
-#include <string.h>
#include <stdarg.h>
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index fb2b0f2..58ee7cf 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -46,9 +46,6 @@
#include "fcint.h"
#include "fcftint.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_TRUETYPE_TABLES_H
diff --git a/src/fcfs.c b/src/fcfs.c
index 6625687..fb55d07 100644
--- a/src/fcfs.c
+++ b/src/fcfs.c
@@ -23,7 +23,6 @@
*/
#include "fcint.h"
-#include <stdlib.h>
FcFontSet *
FcFontSetCreate (void)
diff --git a/src/fcinit.c b/src/fcinit.c
index 9c3adb5..69b17ff 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -23,7 +23,6 @@
*/
#include "fcint.h"
-#include <stdlib.h>
static FcConfig *
FcInitFallbackConfig (void)
diff --git a/src/fclist.c b/src/fclist.c
index 56f0432..9790593 100644
--- a/src/fclist.c
+++ b/src/fclist.c
@@ -23,7 +23,6 @@
*/
#include "fcint.h"
-#include <stdlib.h>
FcObjectSet *
FcObjectSetCreate (void)
diff --git a/src/fcmatrix.c b/src/fcmatrix.c
index f0c6139..1e7129c 100644
--- a/src/fcmatrix.c
+++ b/src/fcmatrix.c
@@ -24,8 +24,6 @@
#include "fcint.h"
#include <math.h>
-#include <stdlib.h>
-#include <ctype.h>
const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
diff --git a/src/fcname.c b/src/fcname.c
index e85ff76..272e37e 100644
--- a/src/fcname.c
+++ b/src/fcname.c
@@ -23,10 +23,6 @@
*/
#include "fcint.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
static const FcObjectType FcObjects[] = {
#define FC_OBJECT(NAME, Type) { FC_##NAME, Type },
diff --git a/src/fcobjs.c b/src/fcobjs.c
index 0e80b49..75bb848 100644
--- a/src/fcobjs.c
+++ b/src/fcobjs.c
@@ -26,8 +26,6 @@
#include "fcobjshash.h"
-#include <string.h>
-
int
FcObjectLookupIdByName (const char *str)
{
diff --git a/src/fcstr.c b/src/fcstr.c
index bbf42cc..842f85c 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -23,9 +23,6 @@
*/
#include "fcint.h"
-#include <stdlib.h>
-#include <ctype.h>
-#include <string.h>
#ifdef HAVE_REGEX_H
#include <regex.h>
#endif
commit b9c06fd6272b2960c0d62560a2f051c3036e1ff6
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 14:41:38 2012 -0400
Make refcounts, patterns, charsets, strings, and FcLang thread-safe
diff --git a/src/fcatomic.h b/src/fcatomic.h
index 7479a3d..c066d12 100644
--- a/src/fcatomic.h
+++ b/src/fcatomic.h
@@ -63,7 +63,7 @@ static inline void HBMemoryBarrier (void) {
}
#endif
-typedef long fc_atomic_int_t;
+typedef int fc_atomic_int_t;
#define fc_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
#define fc_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P))
@@ -74,7 +74,7 @@ typedef long fc_atomic_int_t;
#include <libkern/OSAtomic.h>
-typedef int32_t fc_atomic_int_t;
+typedef int fc_atomic_int_t;
#define fc_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
#define fc_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P))
@@ -111,13 +111,13 @@ typedef int fc_atomic_int_t;
#endif
/* reference count */
-#define FC_REF_CONSTANT ((fc_atomic_int_t) -1)
-#define FC_REF_CONSTANT_INIT {FC_REF_CONSTANT}
+#define FC_REF_CONSTANT_VALUE ((fc_atomic_int_t) -1)
+#define FC_REF_CONSTANT {FC_REF_CONSTANT_VALUE}
typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
-static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
-static inline int FcRefInc (FcRef *r) { return fc_atomic_int_add (r->count, +1); }
-static inline int FcRefDec (FcRef *r) { return fc_atomic_int_add (r->count, -1); }
-static inline void FcRefFinish (FcRef *r) { r->count = FC_REF_CONSTANT; }
-static inline FcBool FcRefIsConst (FcRef *r) { return r->count == FC_REF_CONSTANT; }
+static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
+static inline int FcRefInc (FcRef *r) { return fc_atomic_int_add (r->count, +1); }
+static inline int FcRefDec (FcRef *r) { return fc_atomic_int_add (r->count, -1); }
+static inline void FcRefSetConst (FcRef *r) { r->count = FC_REF_CONSTANT_VALUE; }
+static inline FcBool FcRefIsConst (const FcRef *r) { return r->count == FC_REF_CONSTANT_VALUE; }
#endif /* _FCATOMIC_H_ */
diff --git a/src/fccfg.c b/src/fccfg.c
index d3752e5..7090090 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -95,7 +95,7 @@ FcConfigCreate (void)
config->expr_pool = NULL;
- config->ref = 1;
+ FcRefInit (&config->ref, 1);
return config;
@@ -225,7 +225,7 @@ FcConfigReference (FcConfig *config)
return 0;
}
- config->ref++;
+ FcRefInc (&config->ref);
return config;
}
@@ -236,7 +236,7 @@ FcConfigDestroy (FcConfig *config)
FcSetName set;
FcExprPage *page;
- if (--config->ref > 0)
+ if (FcRefDec (&config->ref) != 1)
return;
if (config == _fcConfig)
@@ -669,7 +669,7 @@ typedef struct _FcSubState {
} FcSubState;
static FcValue
-FcConfigPromote (FcValue v, FcValue u)
+FcConfigPromote (FcValue v, FcValue u, FcValuePromotionBuffer *buf)
{
if (v.type == FcTypeInteger)
{
@@ -683,7 +683,8 @@ FcConfigPromote (FcValue v, FcValue u)
}
else if (v.type == FcTypeString && u.type == FcTypeLangSet)
{
- v.u.l = FcLangSetPromote (v.u.s);
+ assert (buf != NULL);
+ v.u.l = FcLangSetPromote (v.u.s, buf);
v.type = FcTypeLangSet;
}
return v;
@@ -699,9 +700,10 @@ FcConfigCompareValue (const FcValue *left_o,
FcBool ret = FcFalse;
FcOp op = FC_OP_GET_OP (op_);
int flags = FC_OP_GET_FLAGS (op_);
+ FcValuePromotionBuffer buf1, buf2;
- left = FcConfigPromote (left, right);
- right = FcConfigPromote (right, left);
+ left = FcConfigPromote (left, right, &buf1);
+ right = FcConfigPromote (right, left, &buf2);
if (left.type == right.type)
{
switch (left.type) {
@@ -964,8 +966,8 @@ FcConfigEvaluate (FcPattern *p, FcExpr *e)
case FcOpDivide:
vl = FcConfigEvaluate (p, e->u.tree.left);
vr = FcConfigEvaluate (p, e->u.tree.right);
- vl = FcConfigPromote (vl, vr);
- vr = FcConfigPromote (vr, vl);
+ vl = FcConfigPromote (vl, vr, NULL);
+ vr = FcConfigPromote (vr, vl, NULL);
if (vl.type == vr.type)
{
switch (vl.type) {
diff --git a/src/fccharset.c b/src/fccharset.c
index 8c1d858..a03e546 100644
--- a/src/fccharset.c
+++ b/src/fccharset.c
@@ -36,7 +36,7 @@ FcCharSetCreate (void)
if (!fcs)
return 0;
FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
- fcs->ref = 1;
+ FcRefInit (&fcs->ref, 1);
fcs->num = 0;
fcs->leaves_offset = 0;
fcs->numbers_offset = 0;
@@ -56,12 +56,12 @@ FcCharSetDestroy (FcCharSet *fcs)
if (fcs)
{
- if (fcs->ref == FC_REF_CONSTANT)
+ if (FcRefIsConst (&fcs->ref))
{
FcCacheObjectDereference (fcs);
return;
}
- if (--fcs->ref > 0)
+ if (FcRefDec (&fcs->ref) != 1)
return;
for (i = 0; i < fcs->num; i++)
{
@@ -255,7 +255,7 @@ FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf;
FcChar32 *b;
- if (fcs == NULL || fcs->ref == FC_REF_CONSTANT)
+ if (fcs == NULL || FcRefIsConst (&fcs->ref))
return FcFalse;
leaf = FcCharSetFindLeafCreate (fcs, ucs4);
if (!leaf)
@@ -271,7 +271,7 @@ FcCharSetDelChar (FcCharSet *fcs, FcChar32 ucs4)
FcCharLeaf *leaf;
FcChar32 *b;
- if (fcs == NULL || fcs->ref == FC_REF_CONSTANT)
+ if (fcs == NULL || FcRefIsConst (&fcs->ref))
return FcFalse;
leaf = FcCharSetFindLeaf (fcs, ucs4);
if (!leaf)
@@ -347,8 +347,8 @@ FcCharSetCopy (FcCharSet *src)
{
if (src)
{
- if (src->ref != FC_REF_CONSTANT)
- src->ref++;
+ if (!FcRefIsConst (&src->ref))
+ FcRefInc (&src->ref);
else
FcCacheObjectReference (src);
}
@@ -506,7 +506,7 @@ FcCharSetMerge (FcCharSet *a, const FcCharSet *b, FcBool *changed)
if (!a || !b)
return FcFalse;
- if (a->ref == FC_REF_CONSTANT) {
+ if (FcRefIsConst (&a->ref)) {
if (changed)
*changed = FcFalse;
return FcFalse;
@@ -1227,7 +1227,7 @@ FcCharSetFreezeBase (FcCharSetFreezer *freezer, FcCharSet *fcs, const FcCharSet
freezer->charsets_allocated++;
- ent->set.ref = FC_REF_CONSTANT;
+ FcRefSetConst (&ent->set.ref);
ent->set.num = fcs->num;
if (fcs->num)
{
@@ -1374,7 +1374,7 @@ FcCharSetSerializeAlloc (FcSerialize *serialize, const FcCharSet *cs)
FcChar16 *numbers;
int i;
- if (cs->ref != FC_REF_CONSTANT)
+ if (!FcRefIsConst (&cs->ref))
{
if (!serialize->cs_freezer)
{
@@ -1413,7 +1413,7 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
FcCharLeaf *leaf, *leaf_serialized;
int i;
- if (cs->ref != FC_REF_CONSTANT && serialize->cs_freezer)
+ if (!FcRefIsConst (&cs->ref) && serialize->cs_freezer)
{
cs = FcCharSetFindFrozen (serialize->cs_freezer, cs);
if (!cs)
@@ -1424,7 +1424,7 @@ FcCharSetSerialize(FcSerialize *serialize, const FcCharSet *cs)
if (!cs_serialized)
return NULL;
- cs_serialized->ref = FC_REF_CONSTANT;
+ FcRefSetConst (&cs_serialized->ref);
cs_serialized->num = cs->num;
if (cs->num)
diff --git a/src/fcint.h b/src/fcint.h
index 09cc448..a4ca8a9 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -40,6 +40,7 @@
#endif
#include <string.h>
#include <ctype.h>
+#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <stddef.h>
@@ -142,6 +143,8 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
#define FcPrivate
#endif
+FC_ASSERT_STATIC (sizeof (FcRef) == sizeof (int));
+
typedef enum _FcValueBinding {
FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
} FcValueBinding;
@@ -222,7 +225,7 @@ struct _FcPattern {
int num;
int size;
intptr_t elts_offset;
- int ref;
+ FcRef ref;
};
#define FcPatternElts(p) FcOffsetMember(p,elts_offset,FcPatternElt)
@@ -319,7 +322,7 @@ typedef struct _FcCharLeaf {
} FcCharLeaf;
struct _FcCharSet {
- int ref; /* reference count */
+ FcRef ref; /* reference count */
int num; /* size of leaves and numbers arrays */
intptr_t leaves_offset;
intptr_t numbers_offset;
@@ -332,7 +335,7 @@ struct _FcCharSet {
#define FcCharSetNumbers(c) FcOffsetMember(c,numbers_offset,FcChar16)
struct _FcStrSet {
- int ref; /* reference count */
+ FcRef ref; /* reference count */
int num;
int size;
FcChar8 **strs;
@@ -520,7 +523,7 @@ struct _FcConfig {
time_t rescanTime; /* last time information was scanned */
int rescanInterval; /* interval between scans */
- int ref; /* reference count */
+ FcRef ref; /* reference count */
FcExprPage *expr_pool; /* pool of FcExpr's */
};
@@ -548,6 +551,17 @@ struct _FcStatFS {
FcBool is_mtime_broken;
};
+typedef struct _FcValuePromotionBuffer FcValuePromotionBuffer;
+
+struct _FcValuePromotionBuffer {
+ union {
+ double d;
+ int i;
+ long l;
+ char c[256]; /* Enlarge as needed */
+ } u;
+};
+
/* fcblanks.c */
/* fccache.c */
@@ -825,7 +839,7 @@ FcPrivate FcLangResult
FcLangCompare (const FcChar8 *s1, const FcChar8 *s2);
FcPrivate FcLangSet *
-FcLangSetPromote (const FcChar8 *lang);
+FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *buf);
FcPrivate FcLangSet *
FcNameParseLangSet (const FcChar8 *string);
diff --git a/src/fclang.c b/src/fclang.c
index b7e70fc..caa4068 100644
--- a/src/fclang.c
+++ b/src/fclang.c
@@ -22,10 +22,11 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-#include <string.h>
#include "fcint.h"
#include "fcftint.h"
+/* Objects MT-safe for readonly access. */
+
typedef struct {
const FcChar8 lang[8];
const FcCharSet charset;
@@ -695,34 +696,38 @@ FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
/*
* Used in computing values -- mustn't allocate any storage
- * XXX Not thread-safe
*/
FcLangSet *
-FcLangSetPromote (const FcChar8 *lang)
+FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *vbuf)
{
- static FcLangSet ls;
- static FcStrSet strs;
- static FcChar8 *str;
- int id;
-
- memset (ls.map, '\0', sizeof (ls.map));
- ls.map_size = NUM_LANG_SET_MAP;
- ls.extra = 0;
+ int id;
+ typedef struct {
+ FcLangSet ls;
+ FcStrSet strs;
+ FcChar8 *str;
+ } FcLangSetPromotionBuffer;
+ FcLangSetPromotionBuffer *buf = (FcLangSetPromotionBuffer *) vbuf;
+
+ FC_ASSERT_STATIC (sizeof (FcLangSetPromotionBuffer) <= sizeof (FcValuePromotionBuffer));
+
+ memset (buf->ls.map, '\0', sizeof (buf->ls.map));
+ buf->ls.map_size = NUM_LANG_SET_MAP;
+ buf->ls.extra = 0;
id = FcLangSetIndex (lang);
if (id > 0)
{
- FcLangSetBitSet (&ls, id);
+ FcLangSetBitSet (&buf->ls, id);
}
else
{
- ls.extra = &strs;
- strs.num = 1;
- strs.size = 1;
- strs.strs = &str;
- strs.ref = 1;
- str = (FcChar8 *) lang;
+ buf->ls.extra = &buf->strs;
+ buf->strs.num = 1;
+ buf->strs.size = 1;
+ buf->strs.strs = &buf->str;
+ FcRefInit (&buf->strs.ref, 1);
+ buf->str = (FcChar8 *) lang;
}
- return &ls;
+ return &buf->ls;
}
FcChar32
diff --git a/src/fcmatch.c b/src/fcmatch.c
index 623538b..0d69143 100644
--- a/src/fcmatch.c
+++ b/src/fcmatch.c
@@ -23,10 +23,6 @@
*/
#include "fcint.h"
-#include <assert.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
static double
FcCompareNumber (FcValue *value1, FcValue *value2)
diff --git a/src/fcpat.c b/src/fcpat.c
index 92b4cc4..05b307c 100644
--- a/src/fcpat.c
+++ b/src/fcpat.c
@@ -22,9 +22,8 @@
#include "fcint.h"
#include "fcftint.h"
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
+
+/* Objects MT-safe for readonly access. */
FcPattern *
FcPatternCreate (void)
@@ -38,7 +37,7 @@ FcPatternCreate (void)
p->num = 0;
p->size = 0;
p->elts_offset = FcPtrToOffset (p, NULL);
- p->ref = 1;
+ FcRefInit (&p->ref, 1);
return p;
}
@@ -280,13 +279,13 @@ FcPatternDestroy (FcPattern *p)
int i;
FcPatternElt *elts;
- if (p->ref == FC_REF_CONSTANT)
+ if (FcRefIsConst (&p->ref))
{
FcCacheObjectDereference (p);
return;
}
- if (--p->ref > 0)
+ if (FcRefDec (&p->ref) != 1)
return;
elts = FcPatternElts (p);
@@ -470,7 +469,7 @@ FcPatternObjectAddWithBinding (FcPattern *p,
FcPatternElt *e;
FcValueListPtr new, *prev;
- if (p->ref == FC_REF_CONSTANT)
+ if (FcRefIsConst (&p->ref))
goto bail0;
new = malloc (sizeof (FcValueList));
@@ -936,8 +935,8 @@ bail0:
void
FcPatternReference (FcPattern *p)
{
- if (p->ref != FC_REF_CONSTANT)
- p->ref++;
+ if (!FcRefIsConst (&p->ref))
+ FcRefInc (&p->ref);
else
FcCacheObjectReference (p);
}
@@ -1073,7 +1072,7 @@ FcPatternSerialize (FcSerialize *serialize, const FcPattern *pat)
return NULL;
*pat_serialized = *pat;
pat_serialized->size = pat->num;
- pat_serialized->ref = FC_REF_CONSTANT;
+ FcRefSetConst (&pat_serialized->ref);
elts_serialized = FcSerializePtr (serialize, elts);
if (!elts_serialized)
diff --git a/src/fcstr.c b/src/fcstr.c
index f505ea6..bbf42cc 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -33,6 +33,8 @@
#include <windows.h>
#endif
+/* Objects MT-safe for readonly access. */
+
FcChar8 *
FcStrCopy (const FcChar8 *s)
{
@@ -1088,7 +1090,7 @@ FcStrSetCreate (void)
if (!set)
return 0;
FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
- set->ref = 1;
+ FcRefInit (&set->ref, 1);
set->num = 0;
set->size = 0;
set->strs = 0;
@@ -1244,20 +1246,20 @@ FcStrSetDel (FcStrSet *set, const FcChar8 *s)
void
FcStrSetDestroy (FcStrSet *set)
{
- if (--set->ref == 0)
- {
- int i;
+ int i;
- for (i = 0; i < set->num; i++)
- FcStrFree (set->strs[i]);
- if (set->strs)
- {
- FcMemFree (FC_MEM_STRSET, (set->size + 1) * sizeof (FcChar8 *));
- free (set->strs);
- }
- FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
- free (set);
+ if (FcRefDec (&set->ref) != 1)
+ return;
+
+ for (i = 0; i < set->num; i++)
+ FcStrFree (set->strs[i]);
+ if (set->strs)
+ {
+ FcMemFree (FC_MEM_STRSET, (set->size + 1) * sizeof (FcChar8 *));
+ free (set->strs);
}
+ FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
+ free (set);
}
FcStrList *
@@ -1270,7 +1272,7 @@ FcStrListCreate (FcStrSet *set)
return 0;
FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
list->set = set;
- set->ref++;
+ FcRefInc (&set->ref);
list->n = 0;
return list;
}
commit 7d36ebb500ed0263206c4b4885d2851b982c5e9f
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 14:24:28 2012 -0400
Add thread-safety primitives
diff --git a/COPYING b/COPYING
index 2a5d777..66392b1 100644
--- a/COPYING
+++ b/COPYING
@@ -5,6 +5,7 @@ Copyright © 2005 Patrick Lam
Copyright © 2009 Roozbeh Pournader
Copyright © 2008,2009 Red Hat, Inc.
Copyright © 2008 Danilo Šegan
+Copyright © 2012 Google, Inc.
Permission to use, copy, modify, distribute, and sell this software and its
diff --git a/src/Makefile.am b/src/Makefile.am
index 3d83d3c..41633ba 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -122,6 +122,7 @@ EXTRA_DIST += \
libfontconfig_la_SOURCES = \
fcarch.h \
fcatomic.c \
+ fcatomic.h \
fcblanks.c \
fccache.c \
fccfg.c \
@@ -137,6 +138,7 @@ libfontconfig_la_SOURCES = \
fclist.c \
fcmatch.c \
fcmatrix.c \
+ fcmutex.h \
fcname.c \
fcobjs.c \
fcobjs.h \
diff --git a/src/fcatomic.h b/src/fcatomic.h
new file mode 100644
index 0000000..7479a3d
--- /dev/null
+++ b/src/fcatomic.h
@@ -0,0 +1,123 @@
+/*
+ * Mutex operations. Originally copied from HarfBuzz.
+ *
+ * Copyright © 2007 Chris Wilson
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef _FCATOMIC_H_
+#define _FCATOMIC_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+/* atomic_int */
+
+/* We need external help for these */
+
+#if 0
+
+
+#elif !defined(FC_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* mingw32 does not have MemoryBarrier.
+ * MemoryBarrier may be defined as a macro or a function.
+ * Just make a failsafe version for ourselves. */
+#ifdef MemoryBarrier
+#define HBMemoryBarrier MemoryBarrier
+#else
+static inline void HBMemoryBarrier (void) {
+ long dummy = 0;
+ InterlockedExchange (&dummy, 1);
+}
+#endif
+
+typedef long fc_atomic_int_t;
+#define fc_atomic_int_add(AI, V) InterlockedExchangeAdd (&(AI), (V))
+
+#define fc_atomic_ptr_get(P) (HBMemoryBarrier (), (void *) *(P))
+#define fc_atomic_ptr_cmpexch(P,O,N) (InterlockedCompareExchangePointer ((void **) (P), (void *) (N), (void *) (O)) == (void *) (O))
+
+
+#elif !defined(FC_NO_MT) && defined(__APPLE__)
+
+#include <libkern/OSAtomic.h>
+
+typedef int32_t fc_atomic_int_t;
+#define fc_atomic_int_add(AI, V) (OSAtomicAdd32Barrier ((V), &(AI)) - (V))
+
+#define fc_atomic_ptr_get(P) (OSMemoryBarrier (), (void *) *(P))
+#define fc_atomic_ptr_cmpexch(P,O,N) OSAtomicCompareAndSwapPtrBarrier ((void *) (O), (void *) (N), (void **) (P))
+
+
+#elif !defined(FC_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+typedef int fc_atomic_int_t;
+#define fc_atomic_int_add(AI, V) __sync_fetch_and_add (&(AI), (V))
+
+#define fc_atomic_ptr_get(P) (void *) (__sync_synchronize (), *(P))
+#define fc_atomic_ptr_cmpexch(P,O,N) __sync_bool_compare_and_swap ((P), (O), (N))
+
+
+#elif !defined(FC_NO_MT)
+
+#define FC_ATOMIC_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int fc_atomic_int_t;
+#define fc_atomic_int_add(AI, V) (((AI) += (V)) - (V))
+
+#define fc_atomic_ptr_get(P) ((void *) *(P))
+#define fc_atomic_ptr_cmpexch(P,O,N) (* (void * volatile *) (P) == (void *) (O) ? (* (void * volatile *) (P) = (void *) (N), true) : false)
+
+
+#else /* FC_NO_MT */
+
+typedef int fc_atomic_int_t;
+#define fc_atomic_int_add(AI, V) (((AI) += (V)) - (V))
+
+#define fc_atomic_ptr_get(P) ((void *) *(P))
+#define fc_atomic_ptr_cmpexch(P,O,N) (* (void **) (P) == (void *) (O) ? (* (void **) (P) = (void *) (N), true) : false)
+
+#endif
+
+/* reference count */
+#define FC_REF_CONSTANT ((fc_atomic_int_t) -1)
+#define FC_REF_CONSTANT_INIT {FC_REF_CONSTANT}
+typedef struct _FcRef { fc_atomic_int_t count; } FcRef;
+static inline void FcRefInit (FcRef *r, int v) { r->count = v; }
+static inline int FcRefInc (FcRef *r) { return fc_atomic_int_add (r->count, +1); }
+static inline int FcRefDec (FcRef *r) { return fc_atomic_int_add (r->count, -1); }
+static inline void FcRefFinish (FcRef *r) { r->count = FC_REF_CONSTANT; }
+static inline FcBool FcRefIsConst (FcRef *r) { return r->count == FC_REF_CONSTANT; }
+
+#endif /* _FCATOMIC_H_ */
diff --git a/src/fcint.h b/src/fcint.h
index 74646c7..09cc448 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -49,6 +49,8 @@
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcprivate.h>
#include "fcdeprecate.h"
+#include "fcmutex.h"
+#include "fcatomic.h"
#ifndef FC_CONFIG_PATH
#define FC_CONFIG_PATH "fonts.conf"
@@ -316,8 +318,6 @@ typedef struct _FcCharLeaf {
FcChar32 map[256/32];
} FcCharLeaf;
-#define FC_REF_CONSTANT -1
-
struct _FcCharSet {
int ref; /* reference count */
int num; /* size of leaves and numbers arrays */
diff --git a/src/fcmutex.h b/src/fcmutex.h
new file mode 100644
index 0000000..dd4487d
--- /dev/null
+++ b/src/fcmutex.h
@@ -0,0 +1,126 @@
+/*
+ * Atomic int and pointer operations. Originally copied from HarfBuzz.
+ *
+ * Copyright © 2007 Chris Wilson
+ * Copyright © 2009,2010 Red Hat, Inc.
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Contributor(s):
+ * Chris Wilson <chris at chris-wilson.co.uk>
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef _FCMUTEX_H_
+#define _FCMUTEX_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+/* mutex */
+
+/* We need external help for these */
+
+#if 0
+
+
+#elif !defined(FC_NO_MT) && defined(_MSC_VER) || defined(__MINGW32__)
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+typedef CRITICAL_SECTION fc_mutex_impl_t;
+#define FC_MUTEX_IMPL_INIT { NULL, 0, 0, NULL, NULL, 0 }
+#define fc_mutex_impl_init(M) InitializeCriticalSection (M)
+#define fc_mutex_impl_lock(M) EnterCriticalSection (M)
+#define fc_mutex_impl_unlock(M) LeaveCriticalSection (M)
+#define fc_mutex_impl_finish(M) DeleteCriticalSection (M)
+
+
+#elif !defined(FC_NO_MT) && (defined(HAVE_PTHREAD) || defined(__APPLE__))
+
+#include <pthread.h>
+typedef pthread_mutex_t fc_mutex_impl_t;
+#define FC_MUTEX_IMPL_INIT PTHREAD_MUTEX_INITIALIZER
+#define fc_mutex_impl_init(M) pthread_mutex_init (M, NULL)
+#define fc_mutex_impl_lock(M) pthread_mutex_lock (M)
+#define fc_mutex_impl_unlock(M) pthread_mutex_unlock (M)
+#define fc_mutex_impl_finish(M) pthread_mutex_destroy (M)
+
+
+#elif !defined(FC_NO_MT) && defined(HAVE_INTEL_ATOMIC_PRIMITIVES)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define FC_SCHED_YIELD() sched_yield ()
+#else
+# define FC_SCHED_YIELD() FC_STMT_START {} FC_STMT_END
+#endif
+
+/* This actually is not a totally awful implementation. */
+typedef volatile int fc_mutex_impl_t;
+#define FC_MUTEX_IMPL_INIT 0
+#define fc_mutex_impl_init(M) *(M) = 0
+#define fc_mutex_impl_lock(M) FC_STMT_START { while (__sync_lock_test_and_set((M), 1)) FC_SCHED_YIELD (); } FC_STMT_END
+#define fc_mutex_impl_unlock(M) __sync_lock_release (M)
+#define fc_mutex_impl_finish(M) FC_STMT_START {} FC_STMT_END
+
+
+#elif !defined(FC_NO_MT)
+
+#if defined(HAVE_SCHED_H) && defined(HAVE_SCHED_YIELD)
+# include <sched.h>
+# define FC_SCHED_YIELD() sched_yield ()
+#else
+# define FC_SCHED_YIELD() FC_STMT_START {} FC_STMT_END
+#endif
+
+#define FC_MUTEX_INT_NIL 1 /* Warn that fallback implementation is in use. */
+typedef volatile int fc_mutex_impl_t;
+#define FC_MUTEX_IMPL_INIT 0
+#define fc_mutex_impl_init(M) *(M) = 0
+#define fc_mutex_impl_lock(M) FC_STMT_START { while (*(M)) FC_SCHED_YIELD (); (*(M))++; } FC_STMT_END
+#define fc_mutex_impl_unlock(M) (*(M))--;
+#define fc_mutex_impl_finish(M) FC_STMT_START {} FC_STMT_END
+
+
+#else /* FC_NO_MT */
+
+typedef int fc_mutex_impl_t;
+#define FC_MUTEX_IMPL_INIT 0
+#define fc_mutex_impl_init(M) FC_STMT_START {} FC_STMT_END
+#define fc_mutex_impl_lock(M) FC_STMT_START {} FC_STMT_END
+#define fc_mutex_impl_unlock(M) FC_STMT_START {} FC_STMT_END
+#define fc_mutex_impl_finish(M) FC_STMT_START {} FC_STMT_END
+
+#endif
+
+
+#define FC_MUTEX_INIT {FC_MUTEX_IMPL_INIT}
+typedef fc_mutex_impl_t FcMutex;
+static inline void FcMutexInit (FcMutex *m) { fc_mutex_impl_init (m); }
+static inline void FcMutexLock (FcMutex *m) { fc_mutex_impl_lock (m); }
+static inline void FcMutexUnlock (FcMutex *m) { fc_mutex_impl_unlock (m); }
+static inline void FcMutexFinish (FcMutex *m) { fc_mutex_impl_finish (m); }
+
+
+#endif /* _FCMUTEX_H_ */
commit b3a3c1d4599b9dc5412bb1dc0e57b6da75b8821f
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Sun Oct 7 13:49:45 2012 -0400
Add build stuff for threadsafety primitives
Copied over from HarfBuzz.
diff --git a/configure.ac b/configure.ac
index 870979d..6796863 100644
--- a/configure.ac
+++ b/configure.ac
@@ -150,7 +150,7 @@ AC_LINK_IFELSE([AC_LANG_SOURCE([[
}
]])],[
AC_MSG_RESULT([yes])
- AC_DEFINE([HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the `posix_fadvise' function.])
+ AC_DEFINE([HAVE_POSIX_FADVISE], [1], [Define to 1 if you have the 'posix_fadvise' function.])
],[AC_MSG_RESULT([no])])
CFLAGS="$fc_saved_CFLAGS"
@@ -566,6 +566,42 @@ AC_SUBST(CONFIGDIR)
AC_SUBST(xmldir)
AC_SUBST(XMLDIR)
+
+dnl ===========================================================================
+
+#
+# Thread-safety primitives
+#
+
+AC_CACHE_CHECK([for Intel atomic primitives], fc_cv_have_intel_atomic_primitives, [
+ fc_cv_have_intel_atomic_primitives=false
+ AC_TRY_LINK([
+ void memory_barrier (void) { __sync_synchronize (); }
+ int atomic_add (int *i) { return __sync_fetch_and_add (i, 1); }
+ int mutex_trylock (int *m) { return __sync_lock_test_and_set (m, 1); }
+ void mutex_unlock (int *m) { __sync_lock_release (m); }
+ ], [], fc_cv_have_intel_atomic_primitives=true
+ )
+])
+if $fc_cv_have_intel_atomic_primitives; then
+ AC_DEFINE(HAVE_INTEL_ATOMIC_PRIMITIVES, 1, [Have Intel __sync_* atomic primitives])
+fi
+
+AC_CHECK_HEADERS(sched.h)
+AC_CHECK_FUNCS(sched_yield)
+
+have_pthread=false
+if test "$os_win32" = no; then
+ AX_PTHREAD([have_pthread=true])
+fi
+if $have_pthread; then
+ AC_DEFINE(HAVE_PTHREAD, 1, [Have POSIX threads])
+fi
+AM_CONDITIONAL(HAVE_PTHREAD, $have_pthread)
+
+
+dnl ===========================================================================
+
#
# Let people not build/install docs if they don't have docbook
#
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
new file mode 100644
index 0000000..d90de34
--- /dev/null
+++ b/m4/ax_pthread.m4
@@ -0,0 +1,309 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+# This macro figures out how to build C programs using POSIX threads. It
+# sets the PTHREAD_LIBS output variable to the threads library and linker
+# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+# flags that are needed. (The user can also force certain compiler
+# flags/libs to be tested by setting these environment variables.)
+#
+# Also sets PTHREAD_CC to any special C compiler that is needed for
+# multi-threaded programs (defaults to the value of CC otherwise). (This
+# is necessary on AIX to use the special cc_r compiler alias.)
+#
+# NOTE: You are assumed to not only compile your program with these flags,
+# but also link it with them as well. e.g. you should link with
+# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+# If you are only building threads programs, you may wish to use these
+# variables in your default LIBS, CFLAGS, and CC:
+#
+# LIBS="$PTHREAD_LIBS $LIBS"
+# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+# CC="$PTHREAD_CC"
+#
+# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
+# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+# PTHREAD_CFLAGS.
+#
+# ACTION-IF-FOUND is a list of shell commands to run if a threads library
+# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+# is not found. If ACTION-IF-FOUND is not specified, the default action
+# will define HAVE_PTHREAD.
+#
+# Please let the authors know if this macro fails on any platform, or if
+# you have any other suggestions or comments. This macro was based on work
+# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+# Alejandro Forero Cuervo to the autoconf macro repository. We are also
+# grateful for the helpful feedback of numerous users.
+#
+# Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj at alum.mit.edu>
+# Copyright (c) 2011 Daniel Richard G. <skunk at iSKUNK.ORG>
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 18
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test x"$ax_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case ${host_os} in
+ solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthreads/-mt/
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+ ;;
+
+ darwin*)
+ ax_pthread_flags="-pthread $ax_pthread_flags"
+ ;;
+esac
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ pthread-config)
+ AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
+ if test x"$ax_pthread_config" = xno; then continue; fi
+ PTHREAD_CFLAGS="`pthread-config --cflags`"
+ PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+ static void routine(void *a) { a = 0; }
+ static void *start_routine(void *a) { return a; }],
+ [pthread_t th; pthread_attr_t attr;
+ pthread_create(&th, 0, start_routine, 0);
+ pthread_join(th, 0);
+ pthread_attr_init(&attr);
+ pthread_cleanup_push(routine, 0);
+ pthread_cleanup_pop(0) /* ; */])],
+ [ax_pthread_ok=yes],
+ [])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($ax_pthread_ok)
+ if test "x$ax_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ attr_name=unknown
+ for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+ [int attr = $attr; return attr /* ; */])],
+ [attr_name=$attr; break],
+ [])
+ done
+ AC_MSG_RESULT($attr_name)
+ if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+ [Define to necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case ${host_os} in
+ aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
+ osf* | hpux*) flag="-D_REENTRANT";;
+ solaris*)
+ if test "$GCC" = "yes"; then
+ flag="-D_REENTRANT"
+ else
+ flag="-mt -D_REENTRANT"
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+ ax_cv_PTHREAD_PRIO_INHERIT, [
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
+ [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+ [ax_cv_PTHREAD_PRIO_INHERIT=no])
+ ])
+ AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+ AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with xlc_r or cc_r
+ if test x"$GCC" != xyes; then
+ AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+ else
+ PTHREAD_CC=$CC
+ fi
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ ax_pthread_ok=no
+ $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
More information about the Fontconfig
mailing list