Make cache hash threadsafe
This concludes my first pass at making fontconfig threadsafe. Now to testing and actually fixing it!
This commit is contained in:
parent
adb03b730d
commit
68b8ae9af8
|
@ -248,6 +248,7 @@ struct _FcCacheSkip {
|
||||||
|
|
||||||
#define FC_CACHE_MAX_LEVEL 16
|
#define FC_CACHE_MAX_LEVEL 16
|
||||||
|
|
||||||
|
/* Protected by cache_lock below */
|
||||||
static FcCacheSkip *fcCacheChains[FC_CACHE_MAX_LEVEL];
|
static FcCacheSkip *fcCacheChains[FC_CACHE_MAX_LEVEL];
|
||||||
static int fcCacheMaxLevel;
|
static int fcCacheMaxLevel;
|
||||||
|
|
||||||
|
@ -383,6 +384,8 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat)
|
||||||
FcCacheSkip *s, **next;
|
FcCacheSkip *s, **next;
|
||||||
int i, level;
|
int i, level;
|
||||||
|
|
||||||
|
lock_cache ();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find links along each chain
|
* Find links along each chain
|
||||||
*/
|
*/
|
||||||
|
@ -434,11 +437,13 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat)
|
||||||
s->next[i] = *update[i];
|
s->next[i] = *update[i];
|
||||||
*update[i] = s;
|
*update[i] = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock_cache ();
|
||||||
return FcTrue;
|
return FcTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FcCacheSkip *
|
static FcCacheSkip *
|
||||||
FcCacheFindByAddr (void *object)
|
FcCacheFindByAddrUnlocked (void *object)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
FcCacheSkip **next = fcCacheChains;
|
FcCacheSkip **next = fcCacheChains;
|
||||||
|
@ -459,6 +464,16 @@ FcCacheFindByAddr (void *object)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FcCacheSkip *
|
||||||
|
FcCacheFindByAddr (void *object)
|
||||||
|
{
|
||||||
|
FcCacheSkip *ret;
|
||||||
|
lock_cache ();
|
||||||
|
ret = FcCacheFindByAddrUnlocked (object);
|
||||||
|
unlock_cache ();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FcCacheRemove (FcCache *cache)
|
FcCacheRemove (FcCache *cache)
|
||||||
{
|
{
|
||||||
|
@ -469,6 +484,7 @@ FcCacheRemove (FcCache *cache)
|
||||||
/*
|
/*
|
||||||
* Find links along each chain
|
* Find links along each chain
|
||||||
*/
|
*/
|
||||||
|
lock_cache ();
|
||||||
next = fcCacheChains;
|
next = fcCacheChains;
|
||||||
for (i = fcCacheMaxLevel; --i >= 0; )
|
for (i = fcCacheMaxLevel; --i >= 0; )
|
||||||
{
|
{
|
||||||
|
@ -482,6 +498,7 @@ FcCacheRemove (FcCache *cache)
|
||||||
*update[i] = s->next[i];
|
*update[i] = s->next[i];
|
||||||
while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL)
|
while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL)
|
||||||
fcCacheMaxLevel--;
|
fcCacheMaxLevel--;
|
||||||
|
unlock_cache ();
|
||||||
free (s);
|
free (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,14 +507,17 @@ FcCacheFindByStat (struct stat *cache_stat)
|
||||||
{
|
{
|
||||||
FcCacheSkip *s;
|
FcCacheSkip *s;
|
||||||
|
|
||||||
|
lock_cache ();
|
||||||
for (s = fcCacheChains[0]; s; s = s->next[0])
|
for (s = fcCacheChains[0]; s; s = s->next[0])
|
||||||
if (s->cache_dev == cache_stat->st_dev &&
|
if (s->cache_dev == cache_stat->st_dev &&
|
||||||
s->cache_ino == cache_stat->st_ino &&
|
s->cache_ino == cache_stat->st_ino &&
|
||||||
s->cache_mtime == cache_stat->st_mtime)
|
s->cache_mtime == cache_stat->st_mtime)
|
||||||
{
|
{
|
||||||
FcRefInc (&s->ref);
|
FcRefInc (&s->ref);
|
||||||
|
unlock_cache ();
|
||||||
return s->cache;
|
return s->cache;
|
||||||
}
|
}
|
||||||
|
unlock_cache ();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,14 +1007,17 @@ FcDirCacheWrite (FcCache *cache, FcConfig *config)
|
||||||
* new cache file is not read again. If it's large, we don't do that
|
* new cache file is not read again. If it's large, we don't do that
|
||||||
* such that we reload it, using mmap, which is shared across processes.
|
* such that we reload it, using mmap, which is shared across processes.
|
||||||
*/
|
*/
|
||||||
if (cache->size < FC_CACHE_MIN_MMAP &&
|
if (cache->size < FC_CACHE_MIN_MMAP && FcStat (cache_hashed, &cache_stat))
|
||||||
(skip = FcCacheFindByAddr (cache)) &&
|
{
|
||||||
FcStat (cache_hashed, &cache_stat))
|
lock_cache ();
|
||||||
|
if ((skip = FcCacheFindByAddrUnlocked (cache)))
|
||||||
{
|
{
|
||||||
skip->cache_dev = cache_stat.st_dev;
|
skip->cache_dev = cache_stat.st_dev;
|
||||||
skip->cache_ino = cache_stat.st_ino;
|
skip->cache_ino = cache_stat.st_ino;
|
||||||
skip->cache_mtime = cache_stat.st_mtime;
|
skip->cache_mtime = cache_stat.st_mtime;
|
||||||
}
|
}
|
||||||
|
unlock_cache ();
|
||||||
|
}
|
||||||
|
|
||||||
FcStrFree (cache_hashed);
|
FcStrFree (cache_hashed);
|
||||||
FcAtomicUnlock (atomic);
|
FcAtomicUnlock (atomic);
|
||||||
|
|
Loading…
Reference in New Issue