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>