[Spice-devel] [PATCH 15/17] Protect image cache from concurrent access
alexl at redhat.com
alexl at redhat.com
Tue Sep 14 12:09:05 PDT 2010
From: Alexander Larsson <alexl at redhat.com>
---
display/qxldd.h | 1 +
display/res.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----------
2 files changed, 45 insertions(+), 10 deletions(-)
diff --git a/display/qxldd.h b/display/qxldd.h
index fb39b46..be9da7b 100644
--- a/display/qxldd.h
+++ b/display/qxldd.h
@@ -183,6 +183,7 @@ typedef struct DevRes {
HSEMAPHORE cmd_sem;
HSEMAPHORE cursor_sem; /* Protects cursor_ring */
HSEMAPHORE surface_sem; /* Protects surfaces allocation */
+ HSEMAPHORE image_cache_sem; /* Protects image cache */
CacheImage cache_image_pool[IMAGE_POOL_SIZE];
Ring cache_image_lru;
diff --git a/display/res.c b/display/res.c
index 1785f02..901d63f 100644
--- a/display/res.c
+++ b/display/res.c
@@ -403,6 +403,10 @@ void CleanGlobalRes()
EngDeleteSemaphore(res->surface_sem);
res->surface_sem = NULL;
}
+ if (res->image_cache_sem) {
+ EngDeleteSemaphore(res->image_cache_sem);
+ res->image_cache_sem = NULL;
+ }
EngFreeMem(res);
}
}
@@ -468,6 +472,10 @@ static void InitRes(PDev *pdev)
if (!pdev->Res->print_sem) {
PANIC(pdev, "Res print sem creation failed\n");
}
+ pdev->Res->image_cache_sem = EngCreateSemaphore();
+ if (!pdev->Res->image_cache_sem) {
+ PANIC(pdev, "Res cache sem creation failed\n");
+ }
InitMspace(pdev->Res, MSPACE_TYPE_DEVRAM, pdev->io_pages_virt, pdev->num_io_pages * PAGE_SIZE);
InitMspace(pdev->Res, MSPACE_TYPE_VRAM, pdev->fb, pdev->fb_size);
@@ -1300,29 +1308,35 @@ typedef struct InternalImage {
static void ImageKeyPut(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 key)
{
- ImageKey *image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
+ ImageKey *image_key;
if (!unique) {
return;
}
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
+ image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
image_key->hsurf = hsurf;
image_key->unique = unique;
image_key->key = key;
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
}
static BOOL ImageKeyGet(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 *key)
{
ImageKey *image_key;
+ BOOL res = FALSE;
if (!unique) {
return FALSE;
}
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
image_key = &pdev->Res->image_key_lookup[IMAGE_KEY_HASH_VAL(hsurf)];
if (image_key->hsurf == hsurf && image_key->unique == unique) {
*key = image_key->key;
- return TRUE;
+ res = TRUE;
}
- return FALSE;
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
+ return res;
}
#define IMAGE_HASH_VAL(hsurf) (HSURF_HASH_VAL(hsurf) & IMAGE_HASH_MASK)
@@ -1330,26 +1344,35 @@ static BOOL ImageKeyGet(PDev *pdev, HSURF hsurf, UINT64 unique, UINT32 *key)
static CacheImage *ImageCacheGetByKey(PDev *pdev, UINT32 key, BOOL check_rest,
UINT8 format, UINT32 width, UINT32 height)
{
- CacheImage *cache_image = pdev->Res->image_cache[IMAGE_HASH_VAL(key)];
+ CacheImage *cache_image;
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
+ cache_image = pdev->Res->image_cache[IMAGE_HASH_VAL(key)];
while (cache_image) {
if (cache_image->key == key && (!check_rest || (cache_image->format == format &&
cache_image->width == width && cache_image->height == height))) {
- return cache_image;
+ break;
}
cache_image = cache_image->next;
}
- return NULL;
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
+ return cache_image;
}
+/* Called with image_cache_sem held */
static void ImageCacheAdd(PDev *pdev, CacheImage *cache_image)
{
- int key = IMAGE_HASH_VAL(cache_image->key);
+ int key;
+
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
+ key = IMAGE_HASH_VAL(cache_image->key);
cache_image->next = pdev->Res->image_cache[key];
cache_image->hits = 1;
pdev->Res->image_cache[key] = cache_image;
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
}
+/* Called with image_cache_sem held */
static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
{
CacheImage **cache_img;
@@ -1361,12 +1384,13 @@ static void ImageCacheRemove(PDev *pdev, CacheImage *cache_image)
while (*cache_img) {
if ((*cache_img)->key == cache_image->key) {
*cache_img = cache_image->next;
- return;
+ break;
}
cache_img = &(*cache_img)->next;
}
}
+/* Called with image_cache_sem held */
static CacheImage *AllocCacheImage(PDev* pdev)
{
RingItem *item;
@@ -1535,8 +1559,10 @@ static void FreeQuicImage(PDev *pdev, Resource *res) // todo: defer
internal = (InternalImage *)res->res;
if (internal->cache) {
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
RingAdd(pdev, &pdev->Res->cache_image_lru, &internal->cache->lru_link);
internal->cache->image = NULL;
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
}
chunk_phys = ((QXLDataChunk *)internal->image.quic.data)->next_chunk;
@@ -1698,8 +1724,10 @@ static void FreeBitmapImage(PDev *pdev, Resource *res) // todo: defer
internal = (InternalImage *)res->res;
if (internal->cache) {
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
RingAdd(pdev, &pdev->Res->cache_image_lru, &internal->cache->lru_link);
internal->cache->image = NULL;
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
}
if (internal->image.bitmap.palette) {
@@ -2016,7 +2044,9 @@ static CacheImage *GetCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
}
if (CacheSizeTest(pdev, surf)) {
- CacheImage *cache_image = AllocCacheImage(pdev);
+ CacheImage *cache_image;
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
+ cache_image = AllocCacheImage(pdev);
ImageCacheRemove(pdev, cache_image);
cache_image->key = key;
cache_image->image = NULL;
@@ -2025,6 +2055,7 @@ static CacheImage *GetCacheImage(PDev *pdev, SURFOBJ *surf, XLATEOBJ *color_tran
cache_image->height = surf->sizlBitmap.cy;
ImageCacheAdd(pdev, cache_image);
RingAdd(pdev, &pdev->Res->cache_image_lru, &cache_image->lru_link);
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
DEBUG_PRINT((pdev, 11, "%s: ImageCacheAdd %u\n", __FUNCTION__, key));
}
return NULL;
@@ -2314,7 +2345,9 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
return TRUE;
}
} else if (CacheSizeTest(pdev, surf)) {
- CacheImage *cache_image = AllocCacheImage(pdev);
+ CacheImage *cache_image;
+ EngAcquireSemaphore(pdev->Res->image_cache_sem);
+ cache_image = AllocCacheImage(pdev);
ImageCacheRemove(pdev, cache_image);
cache_image->key = key;
cache_image->image = NULL;
@@ -2323,6 +2356,7 @@ BOOL QXLGetAlphaBitmap(PDev *pdev, QXLDrawable *drawable, QXLPHYSICAL *image_phy
cache_image->height = surf->sizlBitmap.cy;
ImageCacheAdd(pdev, cache_image);
RingAdd(pdev, &pdev->Res->cache_image_lru, &cache_image->lru_link);
+ EngReleaseSemaphore(pdev->Res->image_cache_sem);
DEBUG_PRINT((pdev, 11, "%s: ImageCacheAdd %u\n", __FUNCTION__, key));
}
--
1.7.2.2
More information about the Spice-devel
mailing list