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