我试图理解不允许使用“解锁未锁定的互斥锁”将导致无法预料的行为,而Linux内核互斥锁在查看代码时却看不到任何影响。

特别:

/**
 * try to promote the mutex from 0 to 1. if it wasn't 0, call <function>
 * In the failure case, this function is allowed to either set the value to
 * 1, or to set it to a value lower than one.
 * If the implementation sets it to a value of lower than one, the
 * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs
 * to return 0 otherwise.
 */
static inline void
__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
{
    if (unlikely(atomic_xchg(count, 1) != 0))
        fail_fn(count);
}

fail_fn在哪里
static inline void
__mutex_unlock_common_slowpath(atomic_t *lock_count, int nested)
{
    struct mutex *lock = container_of(lock_count, struct mutex, count);
    unsigned long flags;

    spin_lock_mutex(&lock->wait_lock, flags);
    mutex_release(&lock->dep_map, nested, _RET_IP_);
    debug_mutex_unlock(lock);

    /*
     * some architectures leave the lock unlocked in the fastpath failure
     * case, others need to leave it locked. In the later case we have to
     * unlock it here
     */
    if (__mutex_slowpath_needs_to_unlock())
        atomic_set(&lock->count, 1);

    if (!list_empty(&lock->wait_list)) {
        /* get the first entry from the wait-list: */
        struct mutex_waiter *waiter =
                list_entry(lock->wait_list.next,
                       struct mutex_waiter, list);

        debug_mutex_wake_waiter(lock, waiter);

        wake_up_process(waiter->task);
    }

    spin_unlock_mutex(&lock->wait_lock, flags);
}

根据我的判断,无论__mutex_slowpath_needs_to_unlock()是什么,它都将保持解锁状态,我在这里错过了什么吗?

最佳答案

正如Wyzard所建议的,文档可能希望保持某些开放状态。例如,某些other implementations可以使用原子增量而不是交换,例如this one:

static inline void __mutex_fastpath_unlock(atomic_t *v,
                                           void (*fail_fn)(atomic_t *))
{
        asm_volatile_goto(LOCK_PREFIX "   incl %0\n"
                          "   jg %l[exit]\n"
                          : : "m" (v->counter)
                          : "memory", "cc"
                          : exit);

如您所见,连续调用两次是不安全的,因为accompanying try_lock除了0和1以外,不会期望其他任何值:
static inline int __mutex_fastpath_trylock(atomic_t *count,
                                           int (*fail_fn)(atomic_t *))
{
        if (likely(atomic_cmpxchg(count, 1, 0) == 1))

09-28 08:44