Mercurial > hvf > hvf-old
view cp/nucleus/ldep.c @ 503:4e44881e27de
cp: implement mutex dependency tracking
Inspired by the Linux kernel's lockdep code. Currently, ldep is completely
oblivious when it comes to spinlocks. Additionally, it does not actually
check for circular/recursive locking.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Fri, 22 Apr 2011 15:42:29 -0400 |
parents | |
children | b1c6346f553c |
line wrap: on
line source
/* * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * This file is released under the GPLv2. See the COPYING file for more * details. */ #include <sched.h> #include <list.h> #include <spinlock.h> #include <ldep.h> static spinlock_t __lock = SPIN_LOCK_UNLOCKED; static int ldep_enabled; void ldep_on() { unsigned long mask; spin_lock_intsave(&__lock, &mask); ldep_enabled = 1; spin_unlock_intrestore(&__lock, mask); } static int __get_stack_slot() { current->nr_locks++; if (current->nr_locks == LDEP_STACK_SIZE) { con_printf(NULL, "task '%s' exceeded the number of tracked " "locks (%d)! disabling ldep!\n", current->name, LDEP_STACK_SIZE); return 1; } return 0; } static void print_held_locks() { struct held_lock *cur; int i; con_printf(NULL, "\nlocks currently held:\n"); for(i=0; i<current->nr_locks; i++) { cur = ¤t->lock_stack[i]; con_printf(NULL, " #%d: (%s), at %p\n", i, cur->lockname, cur->ra); } } void ldep_lock(void *lock, struct lock_class *c, char *lockname) { void *ra = __builtin_return_address(0); struct held_lock *cur; unsigned long mask; // LOCK spin_lock_intsave(&__lock, &mask); if (!ldep_enabled) goto out; /* ok, no issues, add the lock we're trying to get to the stack */ if (__get_stack_slot()) goto out; cur = ¤t->lock_stack[current->nr_locks-1]; cur->ra = ra; cur->lock = lock; cur->lockname = lockname; out: // UNLOCK spin_unlock_intrestore(&__lock, mask); } void ldep_unlock(void *lock, char *lockname) { void *ra = __builtin_return_address(0); struct held_lock *cur; unsigned long mask; int i; // LOCK spin_lock_intsave(&__lock, &mask); if (!ldep_enabled) goto out; for(i=0; i<current->nr_locks; i++) { cur = ¤t->lock_stack[i]; if (cur->lock == lock) goto found; } con_printf(NULL, "task '%s' is trying to release lock it doesn't have:\n", current->name); con_printf(NULL, " (%s), at %p\n", lockname, ra); print_held_locks(); ldep_enabled = 0; goto out; found: if (i != current->nr_locks-1) memcpy(¤t->lock_stack[i], ¤t->lock_stack[i+1], current->nr_locks - i - 1); current->nr_locks--; out: // UNLOCK spin_unlock_intrestore(&__lock, mask); } void ldep_no_locks() { void *ra = __builtin_return_address(0); unsigned long mask; // LOCK spin_lock_intsave(&__lock, &mask); if (!ldep_enabled) goto out; if (!current->nr_locks) goto out; con_printf(NULL, "task '%s' is holding a lock when it shouldn't have:\n", current->name); con_printf(NULL, " at %p\n", ra); print_held_locks(); ldep_enabled = 0; out: // UNLOCK spin_unlock_intrestore(&__lock, mask); }