XenevaOS
Loading...
Searching...
No Matches
mutex.h
Go to the documentation of this file.
1#ifndef __LINUX_MUTEX_H__
2#define __LINUX_MUTEX_H__
3
4/*
5 * DCL <linux/mutex.h> -- mutexes, plus the two guard classes tty/serial code
6 * takes them through.
7 *
8 * mutex_init/mutex_lock/mutex_unlock are already defined in
9 * <linux/kernel.h> as no-ops, and `typedef int mutex;` lives there too.
10 * This header supplies what the mainline files call but kernel.h does not:
11 *
12 * - `struct mutex`, the tag serial_core.c and tty_io.c declare fields with.
13 * (kernel.h's `typedef int mutex` is a different identifier -- the struct
14 * tag and the ordinary name are separate namespaces in C -- so both can
15 * coexist. `struct mutex m;` gets the struct; `mutex_lock(&m)` still hits
16 * kernel.h's macro.)
17 *
18 * - mutex_lock_interruptible / mutex_trylock / mutex_is_locked, each
19 * answering in the sense the no-op contract implies: an interruptible
20 * take always succeeds, a trylock always wins, and a lock held by the
21 * running context reads as held. That last one is worth stating plainly
22 * -- there is no contention for it to observe, so "held" is not a
23 * simulation of a queue, it is the truth about a lock nobody else can
24 * be waiting on.
25 *
26 * - the `mutex` and `mutex_intr` guard classes. mutex_intr is conditional:
27 * scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &port->mutex) at
28 * serial_core.c:1144 is the only conditional guard in the whole set, and
29 * it is what makes that function's early return safe.
30 *
31 * Concurrency note, recorded rather than hidden: tty's correctness leans on
32 * these for serialising termios changes against readers, and on rwsem for the
33 * same. With no-op locks that serialisation does not happen. It does not
34 * affect a single reader on a single console -- which is every configuration
35 * this milestone targets -- but two processes opening the same port and
36 * racing a tcsetattr against a read is not protected. Making these real is a
37 * separate, deliberate change: it is the moment Xeneva's process-level
38 * locking has to reach into driver context.
39 */
40
41#include <linux/kernel.h> /* mutex_init/lock/unlock, typedef int mutex */
42#include <linux/cleanup.h>
43#include <linux/atomic.h> /* atomic_long_t -- <linux/ww_mutex.h> puts one
44 * in struct ww_class and adds to it from
45 * ww_mutex_lock() without naming this header.
46 * mainline's mutex.h takes it the same way
47 * (:18), so this is DCL catching up rather
48 * than a divergence: without it ww_mutex.h
49 * saw neither the type nor
50 * atomic_long_inc_return_relaxed() and clang
51 * reported the definition as conflicting with
52 * its own earlier implicit declaration. */
53#include <linux/lockdep.h> /* lockdep_set_subclass() -- called on
54 * &tty_port.buf.lock by tty_buffer.c:618,
55 * which includes no lockdep header itself,
56 * so this is where it has to be reachable
57 * from. */
58
59struct mutex {
60 int state;
61};
62
63#define mutex_lock_interruptible(m) (0)
64#define mutex_trylock(m) (1)
65#define mutex_is_locked(m) (1)
66#define mutex_lock_killable(m) (0)
67#define mutex_unlock_nested(m, s) mutex_unlock(m)
68/* mainline kernel/locking/mutex.c; ww_mutex.h's ww_mutex_base_init()
69 * and drm_drv.c's teardown spell the constructor/destructor this way. */
70#define __mutex_init(m, name, key) mutex_init(m)
71#define mutex_destroy(m) do { (void)(m); } while (0)
72
73/*
74 * atomic_dec_and_mutex_lock(v, lock) -- mainline's "last reference takes the
75 * lock" pair (mutex.h:64): decrement, and only if the counter reached zero,
76 * lock on the way out. drm_file.c:505 (drm_release_noglobal) is the caller,
77 * and it branches on the return value. The lock half is a no-op in DCL
78 * (mutex_lock, kernel.h:222), so atomic_dec_and_test() is the whole of the
79 * semantics that survives: false without locking when the count is not zero,
80 * true after locking when it is. It is called through mutex_lock() rather
81 * than skipped so the day the mutex becomes real the pairing is already
82 * spelled out here.
83 */
84static inline bool atomic_dec_and_mutex_lock(atomic_t* v, struct mutex* lock)
85{
86 if (!atomic_dec_and_test(v))
87 return false;
88 mutex_lock(lock);
89 return true;
90}
91
93DCL_LOCK_GUARD_COND(mutex_intr, struct mutex,
95
96
97/*
98 * DEFINE_MUTEX(name) -- the static-initialiser form.
99 *
100 * serial_core.c:40 writes `static DEFINE_MUTEX(port_mutex);`, and without the
101 * macro clang read it as an implicit function declaration followed by a
102 * parameter list: two errors (implicit-int, "parameter list without types")
103 * at one line, which is the tell for a missing object-like macro rather than
104 * a missing function. port_mutex is the lock serial_core holds while walking
105 * its driver list (serial_core_ctrl_find() says as much in its doc comment),
106 * so it has to be a real object with static storage duration even though
107 * taking it is a no-op.
108 *
109 * mainline's __MUTEX_INITIALIZER fills in wait_lock, osq, wait_list and a
110 * lockdep map. DCL's struct mutex is one int (see above), so { 0 } is the
111 * entire initialiser -- and that is the point: there is nothing to lay out.
112 */
113#define DEFINE_MUTEX(name) struct mutex name = { 0 }
114#endif /* __LINUX_MUTEX_H__ */
#define DCL_LOCK_GUARD(name, type, acquire, release)
Definition cleanup.h:168
#define DCL_LOCK_GUARD_COND(name, type, acquire, release)
Definition cleanup.h:180
#define mutex_lock(m)
Definition kernel.h:229
#define mutex_unlock(m)
Definition kernel.h:230
#define mutex_lock_interruptible(m)
Definition mutex.h:63
Definition atomic.h:31
Definition mutex.h:59
int state
Definition mutex.h:60