Hmm. You might be right. It should work without that first alignment operation because the (size) is already aligned. But for safety's sake I would probably want to change the if() into a while() to allow count to be adjusted twice if necessary, just to be sure. The init function is not in a critical path. I'll test it out a bit and commit with a credit to you. Thanks!
-Matt
diff --git a/sys/kern/kern_kmalloc.c b/sys/kern/kern_kmalloc.c index d222e053869..27ae4a81ac9 100644 --- a/sys/kern/kern_kmalloc.c +++ b/sys/kern/kern_kmalloc.c @@ -288,21 +288,23 @@ malloc_mgt_init(struct malloc_type *type __unused, /* * Figure out the count by taking into account the size of the fobjs[] - * array by adding it to the object size. + * array by adding it to the object size. This initial calculation + * ignores alignment edge-cases that might require the count to be + * reduced. */ offset = offsetof(struct kmalloc_slab, fobjs[0]); - offset = __VM_CACHELINE_ALIGN(offset); count = (KMALLOC_SLAB_SIZE - offset) / (size + sizeof(void *)); /* - * However, the fobj[] array itself must be aligned, so we might - * have to reduce the count by 1. (We can do this becaues 'size' - * is already aligned as well). + * Recalculate the offset of the first object, this time including + * the required alignment. (size) should already be aligned. This + * may push the last object beyond the slab so check and loop with + * a reduced count as necessary. */ offset = offsetof(struct kmalloc_slab, fobjs[count]); offset = __VM_CACHELINE_ALIGN(offset); - if (offset + size * count > KMALLOC_SLAB_SIZE) { + while (offset + size * count > KMALLOC_SLAB_SIZE) { --count; offset = offsetof(struct kmalloc_slab, fobjs[count]); offset = __VM_CACHELINE_ALIGN(offset); @@ -311,6 +313,10 @@ malloc_mgt_init(struct malloc_type *type __unused, mgt->slab_offset = offset; mgt->slab_count = count; + + kprintf("XXX mgt_init %s base offset %zx count %zd (end %08zx)\n", + type->ks_shortdesc, offset, count, offset + size * count); + } void