summaryrefslogtreecommitdiff
path: root/src/fccache.c
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2018-05-23 15:08:12 +0200
committerAkira TAGOH <akira@tagoh.org>2018-05-25 14:42:05 +0900
commita63b9c622e240ec0d8f9d83d286db1b55849f374 (patch)
tree79c4e4d4b0288248c455431e38e3eb8b6960b480 /src/fccache.c
parent94080c3d48686117b83acddf516258647b571f03 (diff)
Add FcCacheAllocate() helper
This lets you allocate a chunk of memory that will be freed when the cache is freed. https://bugs.freedesktop.org/show_bug.cgi?id=106618
Diffstat (limited to 'src/fccache.c')
-rw-r--r--src/fccache.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/fccache.c b/src/fccache.c
index 27b1282..041c77b 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -443,6 +443,7 @@ struct _FcCacheSkip {
FcCache *cache;
FcRef ref;
intptr_t size;
+ void *allocated;
dev_t cache_dev;
ino_t cache_ino;
time_t cache_mtime;
@@ -568,6 +569,7 @@ FcCacheInsert (FcCache *cache, struct stat *cache_stat)
s->cache = cache;
s->size = cache->size;
+ s->allocated = NULL;
FcRefInit (&s->ref, 1);
if (cache_stat)
{
@@ -642,6 +644,7 @@ FcCacheRemoveUnlocked (FcCache *cache)
FcCacheSkip **update[FC_CACHE_MAX_LEVEL];
FcCacheSkip *s, **next;
int i;
+ void *allocated;
/*
* Find links along each chain
@@ -659,6 +662,15 @@ FcCacheRemoveUnlocked (FcCache *cache)
*update[i] = s->next[i];
while (fcCacheMaxLevel > 0 && fcCacheChains[fcCacheMaxLevel - 1] == NULL)
fcCacheMaxLevel--;
+
+ allocated = s->allocated;
+ while (allocated)
+ {
+ /* First element in allocated chunk is the free list */
+ next = *(void **)allocated;
+ free (allocated);
+ allocated = next;
+ }
free (s);
}
@@ -728,6 +740,30 @@ FcCacheObjectDereference (void *object)
unlock_cache ();
}
+void *
+FcCacheAllocate (FcCache *cache, size_t len)
+{
+ FcCacheSkip *skip;
+ void *allocated = NULL;
+
+ lock_cache ();
+ skip = FcCacheFindByAddrUnlocked (cache);
+ if (skip)
+ {
+ void *chunk = malloc (sizeof (void *) + len);
+ if (chunk)
+ {
+ /* First element in allocated chunk is the free list */
+ *(void **)chunk = skip->allocated;
+ skip->allocated = chunk;
+ /* Return the rest */
+ allocated = ((FcChar8 *)chunk) + sizeof (void *);
+ }
+ }
+ unlock_cache ();
+ return allocated;
+}
+
void
FcCacheFini (void)
{