From 30f700e9c7902ad335d44cc23c1a0d08f8c6c822 Mon Sep 17 00:00:00 2001 From: Garrett Wollman Date: Thu, 13 Feb 1997 19:41:40 +0000 Subject: [PATCH] Provide an alternative mbuf cluster allocator which permits use of clusters greater than one page in length by calling contigmalloc1(). This uses a helper process `mclalloc' to do the allocation if the system runs out at interrupt time to avoid calling contigmalloc at high spl. It is not yet clear to me whether this works. --- sys/kern/uipc_mbuf.c | 47 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 3f99385b868b..d2cb6c05d145 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -81,8 +81,14 @@ mbinit(dummy) s = splimp(); if (m_mballoc(NMB_INIT, M_DONTWAIT) == 0) goto bad; +#if MCLBYTES <= PAGE_SIZE if (m_clalloc(NCL_INIT, M_DONTWAIT) == 0) goto bad; +#else + /* It's OK to call contigmalloc in this context. */ + if (m_clalloc(16, 0) == 0) + goto bad; +#endif splx(s); return; bad: @@ -130,6 +136,34 @@ m_mballoc(nmb, nowait) return (1); } +#if MCLBYTES > PAGE_SIZE +int i_want_my_mcl; + +void +kproc_mclalloc(void) +{ + int status; + + while (1) { + tsleep(&i_want_my_mcl, PVM, "mclalloc", 0); + + for (; i_want_my_mcl; i_want_my_mcl--) { + if (m_clalloc(1, 0) == 0) + printf("m_clalloc failed even in process context!\n"); + } + } +} + +static struct proc *mclallocproc; +static struct kproc_desc mclalloc_kp = { + "mclalloc", + kproc_mclalloc, + &mclallocproc +}; +SYSINIT_KT(mclallocproc, SI_SUB_KTHREAD_UPDATE, SI_ORDER_ANY, kproc_start, + &mclalloc_kp); +#endif + /* * Allocate some number of mbuf clusters * and place on cluster free list. @@ -153,9 +187,21 @@ m_clalloc(ncl, nowait) if (mb_map_full) return (0); +#if MCLBYTES > PAGE_SIZE + if (nowait) { + i_want_my_mcl += ncl; + wakeup(&i_want_my_mcl); + p = 0; + } else { + p = contigmalloc1(MCLBYTES * ncl, M_DEVBUF, M_WAITOK, 0ul, + ~0ul, PAGE_SIZE, 0, mb_map); + } +#else npg = ncl; p = (caddr_t)kmem_malloc(mb_map, ctob(npg), nowait ? M_NOWAIT : M_WAITOK); + ncl = ncl * PAGE_SIZE / MCLBYTES; +#endif /* * Either the map is now full, or this is nowait and there * are no pages left. @@ -163,7 +209,6 @@ m_clalloc(ncl, nowait) if (p == NULL) return (0); - ncl = ncl * PAGE_SIZE / MCLBYTES; for (i = 0; i < ncl; i++) { ((union mcluster *)p)->mcl_next = mclfree; mclfree = (union mcluster *)p;