kernel: Rewrite KDEBUG_RW_LOCK_DEBUG.
Previously this just turned the rw_lock into the equivalent of a recursive_lock, which meant that reader vs. writer assertions were of no use. Now, we have a per-thread static array which stores the held read locks, allowing ASSERT_READ_LOCKED_RW_LOCK to work properly, and allowing multiple readers to be active at a time. This probably should still remain disabled even on nightly builds, but at least it's much more useful as a debugging tool than it was beforehand. Change-Id: I386b2bc2ada8df42f4ab11a05563ef22af58e77f
This commit is contained in:
@@ -72,23 +72,27 @@ typedef struct rw_lock {
|
||||
#if KDEBUG
|
||||
# define KDEBUG_RW_LOCK_DEBUG 0
|
||||
// Define to 1 if you want to use ASSERT_READ_LOCKED_RW_LOCK().
|
||||
// The rw_lock will just behave like a recursive locker then.
|
||||
# define ASSERT_LOCKED_RECURSIVE(r) \
|
||||
{ ASSERT(find_thread(NULL) == (r)->lock.holder); }
|
||||
# define ASSERT_LOCKED_MUTEX(m) { ASSERT(find_thread(NULL) == (m)->holder); }
|
||||
# define ASSERT_WRITE_LOCKED_RW_LOCK(l) \
|
||||
{ ASSERT(find_thread(NULL) == (l)->holder); }
|
||||
# if KDEBUG_RW_LOCK_DEBUG
|
||||
extern bool _rw_lock_is_read_locked(rw_lock* lock);
|
||||
# define ASSERT_READ_LOCKED_RW_LOCK(l) \
|
||||
{ ASSERT(find_thread(NULL) == (l)->holder); }
|
||||
{ ASSERT_PRINT(_rw_lock_is_read_locked(l), "rwlock %p", l); }
|
||||
# define ASSERT_UNLOCKED_RW_LOCK(l) \
|
||||
{ ASSERT_PRINT(!_rw_lock_is_read_locked(l), "rwlock %p", l); }
|
||||
# else
|
||||
# define ASSERT_READ_LOCKED_RW_LOCK(l) do {} while (false)
|
||||
# define ASSERT_UNLOCKED_RW_LOCK(l) do {} while (false)
|
||||
# endif
|
||||
#else
|
||||
# define ASSERT_LOCKED_RECURSIVE(r) do {} while (false)
|
||||
# define ASSERT_LOCKED_MUTEX(m) do {} while (false)
|
||||
# define ASSERT_WRITE_LOCKED_RW_LOCK(m) do {} while (false)
|
||||
# define ASSERT_READ_LOCKED_RW_LOCK(l) do {} while (false)
|
||||
# define ASSERT_UNLOCKED_RW_LOCK(l) do {} while (false)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -180,7 +184,7 @@ static inline status_t
|
||||
rw_lock_read_lock(rw_lock* lock)
|
||||
{
|
||||
#if KDEBUG_RW_LOCK_DEBUG
|
||||
return rw_lock_write_lock(lock);
|
||||
return _rw_lock_read_lock(lock);
|
||||
#else
|
||||
int32 oldCount = atomic_add(&lock->count, 1);
|
||||
if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
|
||||
@@ -195,7 +199,7 @@ rw_lock_read_lock_with_timeout(rw_lock* lock, uint32 timeoutFlags,
|
||||
bigtime_t timeout)
|
||||
{
|
||||
#if KDEBUG_RW_LOCK_DEBUG
|
||||
return mutex_lock_with_timeout(lock, timeoutFlags, timeout);
|
||||
return _rw_lock_read_lock_with_timeout(lock, timeoutFlags, timeout);
|
||||
#else
|
||||
int32 oldCount = atomic_add(&lock->count, 1);
|
||||
if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
|
||||
@@ -209,7 +213,7 @@ static inline void
|
||||
rw_lock_read_unlock(rw_lock* lock)
|
||||
{
|
||||
#if KDEBUG_RW_LOCK_DEBUG
|
||||
rw_lock_write_unlock(lock);
|
||||
_rw_lock_read_unlock(lock);
|
||||
#else
|
||||
int32 oldCount = atomic_add(&lock->count, -1);
|
||||
if (oldCount >= RW_LOCK_WRITER_COUNT_BASE)
|
||||
|
||||
@@ -547,6 +547,10 @@ struct Thread : TeamThreadIteratorEntry<thread_id>, KernelReferenceable {
|
||||
void (*post_interrupt_callback)(void*);
|
||||
void* post_interrupt_data;
|
||||
|
||||
#if KDEBUG_RW_LOCK_DEBUG
|
||||
rw_lock* held_read_locks[64] = {}; // only modified by this thread
|
||||
#endif
|
||||
|
||||
// architecture dependent section
|
||||
struct arch_thread arch_info;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user