Mercurial > libjeffpc
changeset 754:389216c34b53
synch: each rwlock should contain a magic number
Much like the (mutex) lock and condition variable structures, this magic
number is simply the pointer to the rwlock itself. This trivially catches
three issues:
(1) rwlocks getting clobbered
(2) rwlocks getting moved around (via memmove/memcpy)
(3) rwlocks used by lock/unlock after a destroy
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Thu, 25 Jul 2019 10:55:43 -0400 |
parents | eadcec7390ee |
children | 607f480900f2 |
files | include/jeffpc/synch.h synch.c |
diffstat | 2 files changed, 65 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/include/jeffpc/synch.h Thu Jul 25 11:24:45 2019 -0400 +++ b/include/jeffpc/synch.h Thu Jul 25 10:55:43 2019 -0400 @@ -64,6 +64,7 @@ struct rwlock { pthread_rwlock_t lock; + uintptr_t magic; }; struct cond {
--- a/synch.c Thu Jul 25 11:24:45 2019 -0400 +++ b/synch.c Thu Jul 25 10:55:43 2019 -0400 @@ -105,6 +105,8 @@ #define GENERATE_LOCK_MASK_ARGS(l) \ ((l)->magic != (uintptr_t) (l)) ? 'M' : '.' +#define GENERATE_RW_MASK_ARGS(l) \ + ((l)->magic != (uintptr_t) (l)) ? 'M' : '.' #define GENERATE_COND_MASK_ARGS(c) \ ((c)->magic != (uintptr_t) (c)) ? 'M' : '.' @@ -121,6 +123,14 @@ where->file, where->line); } +static void print_rw(struct rwlock *lock, const struct lock_context *where) +{ + cmn_err(CE_CRIT, "lockdep: %p <%c> at %s:%d", + lock, + GENERATE_RW_MASK_ARGS(lock), + where->file, where->line); +} + static void print_cond(struct cond *cond, const struct lock_context *where) { cmn_err(CE_CRIT, "lockdep: %p <%c> at %s:%d", @@ -389,6 +399,17 @@ panic("lockdep: Aborting - bad lock magic"); } +static void check_rw_magic(struct rwlock *lock, const char *op, + const struct lock_context *where) +{ + if (lock->magic == (uintptr_t) lock) + return; + + cmn_err(CE_CRIT, "lockdep: thread trying to %s rwlock with bad magic", op); + print_rw(lock, where); + panic("lockdep: Aborting - bad rwlock magic"); +} + static void check_cond_magic(struct cond *cond, const char *op, const struct lock_context *where) { @@ -505,6 +526,41 @@ #endif } +static void verify_rw_init(const struct lock_context *where, struct rwlock *l) +{ + if (!l) + print_invalid_call("RWINIT", where); + + l->magic = (uintptr_t) l; +} + +static void verify_rw_destroy(const struct lock_context *where, struct rwlock *l) +{ + if (!l) + print_invalid_call("RWDESTROY", where); + + check_rw_magic(l, "destroy", where); + + l->magic = DESTROYED_MAGIC; +} + +static void verify_rw_lock(const struct lock_context *where, struct rwlock *l, + bool wr) +{ + if (!l) + print_invalid_call("RWLOCK", where); + + check_rw_magic(l, "acquire", where); +} + +static void verify_rw_unlock(const struct lock_context *where, struct rwlock *l) +{ + if (!l) + print_invalid_call("RWUNLOCK", where); + + check_rw_magic(l, "release", where); +} + static void verify_cond_init(const struct lock_context *where, struct cond *c) { if (!c) @@ -657,6 +713,8 @@ { int ret; + verify_rw_init(where, l); + ret = pthread_rwlock_init(&l->lock, NULL); if (ret) panic("rwlock init failed @ %s:%d: %s", @@ -667,6 +725,8 @@ { int ret; + verify_rw_destroy(where, l); + ret = pthread_rwlock_destroy(&l->lock); if (ret) panic("rwlock destroy failed @ %s:%d: %s", @@ -677,6 +737,8 @@ { int ret; + verify_rw_lock(where, l, wr); + if (wr) ret = pthread_rwlock_wrlock(&l->lock); else @@ -692,6 +754,8 @@ { int ret; + verify_rw_unlock(where, l); + ret = pthread_rwlock_unlock(&l->lock); if (ret) panic("rwlock unlock failed @ %s:%d: %s",