> > * app/base/pixel-processor.c: fixed potential race condition on >

2005-02-24  Jay Cox  <jaycox@gimp.org>
>
>       * app/base/pixel-processor.c: fixed potential race condition on
>       processor->threads.  Changed mutex to a GMutex from a GStaticMutex
>       because it needs to me initialized anyway.  Placed g_cond_wait
>       calls inside while loops to handle g_cond_wait returning prematurely.
This commit is contained in:
Jay Cox 2005-02-24 22:58:02 +00:00 committed by jaycox
parent 33b974b4e6
commit 3f532376e8
2 changed files with 44 additions and 32 deletions

View File

@ -1,3 +1,10 @@
2005-02-24 Jay Cox <jaycox@gimp.org>
* app/base/pixel-processor.c: fixed potential race condition on
processor->threads. Changed mutex to a GMutex from a GStaticMutex
because it needs to be initialized anyway. Placed g_cond_wait
calls inside while loops to handle g_cond_wait returning prematurely.
2005-02-24 Manish Singh <yosh@gimp.org> 2005-02-24 Manish Singh <yosh@gimp.org>
* plug-ins/uri/uri-backend-wget.c: Handle large file sizes, and * plug-ins/uri/uri-backend-wget.c: Handle large file sizes, and

View File

@ -38,7 +38,6 @@
#define TILES_PER_THREAD 8 #define TILES_PER_THREAD 8
#define PROGRESS_TIMEOUT 64 #define PROGRESS_TIMEOUT 64
static GThreadPool *pool = NULL; static GThreadPool *pool = NULL;
static GMutex *pool_mutex = NULL; static GMutex *pool_mutex = NULL;
static GCond *pool_cond = NULL; static GCond *pool_cond = NULL;
@ -68,8 +67,9 @@ struct _PixelProcessor
gpointer data; gpointer data;
#ifdef ENABLE_MP #ifdef ENABLE_MP
GStaticMutex mutex; GMutex *mutex;
gint threads; gint threads;
gboolean first;
#endif #endif
PixelRegionIterator *PRI; PixelRegionIterator *PRI;
@ -87,21 +87,15 @@ do_parallel_regions (PixelProcessor *processor)
PixelRegion tr[4]; PixelRegion tr[4];
gint i; gint i;
g_static_mutex_lock (&processor->mutex); g_mutex_lock (processor->mutex);
/* the first thread getting here must not call pixel_regions_process() */ /* the first thread getting here must not call pixel_regions_process() */
if (processor->threads && processor->PRI) if (!processor->first && processor->PRI)
processor->PRI = pixel_regions_process (processor->PRI); processor->PRI = pixel_regions_process (processor->PRI);
else
processor->first = FALSE;
if (processor->PRI == NULL) while (processor->PRI)
{
g_static_mutex_unlock (&processor->mutex);
return;
}
processor->threads++;
do
{ {
guint pixels = (processor->PRI->portion_width * guint pixels = (processor->PRI->portion_width *
processor->PRI->portion_height); processor->PRI->portion_height);
@ -114,7 +108,7 @@ do_parallel_regions (PixelProcessor *processor)
tile_lock (tr[i].curtile); tile_lock (tr[i].curtile);
} }
g_static_mutex_unlock (&processor->mutex); g_mutex_unlock (processor->mutex);
switch(processor->num_regions) switch(processor->num_regions)
{ {
@ -150,7 +144,7 @@ do_parallel_regions (PixelProcessor *processor)
break; break;
} }
g_static_mutex_lock (&processor->mutex); g_mutex_lock (processor->mutex);
for (i = 0; i < processor->num_regions; i++) for (i = 0; i < processor->num_regions; i++)
if (processor->regions[i]) if (processor->regions[i])
@ -160,24 +154,25 @@ do_parallel_regions (PixelProcessor *processor)
} }
processor->progress += pixels; processor->progress += pixels;
if (processor->PRI)
processor->PRI = pixel_regions_process (processor->PRI);
} }
while (processor->PRI &&
(processor->PRI = pixel_regions_process (processor->PRI)));
g_mutex_lock (pool_mutex);
processor->threads--; processor->threads--;
if (processor->threads == 0) if (processor->threads == 0)
{ {
g_static_mutex_unlock (&processor->mutex);
g_mutex_lock (pool_mutex);
g_cond_signal (pool_cond);
g_mutex_unlock (pool_mutex); g_mutex_unlock (pool_mutex);
g_mutex_unlock (processor->mutex);
g_cond_signal (pool_cond);
} }
else else
{ {
g_static_mutex_unlock (&processor->mutex); g_mutex_unlock (pool_mutex);
g_mutex_unlock (processor->mutex);
} }
} }
#endif #endif
@ -283,6 +278,10 @@ pixel_regions_do_parallel (PixelProcessor *processor,
g_mutex_lock (pool_mutex); g_mutex_lock (pool_mutex);
processor->first = TRUE;
processor->threads = tasks;
processor->mutex = g_mutex_new();
while (tasks--) while (tasks--)
{ {
g_thread_pool_push (pool, processor, &error); g_thread_pool_push (pool, processor, &error);
@ -291,38 +290,44 @@ pixel_regions_do_parallel (PixelProcessor *processor,
{ {
g_warning ("thread creation failed: %s", error->message); g_warning ("thread creation failed: %s", error->message);
g_clear_error (&error); g_clear_error (&error);
processor->threads--;
} }
} }
if (progress_func) if (progress_func)
{ {
GTimeVal timeout;
g_get_current_time (&timeout); while (processor->threads != 0)
g_time_val_add (&timeout, PROGRESS_TIMEOUT * 1024);
while (! g_cond_timed_wait (pool_cond, pool_mutex, &timeout))
{ {
gulong progress; gulong progress;
GTimeVal timeout;
g_static_mutex_lock (&processor->mutex); g_get_current_time (&timeout);
g_time_val_add (&timeout, PROGRESS_TIMEOUT * 1024);
g_cond_timed_wait (pool_cond, pool_mutex, &timeout);
g_mutex_lock (processor->mutex);
progress = processor->progress; progress = processor->progress;
g_static_mutex_unlock (&processor->mutex); g_mutex_unlock (processor->mutex);
progress_func (progress_data, progress_func (progress_data,
(gdouble) progress / (gdouble) pixels); (gdouble) progress / (gdouble) pixels);
g_get_current_time (&timeout);
g_time_val_add (&timeout, PROGRESS_TIMEOUT * 1024);
} }
} }
else else
{ {
g_cond_wait (pool_cond, pool_mutex); while (processor->threads != 0)
{
g_cond_wait (pool_cond, pool_mutex);
}
} }
g_mutex_unlock (pool_mutex); g_mutex_unlock (pool_mutex);
g_mutex_free (processor->mutex);
} }
else else
#endif #endif