/** prealloc some entries in the cache. To minimize contention. * Result is 1 lock per alloc_max newly created entries. * @param alloc: the structure to fill up. */ static void prealloc(struct alloc_cache* alloc) { alloc_special_t* p; int i; for(i=0; i<ALLOC_SPECIAL_MAX; i++) { if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) { log_err("prealloc: out of memory"); return; } alloc_setup_special(p); alloc_set_special_next(p, alloc->quar); alloc->quar = p; alloc->num_quar++; } }
alloc_special_type* alloc_special_obtain(struct alloc_cache* alloc) { alloc_special_type* p; log_assert(alloc); /* see if in local cache */ if(alloc->quar) { p = alloc->quar; alloc->quar = alloc_special_next(p); alloc->num_quar--; p->id = alloc_get_id(alloc); return p; } /* see if in global cache */ if(alloc->super) { /* could maybe grab alloc_max/2 entries in one go, * but really, isn't that just as fast as this code? */ lock_quick_lock(&alloc->super->lock); if((p = alloc->super->quar)) { alloc->super->quar = alloc_special_next(p); alloc->super->num_quar--; } lock_quick_unlock(&alloc->super->lock); if(p) { p->id = alloc_get_id(alloc); return p; } } /* allocate new */ prealloc_setup(alloc); if(!(p = (alloc_special_type*)malloc(sizeof(alloc_special_type)))) { log_err("alloc_special_obtain: out of memory"); return NULL; } alloc_setup_special(p); p->id = alloc_get_id(alloc); return p; }