XenevaOS
Loading...
Searching...
No Matches
ww_mutex.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Wound/Wait Mutexes: blocking mutual exclusion locks with deadlock avoidance
4 *
5 * Original mutex implementation started by Ingo Molnar:
6 *
7 * Copyright (C) 2004, 2005, 2006 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
8 *
9 * Wait/Die implementation:
10 * Copyright (C) 2013 Canonical Ltd.
11 * Choice of algorithm:
12 * Copyright (C) 2018 WMWare Inc.
13 *
14 * This file contains the main data structure and API definitions.
15 */
16
17#ifndef __LINUX_WW_MUTEX_H
18#define __LINUX_WW_MUTEX_H
19
21#include <linux/mutex.h>
22#include <linux/rtmutex.h>
23
24#if defined(CONFIG_DEBUG_MUTEXES) || \
25 (defined(CONFIG_PREEMPT_RT) && defined(CONFIG_DEBUG_RT_MUTEXES))
26#define DEBUG_WW_MUTEXES
27#endif
28
29#ifndef CONFIG_PREEMPT_RT
30#define WW_MUTEX_BASE mutex
31#define ww_mutex_base_init(l,n,k) __mutex_init(l,n,k)
32#define ww_mutex_base_is_locked(b) mutex_is_locked((b))
33#else
34#define WW_MUTEX_BASE rt_mutex
35#define ww_mutex_base_init(l,n,k) __rt_mutex_init(l,n,k)
36#define ww_mutex_base_is_locked(b) rt_mutex_base_is_locked(&(b)->rtmutex)
37#endif
38
47
49 struct WW_MUTEX_BASE base;
50 struct ww_acquire_ctx *ctx;
51#ifdef DEBUG_WW_MUTEXES
52 struct ww_class *ww_class;
53#endif
54};
55
56context_lock_struct(ww_acquire_ctx) {
57 struct task_struct *task;
58 unsigned long stamp;
59 unsigned int acquired;
60 unsigned short wounded;
61 unsigned short is_wait_die;
62#ifdef DEBUG_WW_MUTEXES
63 unsigned int done_acquire;
64 struct ww_class *ww_class;
65 void *contending_lock;
66#endif
67#ifdef CONFIG_DEBUG_LOCK_ALLOC
68 struct lockdep_map dep_map;
78 struct lockdep_map first_lock_dep_map;
79#endif
80#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
81 unsigned int deadlock_inject_interval;
82 unsigned int deadlock_inject_countdown;
83#endif
84};
85
86#define __WW_CLASS_INITIALIZER(ww_class, _is_wait_die) \
87 { .stamp = ATOMIC_LONG_INIT(0) \
88 , .acquire_name = #ww_class "_acquire" \
89 , .mutex_name = #ww_class "_mutex" \
90 , .is_wait_die = _is_wait_die }
91
92#define DEFINE_WD_CLASS(classname) \
93 struct ww_class classname = __WW_CLASS_INITIALIZER(classname, 1)
94
95#define DEFINE_WW_CLASS(classname) \
96 struct ww_class classname = __WW_CLASS_INITIALIZER(classname, 0)
97
109static inline void ww_mutex_init(struct ww_mutex *lock,
110 struct ww_class *ww_class)
111{
113 lock->ctx = NULL;
114#ifdef DEBUG_WW_MUTEXES
115 lock->ww_class = ww_class;
116#endif
117}
118
143static inline void ww_acquire_init(struct ww_acquire_ctx *ctx,
144 struct ww_class *ww_class)
146{
147 ctx->task = current;
148 ctx->stamp = atomic_long_inc_return_relaxed(&ww_class->stamp);
149 ctx->acquired = 0;
150 ctx->wounded = false;
151 ctx->is_wait_die = ww_class->is_wait_die;
152#ifdef DEBUG_WW_MUTEXES
153 ctx->ww_class = ww_class;
154 ctx->done_acquire = 0;
155 ctx->contending_lock = NULL;
156#endif
157#ifdef CONFIG_DEBUG_LOCK_ALLOC
158 debug_check_no_locks_freed((void *)ctx, sizeof(*ctx));
159 lockdep_init_map(&ctx->dep_map, ww_class->acquire_name,
160 &ww_class->acquire_key, 0);
161 lockdep_init_map_wait(&ctx->first_lock_dep_map, ww_class->mutex_name,
162 &ww_class->mutex_key, 0, LD_WAIT_SLEEP);
163 mutex_acquire(&ctx->dep_map, 0, 0, _RET_IP_);
164 mutex_acquire_nest(&ctx->first_lock_dep_map, 0, 0, &ctx->dep_map, _RET_IP_);
165#endif
166#ifdef CONFIG_DEBUG_WW_MUTEX_SLOWPATH
167 ctx->deadlock_inject_interval = 1;
168 ctx->deadlock_inject_countdown = ctx->stamp & 0xf;
169#endif
170}
171
183static inline void ww_acquire_done(struct ww_acquire_ctx *ctx)
184 __must_hold(ctx)
185{
186#ifdef DEBUG_WW_MUTEXES
188
189 DEBUG_LOCKS_WARN_ON(ctx->done_acquire);
190 ctx->done_acquire = 1;
191#endif
192}
193
201static inline void ww_acquire_fini(struct ww_acquire_ctx *ctx)
203{
204#ifdef CONFIG_DEBUG_LOCK_ALLOC
205 mutex_release(&ctx->first_lock_dep_map, _THIS_IP_);
206 mutex_release(&ctx->dep_map, _THIS_IP_);
207#endif
208#ifdef DEBUG_WW_MUTEXES
209 DEBUG_LOCKS_WARN_ON(ctx->acquired);
210 if (!IS_ENABLED(CONFIG_PROVE_LOCKING))
211 /*
212 * lockdep will normally handle this,
213 * but fail without anyway
214 */
215 ctx->done_acquire = 1;
216
217 if (!IS_ENABLED(CONFIG_DEBUG_LOCK_ALLOC))
218 /* ensure ww_acquire_fini will still fail if called twice */
219 ctx->acquired = ~0U;
220#endif
221}
222
252extern int /* __must_check */ ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
253 __cond_acquires(0, lock) __must_hold(ctx);
254
285extern int __must_check ww_mutex_lock_interruptible(struct ww_mutex *lock,
286 struct ww_acquire_ctx *ctx)
287 __cond_acquires(0, lock) __must_hold(ctx);
288
312static inline void
313ww_mutex_lock_slow(struct ww_mutex *lock, struct ww_acquire_ctx *ctx)
315{
316 int ret;
317#ifdef DEBUG_WW_MUTEXES
318 DEBUG_LOCKS_WARN_ON(!ctx->contending_lock);
319#endif
320 ret = ww_mutex_lock(lock, ctx);
321 (void)ret;
322}
323
349static inline int __must_check
350ww_mutex_lock_slow_interruptible(struct ww_mutex *lock,
351 struct ww_acquire_ctx *ctx)
353{
354#ifdef DEBUG_WW_MUTEXES
355 DEBUG_LOCKS_WARN_ON(!ctx->contending_lock);
356#endif
357 return ww_mutex_lock_interruptible(lock, ctx);
358}
359
360extern void ww_mutex_unlock(struct ww_mutex *lock) __releases(lock);
361
362extern int __must_check ww_mutex_trylock(struct ww_mutex *lock,
363 struct ww_acquire_ctx *ctx)
364 __cond_acquires(true, lock) __must_hold(ctx);
365
366/***
367 * ww_mutex_destroy - mark a w/w mutex unusable
368 * @lock: the mutex to be destroyed
369 *
370 * This function marks the mutex uninitialized, and any subsequent
371 * use of the mutex is forbidden. The mutex must not be locked when
372 * this function is called.
373 */
374static inline void ww_mutex_destroy(struct ww_mutex *lock)
375 __must_not_hold(lock)
376{
377#ifndef CONFIG_PREEMPT_RT
378 mutex_destroy(&lock->base);
379#endif
380}
381
388static inline bool ww_mutex_is_locked(struct ww_mutex *lock)
389{
390 return ww_mutex_base_is_locked(&lock->base);
391}
392
393#endif
#define NULL
Definition actypes.h:561
#define _THIS_IP_
Definition linkage.h:46
#define __acquires(...)
Definition compiler-context-analysis.h:299
#define __must_not_hold(...)
Definition compiler-context-analysis.h:291
#define __cond_acquires(ret, x)
Definition compiler-context-analysis.h:326
#define __must_hold(...)
Definition compiler-context-analysis.h:283
#define context_lock_struct(name,...)
Definition compiler-context-analysis.h:188
#define __no_context_analysis
Definition compiler-context-analysis.h:191
#define __releases(...)
Definition compiler-context-analysis.h:335
#define __must_check
Definition compiler.h:114
#define DEBUG_LOCKS_WARN_ON(c)
Definition debug_locks.h:24
struct i915_user_extension base
Definition i915_drm.h:0
#define _RET_IP_
Definition instruction_pointer.h:22
#define IS_ENABLED(option)
Definition kconfig.h:80
#define U
Definition libunicode.c:1830
#define mutex_destroy(m)
Definition mutex.h:71
#define lockdep_init_map(lock, name, key, sub)
Definition lockdep.h:57
#define lockdep_assert_held(l)
Definition lockdep.h:71
#define current
Definition mm.h:90
Definition atomic.h:211
Definition lockdep.h:160
Definition lockdep.h:161
Definition sched.h:121
Definition ww_mutex.h:39
atomic_long_t stamp
Definition ww_mutex.h:40
struct lock_class_key acquire_key
Definition ww_mutex.h:41
struct lock_class_key mutex_key
Definition ww_mutex.h:42
const char * mutex_name
Definition ww_mutex.h:44
unsigned int is_wait_die
Definition ww_mutex.h:45
const char * acquire_name
Definition ww_mutex.h:43
void ww_mutex_unlock(struct ww_mutex *lock) __releases(lock)
#define ww_mutex_base_init(l, n, k)
Definition ww_mutex.h:31
#define WW_MUTEX_BASE
Definition ww_mutex.h:30
int ww_mutex_lock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) __cond_acquires(0
#define ww_mutex_base_is_locked(b)
Definition ww_mutex.h:32
int __must_check ww_mutex_lock_interruptible(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) __cond_acquires(0
int __must_check ww_mutex_trylock(struct ww_mutex *lock, struct ww_acquire_ctx *ctx) __cond_acquires(true