diff options
author | Pauli Nieminen <[email protected]> | 2009-07-30 20:17:29 +0300 |
---|---|---|
committer | Alex Deucher <[email protected]> | 2009-08-12 14:14:29 -0400 |
commit | 29173d3d5cf02d58e720b5c7fe48a0630c7d5d5f (patch) | |
tree | afaf64a351d5f451de6e9cd12191c25079888f38 /src/mesa/drivers/dri/radeon/radeon_lock.c | |
parent | 5eeb44f3983dfda2f2707783be12806da795cbcd (diff) |
radeon: Add protection against recursive DRM locking.
Reference counting protects DRM lock call from recursive locking that would
cause hang. Code also adds optional debugging output for recursive call that
is compiled only if NDEBUG is not defined.
This code is not 100% thread safe because mesa doesn't include increment and
test atomic operation. There is built-in gcc functions but they are only
available from gcc 4.2.
Diffstat (limited to 'src/mesa/drivers/dri/radeon/radeon_lock.c')
-rw-r--r-- | src/mesa/drivers/dri/radeon/radeon_lock.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c index 2f0ed1cfced..6294b7e42be 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.c +++ b/src/mesa/drivers/dri/radeon/radeon_lock.c @@ -86,8 +86,34 @@ void radeonGetLock(radeonContextPtr rmesa, GLuint flags) rmesa->vtbl.get_lock(rmesa); } - -void radeon_lock_hardware(radeonContextPtr radeon) +#ifndef NDEBUG +struct lock_debug { + const char* function; + const char* file; + int line; +}; + +static struct lock_debug ldebug = {0}; +#endif + +#if 0 +/** TODO: use atomic operations for reference counting **/ +/** gcc 4.2 has builtin functios for this **/ +#define ATOMIC_INC_AND_FETCH(atomic) __sync_add_and_fetch(&atomic, 1) +#define ATOMIC_DEC_AND_FETCH(atomic) __sync_sub_and_fetch(&atomic, 1) +#else +#define ATOMIC_INC_AND_FETCH(atomic) (++atomic) +#define ATOMIC_DEC_AND_FETCH(atomic) (--atomic) +#endif + + +void radeon_lock_hardware(radeonContextPtr radeon +#ifndef NDEBUG + ,const char* function + ,const char* file + ,const int line +#endif + ) { char ret = 0; struct radeon_framebuffer *rfb = NULL; @@ -102,16 +128,39 @@ void radeon_lock_hardware(radeonContextPtr radeon) } if (!radeon->radeonScreen->driScreen->dri2.enabled) { + if (ATOMIC_INC_AND_FETCH(radeon->dri.hwLockCount) > 1) + { +#ifndef NDEBUG + if ( RADEON_DEBUG & DEBUG_SANITY ) + fprintf(stderr, "*** %d times of recursive call to %s ***\n" + "Original call was from %s (file: %s line: %d)\n" + "Now call is coming from %s (file: %s line: %d)\n" + , radeon->dri.hwLockCount, __FUNCTION__ + , ldebug.function, ldebug.file, ldebug.line + , function, file, line + ); +#endif + return; + } DRM_CAS(radeon->dri.hwLock, radeon->dri.hwContext, (DRM_LOCK_HELD | radeon->dri.hwContext), ret ); if (ret) radeonGetLock(radeon, 0); +#ifndef NDEBUG + ldebug.function = function; + ldebug.file = file; + ldebug.line = line; +#endif } } void radeon_unlock_hardware(radeonContextPtr radeon) { if (!radeon->radeonScreen->driScreen->dri2.enabled) { + if (ATOMIC_DEC_AND_FETCH(radeon->dri.hwLockCount) > 0) + { + return; + } DRM_UNLOCK( radeon->dri.fd, radeon->dri.hwLock, radeon->dri.hwContext ); |