Skip site navigation (1)Skip section navigation (2)
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>