Date: Sun, 1 Feb 1998 05:09:03 +0000 (GMT) From: Terry Lambert <tlambert@primenet.com> To: current@FreeBSD.ORG Subject: General reference counting for structures Message-ID: <199802010509.WAA09147@usr02.primenet.com>
next in thread | raw e-mail | index | archive | help
As things become more and more dynamic, it's as important to know
when *not* to unload something as when to load it. In addition, it's
likely to be useful to have a general method you can use to schedule
the unload of something that is currently in use.
Here are some patches to kernel.h to provide this service:
---------------------------------------------------------------------------
Index: sys/kernel.h
===================================================================
RCS file: /b/cvstree/ncvs/src/sys/sys/kernel.h,v
retrieving revision 1.29
diff -c -r1.29 kernel.h
*** 1.29 1997/04/26 11:46:20
--- kernel.h 1998/02/01 04:44:44
***************
*** 119,124 ****
--- 119,156 ----
/*
+ * Generalized reference counting for use by structures
+ *
+ * Assumes "REFCOUNT" declared in structure; will declare
+ * unqualified member stricture "reference". This makes the
+ * counting independent of the location of the declaration.
+ *
+ * XXX Macros are used to allow for fine grain locking (later)
+ */
+ /* structure*/
+ typedef struct refcnt {
+ int r_count; /* number of references*/
+ void (*r_doref) __P(( int)); /* call when changed*/
+ } REFERENCE;
+ /* instance*/
+ #define REFCOUNT REFERENCE reference;
+ /* static initializer for users of instances*/
+ #define REFINITIALZER(func) { 0, func }
+ /* internal macros*/
+ DOREF(x,y) \
+ { \
+ (x)->reference.r_count += (y); \
+ if( (x)->reference.r_doref) \
+ (*(x)->reference.r_doref)( \
+ (x)->reference.r_count \
+ ); \
+ }
+ /* external macros*/
+ ADDREF(x) DOREF(x,1) /* add a reference*/
+ UNREF(x) DOREF(x,-1) /* remove a reference*/
+
+
+ /*
* Enumerated types for known system startup interfaces.
*
* Startup occurs in ascending numeric order; the list entries are
---------------------------------------------------------------------------
USAGE:
When declaring a structure:
struct mystruct {
...;
...;
REFCOUNT;
...;
...;
};
When declaring a static instance of the structure:
struct mystruct foo = {
...,
...,
REFINITIALZER(NULL),
...,
...
};
When referncing an instance of the structure:
ADDREF(&foo);
When finished referencing an instance of the structure:
UNREF(&foo);
EXAMPLE: SLIP line discipline:
Structure:
struct linesw {
...
REFCOUNT;
};
Declaration:
static struct linesw slipdisc = {
slopen, slclose, l_noread, l_nowrite,
sltioctl, slinput, slstart, ttymodem,
REFINITIALZER(slref)
};
On use:
/* when set*/
ADDREF( slipdisc);
/* when cleared*/
UNREF( slipdisc);
/* called when reference count has changed*/
void
slref( refcount)
int refcount;
{
static int firstref = 1;
if( firstref) {
/* reference count 0 -> 1*/
firstref = 0;
/* mark as "not OK to unload"*/
...
}
if( refcount)
return;
/* reference count 1 -> 0; mark as "OK to unload"*/
firstref = 1; /* in case rereferenced...*/
...
/* if marked "pending unload", queue unload now*/
...
return;
}
Works for FS, system calls, etc., as well.
Terry Lambert
terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199802010509.WAA09147>
