kernel/lock: Fix ABI compatibility between KDEBUG and non-KDEBUG builds.
This breaks kernel ABI on KDEBUG builds (but not non-KDEBUG builds), but it does so in order to resolve a long-standing incompatibility between them: until now, any kernel add-ons built against one which made use of these lock facilities could not be run on the other; instead you would get hangs and/or crashes. After this change, kernel add-ons built with a KDEBUG configuration should work on a non-KDEBUG kernel, while add-ons built with a non-KDEBUG configuration will fail to load on a KDEBUG kernel with unresolved symbols, preventing incorrect and broken operation.
This commit is contained in:
@@ -164,6 +164,14 @@ extern status_t mutex_switch_lock(mutex* from, mutex* to);
|
|||||||
extern status_t mutex_switch_from_read_lock(rw_lock* from, mutex* to);
|
extern status_t mutex_switch_from_read_lock(rw_lock* from, mutex* to);
|
||||||
// Like mutex_switch_lock(), just for switching from a read-locked rw_lock.
|
// Like mutex_switch_lock(), just for switching from a read-locked rw_lock.
|
||||||
|
|
||||||
|
#if KDEBUG
|
||||||
|
extern status_t mutex_lock(mutex* lock);
|
||||||
|
extern void mutex_unlock(mutex* lock);
|
||||||
|
extern status_t mutex_trylock(mutex* lock);
|
||||||
|
extern status_t mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags,
|
||||||
|
bigtime_t timeout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// implementation private:
|
// implementation private:
|
||||||
|
|
||||||
@@ -173,11 +181,12 @@ extern status_t _rw_lock_read_lock_with_timeout(rw_lock* lock,
|
|||||||
extern void _rw_lock_read_unlock(rw_lock* lock);
|
extern void _rw_lock_read_unlock(rw_lock* lock);
|
||||||
extern void _rw_lock_write_unlock(rw_lock* lock);
|
extern void _rw_lock_write_unlock(rw_lock* lock);
|
||||||
|
|
||||||
|
#if !KDEBUG
|
||||||
extern status_t _mutex_lock(mutex* lock, void* locker);
|
extern status_t _mutex_lock(mutex* lock, void* locker);
|
||||||
extern void _mutex_unlock(mutex* lock);
|
extern void _mutex_unlock(mutex* lock);
|
||||||
extern status_t _mutex_trylock(mutex* lock);
|
|
||||||
extern status_t _mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags,
|
extern status_t _mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags,
|
||||||
bigtime_t timeout);
|
bigtime_t timeout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline status_t
|
static inline status_t
|
||||||
@@ -229,53 +238,41 @@ rw_lock_write_unlock(rw_lock* lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if !KDEBUG
|
||||||
static inline status_t
|
static inline status_t
|
||||||
mutex_lock(mutex* lock)
|
mutex_lock(mutex* lock)
|
||||||
{
|
{
|
||||||
#if KDEBUG
|
|
||||||
return _mutex_lock(lock, NULL);
|
|
||||||
#else
|
|
||||||
if (atomic_add(&lock->count, -1) < 0)
|
if (atomic_add(&lock->count, -1) < 0)
|
||||||
return _mutex_lock(lock, NULL);
|
return _mutex_lock(lock, NULL);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline status_t
|
static inline status_t
|
||||||
mutex_trylock(mutex* lock)
|
mutex_trylock(mutex* lock)
|
||||||
{
|
{
|
||||||
#if KDEBUG
|
|
||||||
return _mutex_trylock(lock);
|
|
||||||
#else
|
|
||||||
if (atomic_test_and_set(&lock->count, -1, 0) != 0)
|
if (atomic_test_and_set(&lock->count, -1, 0) != 0)
|
||||||
return B_WOULD_BLOCK;
|
return B_WOULD_BLOCK;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline status_t
|
static inline status_t
|
||||||
mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
|
mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
|
||||||
{
|
{
|
||||||
#if KDEBUG
|
|
||||||
return _mutex_lock_with_timeout(lock, timeoutFlags, timeout);
|
|
||||||
#else
|
|
||||||
if (atomic_add(&lock->count, -1) < 0)
|
if (atomic_add(&lock->count, -1) < 0)
|
||||||
return _mutex_lock_with_timeout(lock, timeoutFlags, timeout);
|
return _mutex_lock_with_timeout(lock, timeoutFlags, timeout);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
mutex_unlock(mutex* lock)
|
mutex_unlock(mutex* lock)
|
||||||
{
|
{
|
||||||
#if !KDEBUG
|
|
||||||
if (atomic_add(&lock->count, 1) < -1)
|
if (atomic_add(&lock->count, 1) < -1)
|
||||||
#endif
|
|
||||||
_mutex_unlock(lock);
|
_mutex_unlock(lock);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
|||||||
@@ -8,17 +8,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*! Mutex and recursive_lock code */
|
#include <debug.h>
|
||||||
|
|
||||||
|
#if KDEBUG
|
||||||
|
#define KDEBUG_STATIC static
|
||||||
|
static status_t _mutex_lock(struct mutex* lock, void* locker);
|
||||||
|
static void _mutex_unlock(struct mutex* lock);
|
||||||
|
#else
|
||||||
|
#define KDEBUG_STATIC
|
||||||
|
#define mutex_lock mutex_lock_inline
|
||||||
|
#define mutex_unlock mutex_unlock_inline
|
||||||
|
#define mutex_trylock mutex_trylock_inline
|
||||||
|
#define mutex_lock_with_timeout mutex_lock_with_timeout_inline
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
#include <int.h>
|
#include <int.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <listeners.h>
|
#include <listeners.h>
|
||||||
@@ -954,7 +962,7 @@ mutex_switch_from_read_lock(rw_lock* from, mutex* to)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
KDEBUG_STATIC status_t
|
||||||
_mutex_lock(mutex* lock, void* _locker)
|
_mutex_lock(mutex* lock, void* _locker)
|
||||||
{
|
{
|
||||||
#if KDEBUG
|
#if KDEBUG
|
||||||
@@ -1022,7 +1030,7 @@ _mutex_lock(mutex* lock, void* _locker)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
KDEBUG_STATIC void
|
||||||
_mutex_unlock(mutex* lock)
|
_mutex_unlock(mutex* lock)
|
||||||
{
|
{
|
||||||
InterruptsSpinLocker locker(lock->lock);
|
InterruptsSpinLocker locker(lock->lock);
|
||||||
@@ -1064,25 +1072,7 @@ _mutex_unlock(mutex* lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
KDEBUG_STATIC status_t
|
||||||
_mutex_trylock(mutex* lock)
|
|
||||||
{
|
|
||||||
#if KDEBUG
|
|
||||||
InterruptsSpinLocker _(lock->lock);
|
|
||||||
|
|
||||||
if (lock->holder < 0) {
|
|
||||||
lock->holder = thread_get_current_thread_id();
|
|
||||||
return B_OK;
|
|
||||||
} else if (lock->holder == 0)
|
|
||||||
panic("_mutex_trylock(): using uninitialized lock %p", lock);
|
|
||||||
return B_WOULD_BLOCK;
|
|
||||||
#else
|
|
||||||
return mutex_trylock(lock);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
_mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
|
_mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
|
||||||
{
|
{
|
||||||
#if KDEBUG
|
#if KDEBUG
|
||||||
@@ -1183,6 +1173,62 @@ _mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef mutex_trylock
|
||||||
|
status_t
|
||||||
|
mutex_trylock(mutex* lock)
|
||||||
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
InterruptsSpinLocker _(lock->lock);
|
||||||
|
|
||||||
|
if (lock->holder < 0) {
|
||||||
|
lock->holder = thread_get_current_thread_id();
|
||||||
|
return B_OK;
|
||||||
|
} else if (lock->holder == 0) {
|
||||||
|
panic("_mutex_trylock(): using uninitialized lock %p", lock);
|
||||||
|
}
|
||||||
|
return B_WOULD_BLOCK;
|
||||||
|
#else
|
||||||
|
return mutex_trylock_inline(lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef mutex_lock
|
||||||
|
status_t
|
||||||
|
mutex_lock(mutex* lock)
|
||||||
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
return _mutex_lock(lock, NULL);
|
||||||
|
#else
|
||||||
|
return mutex_lock_inline(lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef mutex_unlock
|
||||||
|
void
|
||||||
|
mutex_unlock(mutex* lock)
|
||||||
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
_mutex_unlock(lock);
|
||||||
|
#else
|
||||||
|
mutex_unlock_inline(lock);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef mutex_lock_with_timeout
|
||||||
|
status_t
|
||||||
|
mutex_lock_with_timeout(mutex* lock, uint32 timeoutFlags, bigtime_t timeout)
|
||||||
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
return _mutex_lock_with_timeout(lock, timeoutFlags, timeout);
|
||||||
|
#else
|
||||||
|
return mutex_lock_with_timeout_inline(lock, timeoutFlags, timeout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dump_mutex_info(int argc, char** argv)
|
dump_mutex_info(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user