delay rather than stall ahead threads

avoid deadlocks by only slowing down threads which run ahead of the read
point
This commit is contained in:
John Cupitt 2012-09-05 14:56:13 +01:00
parent 0c87863222
commit 7a0441d455
2 changed files with 22 additions and 9 deletions

View File

@ -1,5 +1,6 @@
4/9/12 started 7.30.2
- sequential stops all threads on error
- sequential delays ahead threads rather than blocking them completely
6/8/12 started 7.30.1
- fixes to dzsave: shrink down to a 1x1 pixel tile, round image size up on

View File

@ -15,6 +15,7 @@
* - use linecache
* 4/9/12
* - stop all threads on error
* - don't stall forever, just delay ahead threads
*/
/*
@ -62,6 +63,10 @@
#include "conversion.h"
/* Stall threads that run ahead for this long, in seconds.
*/
#define STALL_TIME (0.1)
typedef struct _VipsSequential {
VipsConversion parent_instance;
@ -116,13 +121,12 @@ vips_sequential_generate( VipsRegion *or,
vips_diag( "VipsSequential",
"request for %d lines, starting at line %d",
r->height, r->top );
retry:
g_mutex_lock( sequential->lock );
VIPS_DEBUG_MSG( "thread %p has lock ...\n", g_thread_self() );
/* If we've seen an error, everything must stop or we'll deadlock.
/* If we've seen an error, everything must stop.
*/
if( sequential->error ) {
g_mutex_unlock( sequential->lock );
@ -131,19 +135,27 @@ retry:
if( r->top > sequential->y_pos &&
sequential->y_pos > 0 ) {
GTimeVal time;
/* We have started reading (y_pos > 0) and this request is for
* stuff beyond that, stall.
* stuff beyond that, stall for a short while to give other
* threads time to catch up.
*/
VIPS_DEBUG_MSG( "thread %p stalling ...\n", g_thread_self() );
g_cond_wait( sequential->ready, sequential->lock );
VIPS_DEBUG_MSG( "thread %p awake again, retrying ...\n",
VIPS_DEBUG_MSG( "thread %p stalling for up to %gs ...\n",
STALL_TIME, g_thread_self() );
g_get_current_time( &time );
g_time_val_add( &time, STALL_TIME * 1000000 );
g_cond_timed_wait( sequential->ready,
sequential->lock, &time );
VIPS_DEBUG_MSG( "thread %p awake again ...\n",
g_thread_self() );
g_mutex_unlock( sequential->lock );
goto retry;
}
/* This is a request for something some way down the image, and we've
* not read anything yet. Probably the operation is something like
* either not read anything yet or fallen through from the stall
* above.
*
* Probably the operation is something like
* extract_area and we should skip the initial part of the image. In
* fact we read to cache.
*/