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 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 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 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 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 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