xref: /netbsd-src/sys/dev/raidframe/rf_alloclist.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /*	$NetBSD: rf_alloclist.c,v 1.1 1998/11/13 04:20:26 oster Exp $	*/
2 /*
3  * Copyright (c) 1995 Carnegie-Mellon University.
4  * All rights reserved.
5  *
6  * Author: Mark Holland
7  *
8  * Permission to use, copy, modify and distribute this software and
9  * its documentation is hereby granted, provided that both the copyright
10  * notice and this permission notice appear in all copies of the
11  * software, derivative works or modified versions, and any portions
12  * thereof, and that both notices appear in supporting documentation.
13  *
14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
16  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17  *
18  * Carnegie Mellon requests users of this software to return to
19  *
20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
21  *  School of Computer Science
22  *  Carnegie Mellon University
23  *  Pittsburgh PA 15213-3890
24  *
25  * any improvements or extensions that they make and grant Carnegie the
26  * rights to redistribute these changes.
27  */
28 
29 /*
30  * Log: rf_alloclist.c,v
31  * Revision 1.28  1996/07/27 23:36:08  jimz
32  * Solaris port of simulator
33  *
34  * Revision 1.27  1996/06/12  03:29:54  jimz
35  * don't barf just because we can't create an alloclist
36  *
37  * Revision 1.26  1996/06/10  11:55:47  jimz
38  * Straightened out some per-array/not-per-array distinctions, fixed
39  * a couple bugs related to confusion. Added shutdown lists. Removed
40  * layout shutdown function (now subsumed by shutdown lists).
41  *
42  * Revision 1.25  1996/06/09  02:36:46  jimz
43  * lots of little crufty cleanup- fixup whitespace
44  * issues, comment #ifdefs, improve typing in some
45  * places (esp size-related)
46  *
47  * Revision 1.24  1996/06/05  18:06:02  jimz
48  * Major code cleanup. The Great Renaming is now done.
49  * Better modularity. Better typing. Fixed a bunch of
50  * synchronization bugs. Made a lot of global stuff
51  * per-desc or per-array. Removed dead code.
52  *
53  * Revision 1.23  1996/05/30  23:22:16  jimz
54  * bugfixes of serialization, timing problems
55  * more cleanup
56  *
57  * Revision 1.22  1996/05/27  18:56:37  jimz
58  * more code cleanup
59  * better typing
60  * compiles in all 3 environments
61  *
62  * Revision 1.21  1996/05/23  21:46:35  jimz
63  * checkpoint in code cleanup (release prep)
64  * lots of types, function names have been fixed
65  *
66  * Revision 1.20  1996/05/20  16:15:59  jimz
67  * switch to rf_{mutex,cond}_{init,destroy}
68  *
69  * Revision 1.19  1996/05/18  19:51:34  jimz
70  * major code cleanup- fix syntax, make some types consistent,
71  * add prototypes, clean out dead code, et cetera
72  *
73  * Revision 1.18  1996/05/16  22:27:45  jimz
74  * get rid of surreal_MakeAllocList (what was that, anyway?)
75  *
76  * Revision 1.17  1995/12/12  18:10:06  jimz
77  * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT
78  * fix 80-column brain damage in comments
79  *
80  * Revision 1.16  1995/11/30  16:27:07  wvcii
81  * added copyright info
82  *
83  * Revision 1.15  1995/10/05  20:37:56  jimz
84  * assert non-NULLness of pointer to FREE in FreeAllocList()
85  *
86  * Revision 1.14  1995/06/11  20:11:24  holland
87  * changed fl_hist,miss_count from long to int to get around weird kernel bug
88  *
89  * Revision 1.13  1995/05/01  13:28:00  holland
90  * parity range locks, locking disk requests, recon+parityscan in kernel, etc.
91  *
92  * Revision 1.12  1995/04/21  19:13:04  holland
93  * minor change to avoid a syntax error on DO_FREE
94  *
95  * Revision 1.11  1995/02/17  19:39:56  holland
96  * added size param to all calls to Free().
97  * this is ignored at user level, but necessary in the kernel.
98  *
99  * Revision 1.10  1995/02/10  18:08:07  holland
100  * added DO_FREE macro to fix what I broke during kernelization
101  *
102  * Revision 1.9  1995/02/10  17:34:10  holland
103  * kernelization changes
104  *
105  * Revision 1.8  1995/02/03  22:31:36  holland
106  * many changes related to kernelization
107  *
108  * Revision 1.7  1995/02/01  15:13:05  holland
109  * moved #include of general.h out of raid.h and into each file
110  *
111  * Revision 1.6  1995/01/11  19:27:02  holland
112  * many changes related to performance tuning
113  *
114  * Revision 1.5  1994/11/29  20:53:10  danner
115  * Marks mods
116  *
117  * Revision 1.3  1994/11/19  21:01:07  danner
118  * First merge with mark
119  *
120  * Revision 1.1.1.1  1994/11/19  20:23:38  danner
121  * First PQ checkin
122  *
123  * Revision 1.2  1994/11/16  15:45:35  danner
124  * fixed free bug in FreeAllocList
125  *
126  *
127  */
128 
129 /****************************************************************************
130  *
131  * Alloclist.c -- code to manipulate allocation lists
132  *
133  * an allocation list is just a list of AllocListElem structures.  Each
134  * such structure contains a fixed-size array of pointers.  Calling
135  * FreeAList() causes each pointer to be freed.
136  *
137  ***************************************************************************/
138 
139 #include "rf_types.h"
140 #include "rf_threadstuff.h"
141 #include "rf_alloclist.h"
142 #include "rf_debugMem.h"
143 #include "rf_etimer.h"
144 #include "rf_general.h"
145 #include "rf_shutdown.h"
146 #include "rf_sys.h"
147 
148 RF_DECLARE_STATIC_MUTEX(alist_mutex)
149 static unsigned int fl_hit_count, fl_miss_count;
150 
151 static RF_AllocListElem_t *al_free_list=NULL;
152 static int al_free_list_count;
153 
154 #define RF_AL_FREELIST_MAX 256
155 
156 #ifndef KERNEL
157 #define DO_FREE(_p,_sz) free((_p))
158 #else /* !KERNEL */
159 #define DO_FREE(_p,_sz) RF_Free((_p),(_sz))
160 #endif /* !KERNEL */
161 
162 static void rf_ShutdownAllocList(void *);
163 
164 static void rf_ShutdownAllocList(ignored)
165   void  *ignored;
166 {
167   RF_AllocListElem_t *p, *pt;
168 
169   for (p = al_free_list; p; ) {
170     pt = p;
171     p = p->next;
172     DO_FREE(pt, sizeof(*pt));
173   }
174   rf_mutex_destroy(&alist_mutex);
175   /*
176   printf("Alloclist: Free list hit count %lu (%lu %%) miss count %lu (%lu %%)\n",
177 	 fl_hit_count, (100*fl_hit_count)/(fl_hit_count+fl_miss_count),
178 	 fl_miss_count, (100*fl_miss_count)/(fl_hit_count+fl_miss_count));
179   */
180 }
181 
182 int rf_ConfigureAllocList(listp)
183   RF_ShutdownList_t  **listp;
184 {
185   int rc;
186 
187   rc = rf_mutex_init(&alist_mutex);
188   if (rc) {
189     RF_ERRORMSG3("Unable to init mutex file %s line %d rc=%d\n", __FILE__,
190       __LINE__, rc);
191     return(rc);
192   }
193   al_free_list = NULL;
194   fl_hit_count = fl_miss_count = al_free_list_count = 0;
195   rc = rf_ShutdownCreate(listp, rf_ShutdownAllocList, NULL);
196   if (rc) {
197     RF_ERRORMSG3("Unable to add to shutdown list file %s line %d rc=%d\n",
198       __FILE__, __LINE__, rc);
199     rf_mutex_destroy(&alist_mutex);
200     return(rc);
201   }
202   return(0);
203 }
204 
205 
206 /* we expect the lists to have at most one or two elements, so we're willing
207  * to search for the end.  If you ever observe the lists growing longer,
208  * increase POINTERS_PER_ALLOC_LIST_ELEMENT.
209  */
210 void rf_real_AddToAllocList(l, p, size, lockflag)
211   RF_AllocListElem_t  *l;
212   void                *p;
213   int                  size;
214   int                  lockflag;
215 {
216   RF_AllocListElem_t *newelem;
217 
218   for ( ; l->next; l=l->next)
219 	  RF_ASSERT(l->numPointers == RF_POINTERS_PER_ALLOC_LIST_ELEMENT);  /* find end of list */
220 
221   RF_ASSERT(l->numPointers >= 0 && l->numPointers <= RF_POINTERS_PER_ALLOC_LIST_ELEMENT);
222   if (l->numPointers == RF_POINTERS_PER_ALLOC_LIST_ELEMENT) {
223     newelem = rf_real_MakeAllocList(lockflag);
224     l->next = newelem;
225     l = newelem;
226   }
227   l->pointers[ l->numPointers ] = p;
228   l->sizes   [ l->numPointers ] = size;
229   l->numPointers++;
230 
231 }
232 
233 
234 /* we use the debug_mem_mutex here because we need to lock it anyway to call free.
235  * this is probably a bug somewhere else in the code, but when I call malloc/free
236  * outside of any lock I have endless trouble with malloc appearing to return the
237  * same pointer twice.  Since we have to lock it anyway, we might as well use it
238  * as the lock around the al_free_list.  Note that we can't call Free with the
239  * debug_mem_mutex locked.
240  */
241 void rf_FreeAllocList(l)
242   RF_AllocListElem_t  *l;
243 {
244   int i;
245   RF_AllocListElem_t *temp, *p;
246 
247   for (p=l; p; p=p->next) {
248     RF_ASSERT(p->numPointers >= 0 && p->numPointers <= RF_POINTERS_PER_ALLOC_LIST_ELEMENT);
249     for (i=0; i<p->numPointers; i++) {
250       RF_ASSERT(p->pointers[i]);
251       RF_Free(p->pointers[i], p->sizes[i]);
252     }
253   }
254 #ifndef KERNEL
255   RF_LOCK_MUTEX(rf_debug_mem_mutex);
256 #endif /* !KERNEL */
257   while (l) {
258     temp = l;
259     l = l->next;
260     if (al_free_list_count > RF_AL_FREELIST_MAX) {DO_FREE(temp, sizeof(*temp));}
261     else {temp->next = al_free_list; al_free_list = temp; al_free_list_count++;}
262   }
263 #ifndef KERNEL
264   RF_UNLOCK_MUTEX(rf_debug_mem_mutex);
265 #endif /* !KERNEL */
266 }
267 
268 RF_AllocListElem_t *rf_real_MakeAllocList(lockflag)
269   int  lockflag;
270 {
271   RF_AllocListElem_t *p;
272 
273 #ifndef KERNEL
274   if (lockflag) {  RF_LOCK_MUTEX(rf_debug_mem_mutex); }
275 #endif /* !KERNEL */
276   if (al_free_list) {fl_hit_count++; p = al_free_list; al_free_list = p->next; al_free_list_count--;}
277   else {
278     fl_miss_count++;
279 #ifndef KERNEL
280     p = (RF_AllocListElem_t *) malloc(sizeof(RF_AllocListElem_t));  /* can't use Malloc at user level b/c we already locked the mutex */
281 #else /* !KERNEL */
282     RF_Malloc(p, sizeof(RF_AllocListElem_t), (RF_AllocListElem_t *));  /* no allocation locking in kernel, so this is fine */
283 #endif /* !KERNEL */
284   }
285 #ifndef KERNEL
286   if (lockflag) {  RF_UNLOCK_MUTEX(rf_debug_mem_mutex); }
287 #endif /* !KERNEL */
288   if (p == NULL) {
289     return(NULL);
290   }
291   bzero((char *)p, sizeof(RF_AllocListElem_t));
292   return(p);
293 }
294