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