void * obuf_reserve_slow(struct obuf *buf, size_t size) { struct iovec *iov = &buf->iov[buf->pos]; size_t capacity = buf->capacity[buf->pos]; if (iov->iov_len > 0) { /* Move to the next buffer. */ if (buf->pos + 1 >= SMALL_OBUF_IOV_MAX) return NULL; buf->pos++; iov = &buf->iov[buf->pos]; capacity = buf->capacity[buf->pos]; } assert(iov->iov_len == 0); /* Make sure the next buffer can store size. */ if (size > capacity) { if (capacity > 0) { /* Simply realloc. */ while (capacity < size) capacity = capacity * 2; struct slab *slab = slab_get(buf->slabc, capacity); if (slab == NULL) return NULL; struct slab *old = slab_from_data(buf->iov[buf->pos].iov_base); slab_put(buf->slabc, old); buf->iov[buf->pos].iov_base = slab_data(slab); buf->capacity[buf->pos] = slab_capacity(slab); } else if (obuf_alloc_pos(buf, size) == NULL) { return NULL; } } assert(buf->iov[buf->pos].iov_len + size <= buf->capacity[buf->pos]); return (char*) buf->iov[buf->pos].iov_base + buf->iov[buf->pos].iov_len; }
int main() { srand(time(0)); struct slab_arena arena; struct slab_cache cache; slab_arena_create(&arena, 0, UINT_MAX, 4000000, MAP_PRIVATE); slab_cache_create(&cache, &arena, 0); int i = 0; while (i < ITERATIONS) { int run = random() % NRUNS; int size = random() % MAX_ALLOC; if (runs[run]) { slab_put(&cache, runs[run]); } runs[run] = slab_get(&cache, size); fail_unless(runs[run]); slab_cache_check(&cache); i++; } slab_cache_destroy(&cache); }
void * region_reserve_slow(struct region *region, size_t size) { /* The new slab must have at least this many bytes available. */ size_t slab_min_size = size + rslab_sizeof() - slab_sizeof(); struct rslab *slab; slab = (struct rslab *) slab_get(region->cache, slab_min_size); if (slab == NULL) return NULL; slab->used = 0; /* * Sic: add the new slab to the beginning of the * region, even if it is full, otherwise, * region_truncate() won't work. */ slab_list_add(®ion->slabs, &slab->slab, next_in_list); return rslab_data(slab); }
/** Allocate memory for a single iovec buffer. */ static inline void * obuf_alloc_pos(struct obuf *buf, size_t size) { int pos = buf->pos; assert(buf->capacity[pos] == 0 && buf->iov[pos].iov_len == 0); assert(pos < SMALL_OBUF_IOV_MAX); assert(buf->n_iov == pos); /** Initialize the next pos. */ buf->iov[pos+1] = buf->iov[pos]; buf->capacity[pos+1] = buf->capacity[pos]; size_t capacity = buf->start_capacity << pos; while (capacity < size) { capacity = capacity == 0 ? buf->start_capacity: capacity * 2; } struct slab *slab = slab_get(buf->slabc, capacity); if (slab == NULL) return NULL; buf->iov[pos].iov_base = slab_data(slab); buf->capacity[pos] = slab_capacity(slab); buf->n_iov++; return buf->iov[pos].iov_base; }