> Date: Sun, 30 Jul 2017 10:22:11 +0200
> From: Kamil Rytarowski <n...@gmx.com>
> 
> I think we should go for kmem_reallocarr(). It has been designed for
> overflows like realocarray(3) with an option to be capable to resize a
> table fron 1 to N elements and back from N to 0 including freeing.

Initially I was reluctant to do that because (a) we don't even have a
kmem_realloc, perhaps for some particular reason, and (b) it requires
an extra parameter for the old size.  But I don't know any particular
reason in (a), and perhaps (b) not so bad after all.  Here's a draft:

int
kmem_reallocarr(void *ptrp, size_t size, size_t ocnt, size_t ncnt, int flags)
{
        void *optr, *nptr;

        KASSERT(size != 0);
        if (__predict_false((size|ncnt) >= SQRT_SIZE_MAX &&
                ncnt > SIZE_MAX/size))
                return ENOMEM;

        memcpy(&optr, ptrp, sizeof(void *));
        KASSERT((ocnt == 0) == (optr == NULL));
        if (ncnt == 0) {
                nptr = NULL;
        } else {
                nptr = kmem_alloc(size*ncnt, flags);
                KASSERT(nptr != NULL || flags == KM_NOSLEEP);
                if (nptr == NULL)
                        return ENOMEM;
        }
        KASSERT((ncnt == 0) == (nptr == NULL));
        if (ocnt & ncnt)
                memcpy(nptr, optr, size*MIN(ocnt, ncnt));
        if (ocnt != 0)
                kmem_free(optr, size*ocnt);
        memcpy(ptrp, &nptr, sizeof(void *));

        return 0;
}

Reply via email to