summaryrefslogtreecommitdiffstats
path: root/src/core/refcnt.c
diff options
context:
space:
mode:
authorMichael Brown2010-11-05 23:24:46 +0100
committerMichael Brown2010-11-08 04:35:35 +0100
commit6e41f2cf18217dd5f4086852b61bb6f0146c1e0b (patch)
tree6d5e696d2e626d5187e69428d9d987e8cae9d5fb /src/core/refcnt.c
parent[malloc] Use list_for_each_entry_safe() when we may delete a list entry (diff)
downloadipxe-6e41f2cf18217dd5f4086852b61bb6f0146c1e0b.tar.gz
ipxe-6e41f2cf18217dd5f4086852b61bb6f0146c1e0b.tar.xz
ipxe-6e41f2cf18217dd5f4086852b61bb6f0146c1e0b.zip
[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.c26
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 );