Rev 767 | Rev 769 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 767 | Rev 768 | ||
---|---|---|---|
Line 73... | Line 73... | ||
73 | 73 | ||
74 | data = (void *)frame_alloc(FRAME_KA | flags, cache->order, &status, &zone); |
74 | data = (void *)frame_alloc(FRAME_KA | flags, cache->order, &status, &zone); |
75 | if (status != FRAME_OK) { |
75 | if (status != FRAME_OK) { |
76 | return NULL; |
76 | return NULL; |
77 | } |
77 | } |
78 | if (! cache->flags & SLAB_CACHE_SLINSIDE) { |
78 | if (! (cache->flags & SLAB_CACHE_SLINSIDE)) { |
79 | slab = malloc(sizeof(*slab)); // , flags); |
79 | slab = malloc(sizeof(*slab)); // , flags); |
80 | if (!slab) { |
80 | if (!slab) { |
81 | frame_free((__address)data); |
81 | frame_free((__address)data); |
82 | return NULL; |
82 | return NULL; |
83 | } |
83 | } |
Line 100... | Line 100... | ||
100 | 100 | ||
101 | for (i=0; i<cache->objects;i++) |
101 | for (i=0; i<cache->objects;i++) |
102 | *((int *) (slab->start + i*cache->size)) = i+1; |
102 | *((int *) (slab->start + i*cache->size)) = i+1; |
103 | 103 | ||
104 | atomic_inc(&cache->allocated_slabs); |
104 | atomic_inc(&cache->allocated_slabs); |
105 | - | ||
106 | return slab; |
105 | return slab; |
107 | } |
106 | } |
108 | 107 | ||
109 | /** |
108 | /** |
110 | * Deallocate space associated with SLAB |
109 | * Deallocate space associated with SLAB |
Line 112... | Line 111... | ||
112 | * @return number of freed frames |
111 | * @return number of freed frames |
113 | */ |
112 | */ |
114 | static count_t slab_space_free(slab_cache_t *cache, slab_t *slab) |
113 | static count_t slab_space_free(slab_cache_t *cache, slab_t *slab) |
115 | { |
114 | { |
116 | frame_free((__address)slab->start); |
115 | frame_free((__address)slab->start); |
117 | if (! cache->flags & SLAB_CACHE_SLINSIDE) |
116 | if (! (cache->flags & SLAB_CACHE_SLINSIDE)) |
118 | free(slab); |
117 | free(slab); |
119 | 118 | ||
120 | atomic_dec(&cache->allocated_slabs); |
119 | atomic_dec(&cache->allocated_slabs); |
121 | 120 | ||
122 | return 1 << cache->order; |
121 | return 1 << cache->order; |
Line 275... | Line 274... | ||
275 | spinlock_unlock(&cache->lock); |
274 | spinlock_unlock(&cache->lock); |
276 | goto out; |
275 | goto out; |
277 | } |
276 | } |
278 | /* Free current magazine and take one from list */ |
277 | /* Free current magazine and take one from list */ |
279 | slab_free(&mag_cache, mag); |
278 | slab_free(&mag_cache, mag); |
- | 279 | ||
280 | mag = list_get_instance(cache->magazines.next, |
280 | mag = list_get_instance(cache->magazines.next, |
281 | slab_magazine_t, |
281 | slab_magazine_t, |
282 | link); |
282 | link); |
283 | list_remove(&mag->link); |
283 | list_remove(&mag->link); |
284 | 284 | ||
Line 294... | Line 294... | ||
294 | spinlock_unlock(&cache->mag_cache[CPU->id].lock); |
294 | spinlock_unlock(&cache->mag_cache[CPU->id].lock); |
295 | return NULL; |
295 | return NULL; |
296 | } |
296 | } |
297 | 297 | ||
298 | /** |
298 | /** |
- | 299 | * Assure that the current magazine is empty, return pointer to it, or NULL if |
|
299 | * Put object into CPU-cache magazine |
300 | * no empty magazine available and cannot be allocated |
300 | * |
301 | * |
301 | * We have 2 magazines bound to processor. |
302 | * We have 2 magazines bound to processor. |
302 | * First try the current. |
303 | * First try the current. |
303 | * If full, try the last. |
304 | * If full, try the last. |
304 | * If full, put to magazines list. |
305 | * If full, put to magazines list. |
305 | * allocate new, exchange last & current |
306 | * allocate new, exchange last & current |
306 | * |
307 | * |
- | 308 | */ |
|
- | 309 | static slab_magazine_t * make_empty_current_mag(slab_cache_t *cache) |
|
- | 310 | { |
|
- | 311 | slab_magazine_t *cmag,*lastmag,*newmag; |
|
- | 312 | ||
- | 313 | cmag = cache->mag_cache[CPU->id].current; |
|
- | 314 | lastmag = cache->mag_cache[CPU->id].last; |
|
- | 315 | ||
- | 316 | if (cmag) { |
|
- | 317 | if (cmag->busy < cmag->size) |
|
- | 318 | return cmag; |
|
- | 319 | if (lastmag && lastmag->busy < lastmag->size) { |
|
- | 320 | cache->mag_cache[CPU->id].last = cmag; |
|
- | 321 | cache->mag_cache[CPU->id].current = lastmag; |
|
- | 322 | return lastmag; |
|
- | 323 | } |
|
- | 324 | } |
|
- | 325 | /* current | last are full | nonexistent, allocate new */ |
|
- | 326 | /* We do not want to sleep just because of caching */ |
|
- | 327 | /* Especially we do not want reclaiming to start, as |
|
- | 328 | * this would deadlock */ |
|
- | 329 | newmag = slab_alloc(&mag_cache, FRAME_ATOMIC | FRAME_NO_RECLAIM); |
|
- | 330 | if (!newmag) |
|
- | 331 | return NULL; |
|
- | 332 | newmag->size = SLAB_MAG_SIZE; |
|
- | 333 | newmag->busy = 0; |
|
- | 334 | ||
- | 335 | /* Flush last to magazine list */ |
|
- | 336 | if (lastmag) |
|
- | 337 | list_prepend(&lastmag->link, &cache->magazines); |
|
- | 338 | /* Move current as last, save new as current */ |
|
- | 339 | cache->mag_cache[CPU->id].last = cmag; |
|
- | 340 | cache->mag_cache[CPU->id].current = newmag; |
|
- | 341 | ||
- | 342 | return newmag; |
|
- | 343 | } |
|
- | 344 | ||
- | 345 | /** |
|
- | 346 | * Put object into CPU-cache magazine |
|
- | 347 | * |
|
307 | * @return 0 - success, -1 - could not get memory |
348 | * @return 0 - success, -1 - could not get memory |
308 | */ |
349 | */ |
309 | static int magazine_obj_put(slab_cache_t *cache, void *obj) |
350 | static int magazine_obj_put(slab_cache_t *cache, void *obj) |
310 | { |
351 | { |
311 | slab_magazine_t *mag; |
352 | slab_magazine_t *mag; |
312 | 353 | ||
313 | spinlock_lock(&cache->mag_cache[CPU->id].lock); |
354 | spinlock_lock(&cache->mag_cache[CPU->id].lock); |
- | 355 | ||
- | 356 | mag = make_empty_current_mag(cache); |
|
- | 357 | if (!mag) |
|
- | 358 | goto errout; |
|
314 | 359 | ||
315 | mag = cache->mag_cache[CPU->id].current; |
- | |
316 | if (!mag) { |
- | |
317 | /* We do not want to sleep just because of caching */ |
- | |
318 | /* Especially we do not want reclaiming to start, as |
- | |
319 | * this would deadlock */ |
- | |
320 | mag = slab_alloc(&mag_cache, FRAME_ATOMIC | FRAME_NO_RECLAIM); |
- | |
321 | if (!mag) /* Allocation failed, give up on caching */ |
- | |
322 | goto errout; |
- | |
323 | - | ||
324 | cache->mag_cache[CPU->id].current = mag; |
- | |
325 | mag->size = SLAB_MAG_SIZE; |
- | |
326 | mag->busy = 0; |
- | |
327 | } else if (mag->busy == mag->size) { |
- | |
328 | /* If the last is full | empty, allocate new */ |
- | |
329 | mag = cache->mag_cache[CPU->id].last; |
- | |
330 | if (!mag || mag->size == mag->busy) { |
- | |
331 | if (mag) |
- | |
332 | list_prepend(&mag->link, &cache->magazines); |
- | |
333 | - | ||
334 | mag = slab_alloc(&mag_cache, FRAME_ATOMIC | FRAME_NO_RECLAIM); |
- | |
335 | if (!mag) |
- | |
336 | goto errout; |
- | |
337 | - | ||
338 | mag->size = SLAB_MAG_SIZE; |
- | |
339 | mag->busy = 0; |
- | |
340 | cache->mag_cache[CPU->id].last = mag; |
- | |
341 | } |
- | |
342 | /* Exchange the 2 */ |
- | |
343 | cache->mag_cache[CPU->id].last = cache->mag_cache[CPU->id].current; |
- | |
344 | cache->mag_cache[CPU->id].current = mag; |
- | |
345 | } |
- | |
346 | mag->objs[mag->busy++] = obj; |
360 | mag->objs[mag->busy++] = obj; |
347 | 361 | ||
348 | spinlock_unlock(&cache->mag_cache[CPU->id].lock); |
362 | spinlock_unlock(&cache->mag_cache[CPU->id].lock); |
349 | atomic_inc(&cache->cached_objs); |
363 | atomic_inc(&cache->cached_objs); |
350 | return 0; |
364 | return 0; |
Line 406... | Line 420... | ||
406 | 420 | ||
407 | list_initialize(&cache->full_slabs); |
421 | list_initialize(&cache->full_slabs); |
408 | list_initialize(&cache->partial_slabs); |
422 | list_initialize(&cache->partial_slabs); |
409 | list_initialize(&cache->magazines); |
423 | list_initialize(&cache->magazines); |
410 | spinlock_initialize(&cache->lock, "cachelock"); |
424 | spinlock_initialize(&cache->lock, "cachelock"); |
411 | if (! cache->flags & SLAB_CACHE_NOMAGAZINE) { |
425 | if (! (cache->flags & SLAB_CACHE_NOMAGAZINE)) { |
412 | for (i=0; i< config.cpu_count; i++) |
426 | for (i=0; i< config.cpu_count; i++) |
413 | spinlock_initialize(&cache->mag_cache[i].lock, |
427 | spinlock_initialize(&cache->mag_cache[i].lock, |
414 | "cpucachelock"); |
428 | "cpucachelock"); |
415 | } |
429 | } |
416 | 430 | ||
Line 455... | Line 469... | ||
455 | /** |
469 | /** |
456 | * Reclaim space occupied by objects that are already free |
470 | * Reclaim space occupied by objects that are already free |
457 | * |
471 | * |
458 | * @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing |
472 | * @param flags If contains SLAB_RECLAIM_ALL, do aggressive freeing |
459 | * @return Number of freed pages |
473 | * @return Number of freed pages |
460 | * |
- | |
461 | * TODO: Add light reclaim |
- | |
462 | */ |
474 | */ |
463 | static count_t _slab_reclaim(slab_cache_t *cache, int flags) |
475 | static count_t _slab_reclaim(slab_cache_t *cache, int flags) |
464 | { |
476 | { |
465 | int i; |
477 | int i; |
466 | slab_magazine_t *mag; |
478 | slab_magazine_t *mag; |
Line 491... | Line 503... | ||
491 | } |
503 | } |
492 | } |
504 | } |
493 | /* Destroy full magazines */ |
505 | /* Destroy full magazines */ |
494 | cur=cache->magazines.prev; |
506 | cur=cache->magazines.prev; |
495 | 507 | ||
496 | while (cur!=&cache->magazines) { |
508 | while (cur != &cache->magazines) { |
497 | mag = list_get_instance(cur, slab_magazine_t, link); |
509 | mag = list_get_instance(cur, slab_magazine_t, link); |
498 | 510 | ||
499 | cur = cur->prev; |
511 | cur = cur->prev; |
500 | list_remove(cur->next); |
- | |
501 | // list_remove(&mag->link); |
512 | list_remove(&mag->link); |
502 | frames += magazine_destroy(cache,mag); |
513 | frames += magazine_destroy(cache,mag); |
503 | /* If we do not do full reclaim, break |
514 | /* If we do not do full reclaim, break |
504 | * as soon as something is freed */ |
515 | * as soon as something is freed */ |
505 | if (!(flags & SLAB_RECLAIM_ALL) && frames) |
516 | if (!(flags & SLAB_RECLAIM_ALL) && frames) |
506 | break; |
517 | break; |
Line 542... | Line 553... | ||
542 | void *result = NULL; |
553 | void *result = NULL; |
543 | 554 | ||
544 | /* Disable interrupts to avoid deadlocks with interrupt handlers */ |
555 | /* Disable interrupts to avoid deadlocks with interrupt handlers */ |
545 | ipl = interrupts_disable(); |
556 | ipl = interrupts_disable(); |
546 | 557 | ||
547 | if (!cache->flags & SLAB_CACHE_NOMAGAZINE) |
558 | if (!(cache->flags & SLAB_CACHE_NOMAGAZINE)) |
548 | result = magazine_obj_get(cache); |
559 | result = magazine_obj_get(cache); |
549 | 560 | ||
550 | if (!result) { |
561 | if (!result) { |
551 | spinlock_lock(&cache->lock); |
562 | spinlock_lock(&cache->lock); |
552 | result = slab_obj_create(cache, flags); |
563 | result = slab_obj_create(cache, flags); |