[gegl] tile-handler-cache: avoid deadlock when dropping hot tile
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] tile-handler-cache: avoid deadlock when dropping hot tile
- Date: Mon, 17 Jul 2017 09:52:29 +0000 (UTC)
commit 8c60f31f18ec3e91f56b4ababefef75573118478
Author: Ell <ell_se yahoo com>
Date: Mon Jul 17 00:37:47 2017 -0400
tile-handler-cache: avoid deadlock when dropping hot tile
In gimp-tile-handler-cache.c, drop_hot_tile() might be called while
the current thread holds the global cache mutex, and subsequently
wait on the hot tile storage's mutex. If another thread already
holds the hot tile storage's mutex, and subsequently waits on the
global cache mutex, the program deadlocks.
Fix this by temporarily unlocking the global cache mutex while
dropping the hot tile, so that if the above happens, the other
thread can progress. This is ugly; ultimately, it would have
been nicer to order the global cache mutex lock and the hot tile
storage's mutex lock such that this couldn't happen, but we need
to lock the global cache mutex to reliably find the tile to drop
in the first place. We do make sure, however, that unlocking the
global cache mutex in the middle of any operation that may call
drop_hot_tile() is safe.
gegl/buffer/gegl-tile-handler-cache.c | 50 ++++++++++++++++++++++++++------
1 files changed, 40 insertions(+), 10 deletions(-)
---
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index e595bfc..b997bde 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -378,14 +378,32 @@ gegl_tile_handler_cache_has_tile (GeglTileHandlerCache *cache,
}
static void
-drop_hot_tile (GeglTile *tile)
+drop_hot_tile (GeglTile *tile,
+ gboolean mutex_locked)
{
GeglTileStorage *storage = tile->tile_storage;
if (storage)
{
if (gegl_config_threads()>1)
- g_rec_mutex_lock (&storage->mutex);
+ {
+ if (mutex_locked)
+ {
+ /* XXX: unlock the global cache mutex in order not to deadlock,
+ * in case the tile storage's mutex is held by another thread,
+ * that waits on the global cache mutex. this is really ugly,
+ * but we need to lock the global mutex before we can figure out
+ * the tile to drop, so ordering the locks correctly is tricky.
+ *
+ * note that we need to make sure that unlocking the global mutex
+ * here doesn't break our callers.
+ */
+ g_object_ref (storage);
+ g_mutex_unlock (&mutex);
+ }
+
+ g_rec_mutex_lock (&storage->mutex);
+ }
if (storage->hot_tile == tile)
{
@@ -394,7 +412,15 @@ drop_hot_tile (GeglTile *tile)
}
if (gegl_config_threads()>1)
- g_rec_mutex_unlock (&storage->mutex);
+ {
+ g_rec_mutex_unlock (&storage->mutex);
+
+ if (mutex_locked)
+ {
+ g_mutex_lock (&mutex);
+ g_object_unref (storage);
+ }
+ }
}
}
@@ -412,7 +438,7 @@ gegl_tile_handler_cache_trim (GeglTileHandlerCache *cache)
g_hash_table_remove (last_writable->handler->items, last_writable);
cache_total -= tile->size;
- drop_hot_tile (tile);
+ drop_hot_tile (tile, TRUE);
gegl_tile_unref (tile);
g_slice_free (CacheItem, last_writable);
return TRUE;
@@ -434,17 +460,21 @@ gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cache,
if (item)
{
cache_total -= item->tile->size;
- drop_hot_tile (item->tile);
- item->tile->tile_storage = NULL;
- gegl_tile_mark_as_stored (item->tile); /* to cheat it out of being stored */
- gegl_tile_unref (item->tile);
g_queue_unlink (cache_queue, &item->link);
g_hash_table_remove (cache->items, item);
+ g_mutex_unlock (&mutex);
+
+ drop_hot_tile (item->tile, FALSE);
+ item->tile->tile_storage = NULL;
+ gegl_tile_mark_as_stored (item->tile); /* to cheat it out of being stored */
+ gegl_tile_unref (item->tile);
+
g_slice_free (CacheItem, item);
}
- g_mutex_unlock (&mutex);
+ else
+ g_mutex_unlock (&mutex);
}
@@ -469,7 +499,7 @@ gegl_tile_handler_cache_void (GeglTileHandlerCache *cache,
if (item)
{
- drop_hot_tile (item->tile);
+ drop_hot_tile (item->tile, FALSE);
gegl_tile_void (item->tile);
gegl_tile_unref (item->tile);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]