/** *structobjpool_head-objectpoolingmetadata *@obj_size:objectsize,alignedtosizeof(void*) *@nr_objs:totalobjs(tobepre-allocatedwithobjpool) *@nr_possible_cpus:cachedvalueofnum_possible_cpus() *@capacity:maxobjscanbemanagedbyoneobjpool_slot *@gfp:gfpflagsforkmalloc&vmalloc *@ref:refcountofobjpool *@flags:flagsforobjpoolmanagement *@cpu_slots:pointertothearrayofobjpool_slot *@release:resourcecleanupcallback *@context:caller-providedcontext
*/ struct objpool_head { int obj_size; int nr_objs; int nr_possible_cpus; int capacity;
gfp_t gfp;
refcount_t ref; unsignedlong flags; struct objpool_slot **cpu_slots;
objpool_fini_cb release; void *context;
};
#define OBJPOOL_NR_OBJECT_MAX (1UL << 24) /* maximum numbers of total objects */ #define OBJPOOL_OBJECT_SIZE_MAX (1UL << 16) /* maximum size of an object */
/* try to retrieve object from slot */ staticinlinevoid *__objpool_try_get_slot(struct objpool_head *pool, int cpu)
{ struct objpool_slot *slot = pool->cpu_slots[cpu]; /* load head snapshot, other cpus may change it */
uint32_t head = smp_load_acquire(&slot->head);
while (head != READ_ONCE(slot->last)) { void *obj;
/* *datavisibilityof'last'and'head'couldbeoutof *ordersincememoryupdatingof'last'and'head'are *performedinpush()andpop()independently * *beforeanyretrievingattempts,pop()mustguarantee *'last'isbehind'head',thatistosay,theremust *beavailableobjectsinslot,whichcouldbeensured *bycondition'last!=head&&last-head<=nr_objs' *thatisequivalentto'last-head-1<nr_objs'as *'last'and'head'arebothunsignedint32
*/ if (READ_ONCE(slot->last) - head - 1 >= pool->nr_objs) {
head = READ_ONCE(slot->head); continue;
}
/* obj must be retrieved before moving forward head */
obj = READ_ONCE(slot->entries[head & slot->mask]);
/* move head forward to mark it's consumption */ if (try_cmpxchg_release(&slot->head, &head, head + 1)) return obj;
}
/* adding object to slot, abort if the slot was already full */ staticinlineint
__objpool_try_add_slot(void *obj, struct objpool_head *pool, int cpu)
{ struct objpool_slot *slot = pool->cpu_slots[cpu];
uint32_t head, tail;
/* loading tail and head as a local snapshot, tail first */
tail = READ_ONCE(slot->tail);
do {
head = READ_ONCE(slot->head); /* fault caught: something must be wrong */
WARN_ON_ONCE(tail - head > pool->nr_objs);
} while (!try_cmpxchg_acquire(&slot->tail, &tail, tail + 1));
/* now the tail position is reserved for the given obj */
WRITE_ONCE(slot->entries[tail & slot->mask], obj); /* update sequence to make this obj available for pop() */
smp_store_release(&slot->last, tail + 1);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.