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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxx> 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@xxxxxxxxxxxxxxxxxx> + * 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@xxxxxxxxxxxxxxxxxx> + * 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@xxxxxxxxxx> 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@xxxxxxxxxxxx> +# Copyright (c) 2011 Daniel Richard G. <skunk@xxxxxxxxxx> +# +# 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
_______________________________________________ Fontconfig mailing list Fontconfig@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/fontconfig