diff options
author | Michael Brown <mcb30@ipxe.org> | 2010-11-05 22:24:46 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2010-11-08 03:35:35 +0000 |
commit | 6e41f2cf18217dd5f4086852b61bb6f0146c1e0b (patch) | |
tree | 6d5e696d2e626d5187e69428d9d987e8cae9d5fb /src/core/refcnt.c | |
parent | fc69ab94d939214e2a8bbb335a5e7e31552e88e1 (diff) | |
download | ipxe-6e41f2cf18217dd5f4086852b61bb6f0146c1e0b.tar.gz |
[refcnt] Check reference validity on each use of ref_get() and ref_put()
Check that the reference count is valid (i.e. non-negative) on each
call to ref_get() and ref_put(), using an assert() at the point of
use.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core/refcnt.c')
-rw-r--r-- | src/core/refcnt.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/src/core/refcnt.c b/src/core/refcnt.c index e540240f..6117d741 100644 --- a/src/core/refcnt.c +++ b/src/core/refcnt.c @@ -31,18 +31,16 @@ FILE_LICENCE ( GPL2_OR_LATER ); * Increment reference count * * @v refcnt Reference counter, or NULL - * @ret refcnt Reference counter * * If @c refcnt is NULL, no action is taken. */ -struct refcnt * ref_get ( struct refcnt *refcnt ) { +void ref_increment ( struct refcnt *refcnt ) { if ( refcnt ) { - refcnt->refcnt++; + refcnt->count++; DBGC2 ( refcnt, "REFCNT %p incremented to %d\n", - refcnt, refcnt->refcnt ); + refcnt, refcnt->count ); } - return refcnt; } /** @@ -55,18 +53,28 @@ struct refcnt * ref_get ( struct refcnt *refcnt ) { * * If @c refcnt is NULL, no action is taken. */ -void ref_put ( struct refcnt *refcnt ) { +void ref_decrement ( struct refcnt *refcnt ) { if ( ! refcnt ) return; - refcnt->refcnt--; + refcnt->count--; DBGC2 ( refcnt, "REFCNT %p decremented to %d\n", - refcnt, refcnt->refcnt ); + refcnt, refcnt->count ); - if ( refcnt->refcnt >= 0 ) + if ( refcnt->count >= 0 ) return; + if ( refcnt->count < -1 ) { + DBGC ( refcnt, "REFCNT %p decremented too far (%d)!\n", + refcnt, refcnt->count ); + /* Avoid multiple calls to free(), which typically + * result in memory corruption that is very hard to + * track down. + */ + return; + } + if ( refcnt->free ) { DBGC ( refcnt, "REFCNT %p being freed via method %p\n", refcnt, refcnt->free ); |