linux/kernel/locking/ww_rt_mutex.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * rtmutex API
   4 */
   5#include <linux/spinlock.h>
   6#include <linux/export.h>
   7
   8#define RT_MUTEX_BUILD_MUTEX
   9#define WW_RT
  10#include "rtmutex.c"
  11
  12static int __sched
  13__ww_rt_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ww_ctx,
  14                   unsigned int state, unsigned long ip)
  15{
  16        struct lockdep_map __maybe_unused *nest_lock = NULL;
  17        struct rt_mutex *rtm = &lock->base;
  18        int ret;
  19
  20        might_sleep();
  21
  22        if (ww_ctx) {
  23                if (unlikely(ww_ctx == READ_ONCE(lock->ctx)))
  24                        return -EALREADY;
  25
  26                /*
  27                 * Reset the wounded flag after a kill. No other process can
  28                 * race and wound us here, since they can't have a valid owner
  29                 * pointer if we don't have any locks held.
  30                 */
  31                if (ww_ctx->acquired == 0)
  32                        ww_ctx->wounded = 0;
  33
  34#ifdef CONFIG_DEBUG_LOCK_ALLOC
  35                nest_lock = &ww_ctx->dep_map;
  36#endif
  37        }
  38        mutex_acquire_nest(&rtm->dep_map, 0, 0, nest_lock, ip);
  39
  40        if (likely(rt_mutex_cmpxchg_acquire(&rtm->rtmutex, NULL, current))) {
  41                if (ww_ctx)
  42                        ww_mutex_set_context_fastpath(lock, ww_ctx);
  43                return 0;
  44        }
  45
  46        ret = rt_mutex_slowlock(&rtm->rtmutex, ww_ctx, state);
  47
  48        if (ret)
  49                mutex_release(&rtm->dep_map, ip);
  50        return ret;
  51}
  52
  53int __sched
  54ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
  55{
  56        return __ww_rt_mutex_lock(lock, ctx, TASK_UNINTERRUPTIBLE, _RET_IP_);
  57}
  58EXPORT_SYMBOL(ww_mutex_lock);
  59
  60int __sched
  61ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
  62{
  63        return __ww_rt_mutex_lock(lock, ctx, TASK_INTERRUPTIBLE, _RET_IP_);
  64}
  65EXPORT_SYMBOL(ww_mutex_lock_interruptible);
  66
  67void __sched ww_mutex_unlock(struct ww_mutex *lock)
  68{
  69        struct rt_mutex *rtm = &lock->base;
  70
  71        __ww_mutex_unlock(lock);
  72
  73        mutex_release(&rtm->dep_map, _RET_IP_);
  74        __rt_mutex_unlock(&rtm->rtmutex);
  75}
  76EXPORT_SYMBOL(ww_mutex_unlock);
  77