1*51f49692SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
2*51f49692SMarouene Boubakri /*
3*51f49692SMarouene Boubakri * Copyright (c) 2018, Linaro Limited
4*51f49692SMarouene Boubakri */
5*51f49692SMarouene Boubakri
6*51f49692SMarouene Boubakri #include <assert.h>
7*51f49692SMarouene Boubakri #include <kernel/lockdep.h>
8*51f49692SMarouene Boubakri #include <kernel/spinlock.h>
9*51f49692SMarouene Boubakri #include <kernel/thread.h>
10*51f49692SMarouene Boubakri #include <sys/queue.h>
11*51f49692SMarouene Boubakri #include <trace.h>
12*51f49692SMarouene Boubakri
13*51f49692SMarouene Boubakri #include "mutex_lockdep.h"
14*51f49692SMarouene Boubakri
15*51f49692SMarouene Boubakri /* Global graph of all mutexes used in the code */
16*51f49692SMarouene Boubakri static struct lockdep_node_head graph = TAILQ_HEAD_INITIALIZER(graph);
17*51f49692SMarouene Boubakri
18*51f49692SMarouene Boubakri /* Protects @graph */
19*51f49692SMarouene Boubakri static unsigned int graph_lock = SPINLOCK_UNLOCK;
20*51f49692SMarouene Boubakri
21*51f49692SMarouene Boubakri /*
22*51f49692SMarouene Boubakri * One queue per thread, contains the mutexes the thread owns at any point in
23*51f49692SMarouene Boubakri * time (in aquire order)
24*51f49692SMarouene Boubakri */
25*51f49692SMarouene Boubakri static struct lockdep_lock_head owned[CFG_NUM_THREADS];
26*51f49692SMarouene Boubakri
mutex_lockdep_init(void)27*51f49692SMarouene Boubakri void mutex_lockdep_init(void)
28*51f49692SMarouene Boubakri {
29*51f49692SMarouene Boubakri int n = 0;
30*51f49692SMarouene Boubakri
31*51f49692SMarouene Boubakri for (n = 0; n < CFG_NUM_THREADS; n++)
32*51f49692SMarouene Boubakri TAILQ_INIT(&owned[n]);
33*51f49692SMarouene Boubakri
34*51f49692SMarouene Boubakri DMSG("lockdep is enabled for mutexes");
35*51f49692SMarouene Boubakri }
36*51f49692SMarouene Boubakri
mutex_lock_check(struct mutex * m)37*51f49692SMarouene Boubakri void mutex_lock_check(struct mutex *m)
38*51f49692SMarouene Boubakri {
39*51f49692SMarouene Boubakri short int thread = thread_get_id();
40*51f49692SMarouene Boubakri uint32_t exceptions = 0;
41*51f49692SMarouene Boubakri
42*51f49692SMarouene Boubakri exceptions = cpu_spin_lock_xsave(&graph_lock);
43*51f49692SMarouene Boubakri lockdep_lock_acquire(&graph, &owned[thread], (uintptr_t)m);
44*51f49692SMarouene Boubakri cpu_spin_unlock_xrestore(&graph_lock, exceptions);
45*51f49692SMarouene Boubakri }
46*51f49692SMarouene Boubakri
mutex_trylock_check(struct mutex * m)47*51f49692SMarouene Boubakri void mutex_trylock_check(struct mutex *m)
48*51f49692SMarouene Boubakri {
49*51f49692SMarouene Boubakri short int thread = thread_get_id();
50*51f49692SMarouene Boubakri uint32_t exceptions = 0;
51*51f49692SMarouene Boubakri
52*51f49692SMarouene Boubakri exceptions = cpu_spin_lock_xsave(&graph_lock);
53*51f49692SMarouene Boubakri lockdep_lock_tryacquire(&graph, &owned[thread], (uintptr_t)m);
54*51f49692SMarouene Boubakri cpu_spin_unlock_xrestore(&graph_lock, exceptions);
55*51f49692SMarouene Boubakri }
56*51f49692SMarouene Boubakri
mutex_unlock_check(struct mutex * m)57*51f49692SMarouene Boubakri void mutex_unlock_check(struct mutex *m)
58*51f49692SMarouene Boubakri {
59*51f49692SMarouene Boubakri short int thread = thread_get_id();
60*51f49692SMarouene Boubakri uint32_t exceptions = 0;
61*51f49692SMarouene Boubakri
62*51f49692SMarouene Boubakri exceptions = cpu_spin_lock_xsave(&graph_lock);
63*51f49692SMarouene Boubakri lockdep_lock_release(&owned[thread], (uintptr_t)m);
64*51f49692SMarouene Boubakri cpu_spin_unlock_xrestore(&graph_lock, exceptions);
65*51f49692SMarouene Boubakri }
66*51f49692SMarouene Boubakri
mutex_destroy_check(struct mutex * m)67*51f49692SMarouene Boubakri void mutex_destroy_check(struct mutex *m)
68*51f49692SMarouene Boubakri {
69*51f49692SMarouene Boubakri uint32_t exceptions = cpu_spin_lock_xsave(&graph_lock);
70*51f49692SMarouene Boubakri
71*51f49692SMarouene Boubakri lockdep_lock_destroy(&graph, (uintptr_t)m);
72*51f49692SMarouene Boubakri cpu_spin_unlock_xrestore(&graph_lock, exceptions);
73*51f49692SMarouene Boubakri }
74