From b5be66cc63d59d04cafe5dcd24716030636a27c1 Mon Sep 17 00:00:00 2001 From: Samuel J. Greear Date: Wed, 3 Feb 2010 03:31:21 -0700 Subject: [PATCH 1/4] Lock sf_buf hashtable and freelist Move sf procedures out from under mplock --- sys/kern/kern_sfbuf.c | 10 +++++++++- sys/kern/uipc_syscalls.c | 7 ++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_sfbuf.c b/sys/kern/kern_sfbuf.c index 487a091..e5b01dd 100644 --- a/sys/kern/kern_sfbuf.c +++ b/sys/kern/kern_sfbuf.c @@ -40,6 +40,7 @@ #include #include #include +#include #include static void sf_buf_init(void *arg); @@ -61,6 +62,7 @@ static u_int sf_buf_alloc_want; static vm_offset_t sf_base; static struct sf_buf *sf_bufs; +static struct spinlock sf_buf_spin; static int sfbuf_quick = 1; SYSCTL_INT(_debug, OID_AUTO, sfbuf_quick, CTLFLAG_RW, &sfbuf_quick, 0, ""); @@ -87,6 +89,7 @@ sf_buf_init(void *arg) int i; sf_buf_hashtable = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask); + spin_init(&sf_buf_spin); TAILQ_INIT(&sf_buf_freelist); sf_base = kmem_alloc_nofault(&kernel_map, nsfbufs * PAGE_SIZE); sf_bufs = kmalloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, @@ -112,6 +115,7 @@ sf_buf_alloc(struct vm_page *m, int flags) int pflags; gd = mycpu; + spin_lock_wr(&sf_buf_spin); crit_enter(); hash_chain = &sf_buf_hashtable[sf_buf_hash(m)]; LIST_FOREACH(sf, hash_chain, list_entry) { @@ -153,7 +157,8 @@ sf_buf_alloc(struct vm_page *m, int flags) if ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) { pflags = (flags & SFB_CATCH) ? PCATCH : 0; ++sf_buf_alloc_want; - error = tsleep(&sf_buf_freelist, pflags, "sfbufa", 0); + error = ssleep(&sf_buf_freelist, &sf_buf_spin, pflags, + "sfbufa", 0); --sf_buf_alloc_want; if (error) goto done; @@ -192,6 +197,7 @@ sf_buf_alloc(struct vm_page *m, int flags) sf->cpumask = (cpumask_t)-1; } done: + spin_unlock_wr(&sf_buf_spin); crit_exit(); return (sf); } @@ -229,7 +235,9 @@ sf_buf_free(struct sf_buf *sf) crit_enter(); sf->refcnt--; if (sf->refcnt == 0 && (sf->flags & SFBA_ONFREEQ) == 0) { + spin_lock_wr(&sf_buf_spin); TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry); + spin_unlock_wr(&sf_buf_spin); ++nsffree; sf->flags |= SFBA_ONFREEQ; if (sf_buf_alloc_want > 0) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 5aaa424..319a3f7 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1418,13 +1418,14 @@ sf_buf_mfree(void *arg) KKASSERT(sfm->mref_count > 0); if (atomic_fetchadd_int(&sfm->mref_count, -1) == 1) { + m = sf_buf_page(sfm->sf); + sf_buf_free(sfm->sf); + /* - * XXX vm_page_*() and SFBUF routines not MPSAFE yet. + * XXX vm_page_*() routines not MPSAFE yet. */ get_mplock(); crit_enter(); - m = sf_buf_page(sfm->sf); - sf_buf_free(sfm->sf); vm_page_unwire(m, 0); if (m->wire_count == 0 && m->object == NULL) vm_page_try_to_free(m); -- 1.6.4