[gegl/gsoc2011-opencl: 9/12] Locking for Tiles
- From: Victor Matheus de Araujo Oliveira <vmaolive src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/gsoc2011-opencl: 9/12] Locking for Tiles
- Date: Mon, 1 Aug 2011 13:27:47 +0000 (UTC)
commit 8da07a9ca34fa5cbf6e82af47eec4c2b271baf08
Author: Victor Oliveira <victormatheus gmail com>
Date: Thu Jun 9 18:42:06 2011 -0300
Locking for Tiles
I'm basing this code on the gsoc2009 branch.
The changes create 4 locks in GeglTile, read and write for cpu and opencl, instead of
the old general one.
this is necessary because we can't guarantee anymore reading is in sync, because
we can change data in the gpu without updating the correspondent data in cpu (and vice-versa).
gegl/buffer/gegl-buffer-access.c | 4 +-
gegl/buffer/gegl-buffer-backend.h | 2 +
gegl/buffer/gegl-buffer-iterator.c | 2 +-
gegl/buffer/gegl-buffer-linear.c | 2 +-
gegl/buffer/gegl-buffer-load.c | 2 +-
gegl/buffer/gegl-buffer-private.h | 30 ++++++++-
gegl/buffer/gegl-buffer.c | 2 +-
gegl/buffer/gegl-tile-handler-zoom.c | 2 +-
gegl/buffer/gegl-tile.c | 131 +++++++++++++++++++++++++--------
gegl/buffer/gegl-tile.h | 3 +-
10 files changed, 139 insertions(+), 41 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index fa37f37..5297b95 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -187,7 +187,7 @@ gegl_buffer_set_pixel (GeglBuffer *buffer,
gint offsety = gegl_tile_offset (tiledy, tile_height);
guchar *tp;
- gegl_tile_lock (tile);
+ gegl_tile_lock (tile, GEGL_TILE_LOCK_WRITE);
tp = gegl_tile_get_data (tile) +
(offsety * tile_width + offsetx) * px_size;
@@ -470,7 +470,7 @@ gegl_buffer_iterate (GeglBuffer *buffer,
}
if (write)
- gegl_tile_lock (tile);
+ gegl_tile_lock (tile, GEGL_TILE_LOCK_WRITE);
tile_base = gegl_tile_get_data (tile);
tp = ((guchar *) tile_base) + (offsety * tile_width + offsetx) * px_size;
diff --git a/gegl/buffer/gegl-buffer-backend.h b/gegl/buffer/gegl-buffer-backend.h
index 40342ac..7edca0c 100644
--- a/gegl/buffer/gegl-buffer-backend.h
+++ b/gegl/buffer/gegl-buffer-backend.h
@@ -29,6 +29,8 @@ typedef struct _GeglTileBackendPrivate GeglTileBackendPrivate;
typedef struct _GeglTile GeglTile;
+typedef enum _GeglTileLockMode GeglTileLockMode;
+
#include "gegl-types.h"
#include "gegl-tile-backend.h"
#include "gegl-tile-source.h"
diff --git a/gegl/buffer/gegl-buffer-iterator.c b/gegl/buffer/gegl-buffer-iterator.c
index e0f8681..70d1760 100644
--- a/gegl/buffer/gegl-buffer-iterator.c
+++ b/gegl/buffer/gegl-buffer-iterator.c
@@ -186,7 +186,7 @@ gulp:
0);
if (i->write && tile_width==i->subrect.width)
{
- gegl_tile_lock (i->tile);
+ gegl_tile_lock (i->tile, GEGL_TILE_LOCK_WRITE);
}
i->data = gegl_tile_get_data (i->tile);
diff --git a/gegl/buffer/gegl-buffer-linear.c b/gegl/buffer/gegl-buffer-linear.c
index 739fc16..478a6f2 100644
--- a/gegl/buffer/gegl-buffer-linear.c
+++ b/gegl/buffer/gegl-buffer-linear.c
@@ -148,7 +148,7 @@ gegl_buffer_linear_open (GeglBuffer *buffer,
tile = gegl_tile_source_get_tile ((GeglTileSource*) (buffer),
0,0,0);
g_assert (tile);
- gegl_tile_lock (tile);
+ gegl_tile_lock (tile, GEGL_TILE_LOCK_WRITE);
g_object_set_data (G_OBJECT (buffer), "linear-tile", tile);
diff --git a/gegl/buffer/gegl-buffer-load.c b/gegl/buffer/gegl-buffer-load.c
index 8a7300b..b6f5ae2 100644
--- a/gegl/buffer/gegl-buffer-load.c
+++ b/gegl/buffer/gegl-buffer-load.c
@@ -320,7 +320,7 @@ gegl_buffer_load (const gchar *path)
g_assert (tile);
- gegl_tile_lock (tile);
+ gegl_tile_lock (tile, GEGL_TILE_LOCK_WRITE);
data = gegl_tile_get_data (tile);
g_assert (data);
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index d065ba8..62342f1 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -134,6 +134,25 @@ void gegl_buffer_sampler (GeglBuffer *buffer,
+enum _GeglTileLockMode
+{
+ GEGL_TILE_LOCK_NONE = 0,
+ GEGL_TILE_LOCK_READ = (1 << 0),
+ GEGL_TILE_LOCK_WRITE = (1 << 1),
+ GEGL_TILE_LOCK_CL_READ = (1 << 2),
+ GEGL_TILE_LOCK_CL_WRITE = (1 << 3),
+ GEGL_TILE_LOCK_READWRITE = GEGL_TILE_LOCK_READ
+ | GEGL_TILE_LOCK_WRITE,
+ GEGL_TILE_LOCK_CL_READWRITE = GEGL_TILE_LOCK_CL_READ
+ | GEGL_TILE_LOCK_CL_WRITE,
+ GEGL_TILE_LOCK_ALL_READ = GEGL_TILE_LOCK_READ
+ | GEGL_TILE_LOCK_CL_READ,
+ GEGL_TILE_LOCK_ALL_WRITE = GEGL_TILE_LOCK_WRITE
+ | GEGL_TILE_LOCK_CL_WRITE,
+ GEGL_TILE_LOCK_ALL = GEGL_TILE_LOCK_READWRITE
+ | GEGL_TILE_LOCK_CL_READWRITE,
+};
+
/* the instance size of a GeglTile is a bit large, and should if possible be
* trimmed down
*/
@@ -160,9 +179,17 @@ struct _GeglTile
guint stored_rev; /* what revision was we when we from tile_storage?
(currently set to 1 when loaded from disk */
- gchar lock; /* number of times the tile is write locked
+ guint read_locks; /* number of times the tile is read locked
+ * if lock/unlock are correctly done, it should
+ be 0/1, but there is no problem with shared reads
+ */
+
+ gchar write_locks; /* number of times the tile is write locked
* should in theory just have the values 0/1
*/
+
+ GeglTileLockMode lock_mode;
+
GMutex *mutex;
/* the shared list is a doubly linked circular list */
@@ -178,6 +205,7 @@ struct _GeglTile
#ifndef __GEGL_TILE_C
#define gegl_tile_get_data(tile) ((guchar*)((tile)->data))
+#define gegl_tile_get_cl_data(tile) ((tile)->cl_data))
#endif // __GEGL_TILE_C
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index 08056bb..cd1b411 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -736,7 +736,7 @@ gegl_buffer_get_tile (GeglTileSource *source,
{
if (!tile->tile_storage)
{
- gegl_tile_lock (tile);
+ gegl_tile_lock (tile, GEGL_TILE_LOCK_WRITE);
tile->tile_storage = buffer->tile_storage;
gegl_tile_unlock (tile);
}
diff --git a/gegl/buffer/gegl-tile-handler-zoom.c b/gegl/buffer/gegl-tile-handler-zoom.c
index c94cb73..60b034c 100644
--- a/gegl/buffer/gegl-tile-handler-zoom.c
+++ b/gegl/buffer/gegl-tile-handler-zoom.c
@@ -267,7 +267,7 @@ get_tile (GeglTileSource *gegl_tile_source,
if (zoom->cache)
gegl_tile_handler_cache_insert (zoom->cache, tile, x, y, z);
}
- gegl_tile_lock (tile);
+ gegl_tile_lock (tile, GEGL_TILE_LOCK_WRITE);
for (i = 0; i < 2; i++)
for (j = 0; j < 2; j++)
diff --git a/gegl/buffer/gegl-tile.c b/gegl/buffer/gegl-tile.c
index c59b184..521867a 100644
--- a/gegl/buffer/gegl-tile.c
+++ b/gegl/buffer/gegl-tile.c
@@ -103,7 +103,9 @@ gegl_tile_new_bare (void)
tile->stored_rev = 1;
tile->rev = 1;
tile->cl_rev = 0;
- tile->lock = 0;
+ tile->read_locks = 0;
+ tile->write_locks = 0;
+ tile->lock_mode = GEGL_TILE_LOCK_NONE;
tile->data = NULL;
tile->cl_data = NULL;
@@ -201,37 +203,78 @@ static gint total_unlocks = 0;
void gegl_bt (void);
void
-gegl_tile_lock (GeglTile *tile)
+gegl_tile_lock (GeglTile *tile,
+ GeglTileLockMode lock_mode)
{
- g_mutex_lock (tile->mutex);
+ //g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "tile locking: %p %d %d %d", tile, lock_mode, tile->read_locks, tile->write_locks);
+ if (lock_mode != GEGL_TILE_LOCK_NONE)
+ g_mutex_lock (tile->mutex);
+ else
+ g_warning ("%s called with lock_mode GEGL_TILE_LOCK_NONE", G_STRFUNC);
- if (tile->lock != 0)
+ if (!tile->cl_data)
{
- g_warning ("strange tile lock count: %i", tile->lock);
- gegl_bt ();
+ lock_mode &= ~GEGL_TILE_LOCK_CL_READWRITE;
+ //g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "change lock to: %d", lock_mode);
}
+
+ if (tile->write_locks != 0)
+ {
+ if (lock_mode & GEGL_TILE_LOCK_ALL_WRITE)
+ {
+ g_warning ("strange tile lock count: %i", tile->write_locks);
+ gegl_bt ();
+ }
+ if (lock_mode & GEGL_TILE_LOCK_ALL_READ)
+ {
+ g_warning ("shouldn't lock for reading while write-lock (%i) is active",
+ tile->write_locks);
+ gegl_bt ();
+ }
+ }
+
+ if (tile->read_locks > 0)
+ {
+ if (lock_mode & GEGL_TILE_LOCK_ALL_READ)
+ {
+ g_warning ("strange tile lock count: %i", tile->read_locks);
+ gegl_bt ();
+ }
+ if (lock_mode & GEGL_TILE_LOCK_ALL_WRITE)
+ {
+ g_warning ("shouldn't lock for writing while read-lock (%i) is active",
+ tile->read_locks);
+ gegl_bt ();
+ }
+ }
+
+
#if 0
total_locks++;
#endif
- tile->lock++;
+ if (lock_mode & GEGL_TILE_LOCK_ALL_READ)
+ tile->read_locks++;
+
+ if (lock_mode & GEGL_TILE_LOCK_ALL_WRITE)
+ tile->write_locks++;
+
/*fprintf (stderr, "global tile locking: %i %i\n", locks, unlocks);*/
gegl_tile_unclone (tile);
- if (gegl_cl_is_accelerated ())
+ if (lock_mode & GEGL_TILE_LOCK_CL_READ && tile->rev > tile->cl_rev)
{
- if (tile->rev > tile->cl_rev)
- {
- gegl_cl_texture_set (tile->cl_data, tile->data);
- tile->cl_rev = tile->rev;
- }
- else if (tile->cl_rev > tile->rev)
- {
- gegl_cl_texture_get (tile->cl_data, tile->data);
- tile->rev = tile->cl_rev;
- }
+ gegl_cl_texture_set (tile->cl_data, tile->data);
+ tile->cl_rev = tile->rev;
+ }
+ else if (lock_mode & GEGL_TILE_LOCK_READ && tile->cl_rev > tile->rev)
+ {
+ gegl_cl_texture_get (tile->cl_data, tile->data);
+ tile->rev = tile->cl_rev;
}
+
+ tile->lock_mode = lock_mode;
}
static void
@@ -264,30 +307,54 @@ gegl_tile_void_pyramid (GeglTile *tile)
void
gegl_tile_unlock (GeglTile *tile)
{
+ //g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "tile UNlocking: %p %d %d %d", tile, tile->lock_mode, tile->read_locks, tile->write_locks);
#if 0
total_unlocks++;
#endif
- if (tile->lock == 0)
+ if (tile->lock_mode & GEGL_TILE_LOCK_ALL_WRITE)
{
- g_warning ("unlocked a tile with lock count == 0");
- }
- tile->lock--;
+ if (tile->write_locks == 0)
+ {
+ g_warning ("unlocked a tile with write-lock count == 0");
+ gegl_bt ();
+ }
+ tile->write_locks--;
- if (tile->lock == 0 &&
- tile->z == 0)
- {
- gegl_tile_void_pyramid (tile);
+ if (tile->write_locks == 0
+ && tile->z == 0)
+ {
+ gegl_tile_void_pyramid (tile);
+ }
+
+ if (tile->write_locks==0)
+ {
+ if (tile->lock_mode & GEGL_TILE_LOCK_CL_WRITE)
+ {
+ tile->cl_rev = MAX(tile->rev, tile->cl_rev)+1; //cl is updated
+ if (tile->lock_mode & GEGL_TILE_LOCK_WRITE)
+ tile->rev = tile->cl_rev; //cl and cpu are in sync
+ }
+ else
+ tile->rev++;
+ }
}
- if (tile->lock==0)
+ if (tile->lock_mode & GEGL_TILE_LOCK_ALL_READ)
{
- if (gegl_cl_is_accelerated ())
- tile->rev = tile->cl_rev = MAX(tile->rev, tile->cl_rev)+1;
- else
- tile->rev++;
+ if (tile->read_locks == 0)
+ {
+ g_warning ("unlocked a tile with read-lock count == 0");
+ gegl_bt ();
+ }
+ tile->read_locks--;
}
- g_mutex_unlock (tile->mutex);
+ if (tile->lock_mode != GEGL_TILE_LOCK_NONE)
+ g_mutex_unlock (tile->mutex);
+ else
+ g_warning ("%s called with lock_mode GEGL_TILE_LOCK_NONE", G_STRFUNC);
+
+ tile->lock_mode = GEGL_TILE_LOCK_NONE;
}
diff --git a/gegl/buffer/gegl-tile.h b/gegl/buffer/gegl-tile.h
index fbc52a9..62ce611 100644
--- a/gegl/buffer/gegl-tile.h
+++ b/gegl/buffer/gegl-tile.h
@@ -30,7 +30,8 @@ void gegl_tile_unref (GeglTile *tile);
/* lock a tile for writing, this would allow writing to buffers
* later gotten with get_data()
*/
-void gegl_tile_lock (GeglTile *tile);
+void gegl_tile_lock (GeglTile *tile,
+ GeglTileLockMode lock_mode);
/* unlock the tile notifying the tile that we're done manipulating
* the data.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]