1 #include "common.h" 2 3 #include <ddekit/lock.h> 4 #include <ddekit/memory.h> 5 #include <ddekit/panic.h> 6 #include <ddekit/pgtab.h> 7 #include <ddekit/inline.h> 8 #include <ddekit/types.h> 9 10 #ifdef DDEKIT_DEBUG_MEM 11 #undef DDEBUG 12 #define DDEBUG DDEKIT_DEBUG_MEM 13 #endif 14 #include "debug.h" 15 #include "util.h" 16 17 #define SLAB_SIZE (4096*4) 18 19 struct ddekit_slab; 20 21 struct ddekit_slab_slab { 22 struct ddekit_slab * cache; 23 unsigned long free; 24 void *objects; 25 void *mem; 26 struct ddekit_slab_slab *next; 27 struct ddekit_slab_slab *prev; 28 }; 29 30 struct ddekit_slab { 31 ddekit_lock_t lock; 32 void * data; /* user pointer */ 33 int contiguous; /* is it coniguous mem*/ 34 unsigned size; /* the size of he objects */ 35 unsigned number; /* the number of objects stored per slab */ 36 struct ddekit_slab_slab full; 37 struct ddekit_slab_slab partial; 38 struct ddekit_slab_slab empty; 39 }; 40 41 static void ddekit_slab_lock(struct ddekit_slab * sc); 42 static void ddekit_slab_unlock(struct ddekit_slab * sc); 43 static struct ddekit_slab_slab * ddekit_slab_find_slab(struct 44 ddekit_slab * sc, void * obj); 45 static void ddekit_slab_slab_insert(struct ddekit_slab_slab *list, 46 struct ddekit_slab_slab *s); 47 static void ddekit_slab_slab_remove(struct ddekit_slab_slab *s); 48 static void ddekit_slab_grow(struct ddekit_slab * sc); 49 static void *ddekit_slab_getobj(struct ddekit_slab_slab *s); 50 static void ddekit_slab_free_slab(struct ddekit_slab_slab * sl, int 51 cont); 52 53 /****************************************************************************** 54 * ddekit_simple_malloc * 55 *****************************************************************************/ 56 void *ddekit_simple_malloc(unsigned size) 57 { 58 /* Simple memory allocation... malloc and free should be ok... */ 59 void * r = malloc(size); 60 if (!r) { 61 ddekit_panic("out of mem?"); 62 } 63 DDEBUG_MSG_VERBOSE("%p", r); 64 return r; 65 } 66 67 /****************************************************************************** 68 * ddekit_simple_free * 69 *****************************************************************************/ 70 void ddekit_simple_free(void *p) 71 { 72 DDEBUG_MSG_VERBOSE("%p", p); 73 free(p); 74 } 75 76 /****************************************************************************** 77 * ddekit_large_malloc * 78 *****************************************************************************/ 79 void *ddekit_large_malloc(int size) 80 { 81 ddekit_addr_t phys; 82 /* allocate a piece of coniguous memory */ 83 void * r = alloc_contig(size, AC_ALIGN4K, &phys); 84 if (!r) { 85 ddekit_panic("out of mem?"); 86 } 87 ddekit_pgtab_set_region_with_size(r, phys, size, PTE_TYPE_LARGE); 88 DDEBUG_MSG_VERBOSE("%p, phys: %p, size: %p.",r, phys, size); 89 DDEBUG_MSG_VERBOSE("%p", r); 90 return r; 91 } 92 93 /****************************************************************************** 94 * ddekit_large_free * 95 *****************************************************************************/ 96 void ddekit_large_free(void *p) 97 { 98 unsigned len; 99 DDEBUG_MSG_VERBOSE("get size of region %x", p); 100 len= ddekit_pgtab_get_size(p); 101 DDEBUG_MSG_VERBOSE("freeing %x, len %d...", p , len); 102 ddekit_pgtab_clear_region(p, 0); /* type is not used here... */ 103 DDEBUG_MSG_VERBOSE("cleared region", p , len); 104 free_contig(p, len); 105 DDEBUG_MSG_VERBOSE("freed mem", p , len); 106 DDEBUG_MSG_VERBOSE("%p", p); 107 } 108 109 /****************************************************************************** 110 * ddekit_contig_malloc * 111 *****************************************************************************/ 112 void *ddekit_contig_malloc(unsigned long size, unsigned long low, 113 unsigned long high, unsigned long aligment, 114 unsigned long boundary) 115 { 116 WARN_UNIMPL; 117 return 0; 118 } 119 120 /****************************************************************************** 121 * ddekit_slab_lock * 122 *****************************************************************************/ 123 static DDEKIT_INLINE void ddekit_slab_lock(struct ddekit_slab * sc) { 124 ddekit_lock_lock(&sc->lock); 125 } 126 127 /****************************************************************************** 128 * ddekit_slab_unlock * 129 *****************************************************************************/ 130 static DDEKIT_INLINE void ddekit_slab_unlock(struct ddekit_slab * sc) { 131 ddekit_lock_unlock(&sc->lock); 132 } 133 134 /****************************************************************************** 135 * ddekit_slab_find_slab * 136 *****************************************************************************/ 137 static struct ddekit_slab_slab * 138 ddekit_slab_find_slab(struct ddekit_slab * sc, void * obj) 139 { 140 141 struct ddekit_slab_slab *s; 142 143 for( s = sc->full.next; s!=&sc->full; s = s->next ) 144 { 145 if (s->mem <= obj && obj < s->mem+(SLAB_SIZE)) 146 { 147 return s; 148 } 149 } 150 151 for( s = sc->partial.next; s!=&sc->partial; s = s->next ) 152 { 153 if (s->mem <= obj && obj < s->mem+(SLAB_SIZE)) 154 { 155 return s; 156 } 157 } 158 159 return 0; 160 } 161 162 /****************************************************************************** 163 * ddekit_slab_slab_insert * 164 *****************************************************************************/ 165 static void ddekit_slab_slab_insert(struct ddekit_slab_slab *list, 166 struct ddekit_slab_slab *s) 167 { 168 s->prev = list; 169 s->next = list->next; 170 list->next->prev = s; 171 list->next = s; 172 } 173 174 /****************************************************************************** 175 * ddekit_slab_slab_remove * 176 *****************************************************************************/ 177 static void ddekit_slab_slab_remove(struct ddekit_slab_slab *s) 178 { 179 s->next->prev = s->prev; 180 s->prev->next = s->next; 181 s->next = s->prev = 0; 182 } 183 184 185 /****************************************************************************** 186 * ddekit_slab_grow * 187 *****************************************************************************/ 188 static void ddekit_slab_grow(struct ddekit_slab *sc) 189 { 190 /* 191 * NOTE: 192 * As it doesn't seem to make problems ddekit_slabs are disregarding 193 * alignment. However this should be revisited, maybe this leads to 194 * performance degregation somewhere. 195 * Further the ddekit_slab doesn't have to be real slab, as the entries are 196 * initialized in the personalized DDEs. (slab is simple the wrong name.) 197 */ 198 int i; 199 char *p; 200 void **p1; 201 struct ddekit_slab_slab *s; 202 203 /* allocate slab control structure */ 204 205 s = (struct ddekit_slab_slab *) 206 ddekit_simple_malloc(sizeof(struct ddekit_slab_slab)); 207 208 s->cache = sc; 209 210 if(sc->contiguous) 211 s->mem = ddekit_large_malloc(SLAB_SIZE); 212 else 213 s->mem = ddekit_simple_malloc(SLAB_SIZE); 214 215 /* setup the object list */ 216 217 s->free = sc->number; 218 219 /* put obj into list */ 220 p1 = s->mem; 221 *p1 = s->mem; 222 s->objects = p1; 223 224 DDEBUG_MSG_VERBOSE("obj size: %d, memory at: %p , first obj: %p, %p ", 225 sc->size, s->mem, s->objects); 226 227 for (i = 0; i < s->free; i++) 228 { 229 p = *p1; 230 p1 = (void **) (p + sc->size); 231 232 if ( i != s->free-1 ) 233 { 234 *p1 = p1+1; 235 DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1); 236 } 237 else 238 { 239 *p1 = 0; 240 DDEBUG_MSG_VERBOSE("%p, %p -> %p", p, p1, *p1); 241 } 242 } 243 244 /* add new slab to free list */ 245 ddekit_slab_slab_insert(&sc->empty, s); 246 } 247 248 249 /****************************************************************************** 250 * ddekit_slab_getobj * 251 *****************************************************************************/ 252 static void *ddekit_slab_getobj(struct ddekit_slab_slab *s) 253 { 254 struct ddekit_slab *sc; 255 void *ret = 0; 256 257 sc = s->cache; 258 ret = s->objects; 259 260 /* get pointer to next object */ 261 262 s->objects = *(void **)((char *) ret + sc->size); 263 s->free--; 264 265 DDEBUG_MSG_VERBOSE("old: %p new: %p", ret, s->objects); 266 267 /* if no more objects move to full */ 268 269 if (!s->free) 270 { 271 ddekit_slab_slab_remove(s); 272 ddekit_slab_slab_insert(&sc->full,s); 273 } 274 275 if (s->free == sc->number-1) 276 { 277 ddekit_slab_slab_remove(s); 278 ddekit_slab_slab_insert(&sc->partial,s); 279 } 280 281 return ret; 282 } 283 284 /****************************************************************************** 285 * ddekit_slab_alloc * 286 *****************************************************************************/ 287 void *ddekit_slab_alloc(struct ddekit_slab * sc) 288 { 289 struct ddekit_slab_slab *s=0; 290 291 ddekit_slab_lock(sc); 292 293 DDEBUG_MSG_VERBOSE("from slab %p", sc); 294 295 /* first try from partial */ 296 if (sc->partial.next != &sc->partial) { 297 DDEBUG_MSG_VERBOSE("from slab %p partial (next=%p)", sc,sc->partial.next); 298 s = sc->partial.next; 299 } 300 301 /* must grow? */ 302 if (!s && (sc->empty.next == &sc->empty )){ 303 DDEBUG_MSG_VERBOSE("slab %p has to grow", sc); 304 ddekit_slab_grow(sc); 305 } 306 307 /* take from free? */ 308 if (!s) { 309 DDEBUG_MSG_VERBOSE("from slab %p empty", sc); 310 s = sc->empty.next; 311 } 312 313 ddekit_slab_unlock(sc); 314 315 return ddekit_slab_getobj(s); 316 } 317 318 /****************************************************************************** 319 * ddekit_slab_free * 320 *****************************************************************************/ 321 void ddekit_slab_free(struct ddekit_slab *sc, void* obj) 322 { 323 void **p; 324 325 struct ddekit_slab_slab *s = 0; 326 327 ddekit_slab_lock(sc); 328 /* first find slab the obj came from */ 329 330 s = ddekit_slab_find_slab(sc, obj); 331 332 p = (void **)((char *) obj + sc->size); 333 334 *p= s->objects; 335 s->objects=obj; 336 337 DDEBUG_MSG_VERBOSE("old: %p, new: %p",*p,s->objects ); 338 339 s->free++; 340 341 if (s->free == sc->number) { 342 ddekit_slab_slab_remove(s); 343 ddekit_slab_slab_insert(&sc->empty, s); 344 } 345 346 if (s->free == 1) { 347 ddekit_slab_slab_remove(s); 348 ddekit_slab_slab_insert(&sc->partial, s); 349 } 350 351 ddekit_slab_unlock(sc); 352 } 353 354 /****************************************************************************** 355 * ddekit_slab_set_data * 356 *****************************************************************************/ 357 void ddekit_slab_set_data(struct ddekit_slab * sc, void *data) 358 { 359 ddekit_slab_lock(sc); 360 sc->data = data; 361 ddekit_slab_unlock(sc); 362 } 363 364 /****************************************************************************** 365 * ddekit_slab_get_data * 366 *****************************************************************************/ 367 void *ddekit_slab_get_data (struct ddekit_slab *sc) 368 { 369 void *ret; 370 ddekit_slab_lock(sc); 371 ret=sc->data; 372 ddekit_slab_unlock(sc); 373 return ret; 374 } 375 376 377 /****************************************************************************** 378 * ddekit_slab_init * 379 *****************************************************************************/ 380 struct ddekit_slab * ddekit_slab_init(unsigned size, int contiguous) 381 { 382 383 struct ddekit_slab * sc = 0; 384 385 sc = (struct ddekit_slab *) 386 ddekit_simple_malloc(sizeof(struct ddekit_slab)); 387 388 sc->data = 0; 389 sc->contiguous = contiguous; 390 sc->size = size; 391 sc->number = SLAB_SIZE/(size+sizeof(void*)); 392 393 if (sc->number == 0) { 394 ddekit_panic("objects too big!"); 395 } 396 397 sc->empty.next = sc->empty.prev = &sc->empty; 398 sc->partial.next = sc->partial.prev = &sc->partial; 399 sc->full.next = sc->full.prev = &sc->full; 400 401 ddekit_lock_init(&sc->lock); 402 403 DDEBUG_MSG_VERBOSE("initialzed slab cache %p: size %x, number %d ", 404 sc, sc->size, sc->number); 405 406 DDEBUG_MSG_VERBOSE("partial %p next %p", &sc->partial, sc->partial.next); 407 return sc ; 408 409 } 410 411 412 /****************************************************************************** 413 * ddekit_slab_free_slab * 414 *****************************************************************************/ 415 static void ddekit_slab_free_slab(struct ddekit_slab_slab * sl, int cont) 416 { 417 418 struct ddekit_slab_slab *s,*t; 419 420 if (!sl) { 421 ddekit_panic("no slab to free!"); 422 } 423 424 for ( s = sl->next; s != sl; ) 425 { 426 DDEBUG_MSG_VERBOSE("cont: %d, %p, s->mem", cont, s->mem); 427 if(cont) 428 { 429 ddekit_large_free(s->mem); 430 } 431 else 432 { 433 ddekit_simple_free(s->mem); 434 } 435 t = s; 436 s = s->next; 437 ddekit_simple_free(t); 438 } 439 440 } 441 442 /****************************************************************************** 443 * ddekit_slab_destroy * 444 *****************************************************************************/ 445 void ddekit_slab_destroy(struct ddekit_slab *sc) 446 { 447 DDEBUG_MSG_VERBOSE("%p full", sc); 448 ddekit_slab_free_slab(&sc->full,sc->contiguous); 449 450 DDEBUG_MSG_VERBOSE("%p empty", sc); 451 ddekit_slab_free_slab(&sc->empty,sc->contiguous); 452 453 DDEBUG_MSG_VERBOSE("%p partial", sc); 454 ddekit_slab_free_slab(&sc->partial,sc->contiguous); 455 456 ddekit_lock_deinit(&sc->lock); 457 458 ddekit_simple_free(sc); 459 } 460