diff options
Diffstat (limited to 'runtime/probe_lock.h')
-rw-r--r-- | runtime/probe_lock.h | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/runtime/probe_lock.h b/runtime/probe_lock.h new file mode 100644 index 00000000..1915d4ff --- /dev/null +++ b/runtime/probe_lock.h @@ -0,0 +1,68 @@ +/* probe locking header file + * Copyright (C) 2009 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + +#ifndef _PROBE_LOCK_H +#define _PROBE_LOCK_H + +#include <linux/spinlock.h> + +// XXX: old 2.6 kernel hack +#ifndef read_trylock +#define read_trylock(x) ({ read_lock(x); 1; }) +#endif + +struct stp_probe_lock { + #ifdef STP_TIMING + atomic_t *skipped; + #endif + rwlock_t *lock; + unsigned write_p; +}; + + +static void +stp_unlock_probe(const struct stp_probe_lock *locks, unsigned num_locks) +{ + unsigned i; + for (i = num_locks; i-- > 0;) { + if (locks[i].write_p) + write_unlock(locks[i].lock); + else + read_unlock(locks[i].lock); + } +} + + +static unsigned +stp_lock_probe(const struct stp_probe_lock *locks, unsigned num_locks) +{ + unsigned i, numtrylock = 0; + for (i = 0; i < num_locks; ++i) { + if (locks[i].write_p) + while (!write_trylock(locks[i].lock) && + (++numtrylock < MAXTRYLOCK)) + ndelay (TRYLOCKDELAY); + else + while (!read_trylock(locks[i].lock) && + (++numtrylock < MAXTRYLOCK)) + ndelay (TRYLOCKDELAY); + if (unlikely(numtrylock >= MAXTRYLOCK)) { + atomic_inc(&skipped_count); + #ifdef STP_TIMING + atomic_inc(locks[i].skipped); + #endif + stp_unlock_probe(locks, i); + return 0; + } + } + return 1; +} + + +#endif /* _PROBE_LOCK_H */ |