Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/uipc_socket.c,v retrieving revision 1.177.4.4 retrieving revision 1.178 diff -u -p -r1.177.4.4 -r1.178 --- src/sys/kern/uipc_socket.c 2011/08/08 19:45:57 1.177.4.4 +++ src/sys/kern/uipc_socket.c 2008/12/07 20:58:46 1.178 @@ -1,11 +1,11 @@ -/* $NetBSD: uipc_socket.c,v 1.177.4.4 2011/08/08 19:45:57 riz Exp $ */ +/* $NetBSD: uipc_socket.c,v 1.178 2008/12/07 20:58:46 pooka Exp $ */ /*- - * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2002, 2007, 2008 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran. + * by Jason R. Thorpe of Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -63,7 +63,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.177.4.4 2011/08/08 19:45:57 riz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.178 2008/12/07 20:58:46 pooka Exp $"); #include "opt_sock_counters.h" #include "opt_sosend_loan.h" @@ -91,7 +91,6 @@ __KERNEL_RCSID(0, "$NetBSD: uipc_socket. #include #include #include -#include #include @@ -137,7 +136,7 @@ int sock_loan_thresh = 4096; #endif static kmutex_t so_pendfree_lock; -static struct mbuf *so_pendfree = NULL; +static struct mbuf *so_pendfree; #ifndef SOMAXKVA #define SOMAXKVA (16 * 1024 * 1024) @@ -148,9 +147,11 @@ static kcondvar_t socurkva_cv; #define SOCK_LOAN_CHUNK 65536 -static void sopendfree_thread(void *); -static kcondvar_t pendfree_thread_cv; -static lwp_t *sopendfree_lwp; +static size_t sodopendfree(void); +static size_t sodopendfreel(void); + +static void sysctl_kern_somaxkva_setup(void); +static struct sysctllog *socket_sysctllog; static vsize_t sokvareserve(struct socket *so, vsize_t len) @@ -159,6 +160,21 @@ sokvareserve(struct socket *so, vsize_t mutex_enter(&so_pendfree_lock); while (socurkva + len > somaxkva) { + size_t freed; + + /* + * try to do pendfree. + */ + + freed = sodopendfreel(); + + /* + * if some kva was freed, try again. + */ + + if (freed) + continue; + SOSEND_COUNTER_INCR(&sosend_kvalimit); error = cv_wait_sig(&socurkva_cv, &so_pendfree_lock); if (error) { @@ -251,45 +267,56 @@ sodoloanfree(struct vm_page **pgs, void sokvafree(sva, len); } +static size_t +sodopendfree(void) +{ + size_t rv; + + if (__predict_true(so_pendfree == NULL)) + return 0; + + mutex_enter(&so_pendfree_lock); + rv = sodopendfreel(); + mutex_exit(&so_pendfree_lock); + + return rv; +} + /* - * sopendfree_thread: free mbufs on "pendfree" list. + * sodopendfreel: free mbufs on "pendfree" list. * unlock and relock so_pendfree_lock when freeing mbufs. + * + * => called with so_pendfree_lock held. */ -static void -sopendfree_thread(void *v) +static size_t +sodopendfreel(void) { struct mbuf *m, *next; - size_t rv; + size_t rv = 0; - mutex_enter(&so_pendfree_lock); + KASSERT(mutex_owned(&so_pendfree_lock)); - for (;;) { - rv = 0; - while (so_pendfree != NULL) { - m = so_pendfree; - so_pendfree = NULL; - mutex_exit(&so_pendfree_lock); - - for (; m != NULL; m = next) { - next = m->m_next; - KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0); - KASSERT(m->m_ext.ext_refcnt == 0); - - rv += m->m_ext.ext_size; - sodoloanfree(m->m_ext.ext_pgs, m->m_ext.ext_buf, - m->m_ext.ext_size); - pool_cache_put(mb_cache, m); - } + while (so_pendfree != NULL) { + m = so_pendfree; + so_pendfree = NULL; + mutex_exit(&so_pendfree_lock); - mutex_enter(&so_pendfree_lock); + for (; m != NULL; m = next) { + next = m->m_next; + KASSERT((~m->m_flags & (M_EXT|M_EXT_PAGES)) == 0); + KASSERT(m->m_ext.ext_refcnt == 0); + + rv += m->m_ext.ext_size; + sodoloanfree(m->m_ext.ext_pgs, m->m_ext.ext_buf, + m->m_ext.ext_size); + pool_cache_put(mb_cache, m); } - if (rv) - cv_broadcast(&socurkva_cv); - cv_wait(&pendfree_thread_cv, &so_pendfree_lock); + + mutex_enter(&so_pendfree_lock); } - panic("sopendfree_thread"); - /* NOTREACHED */ + + return (rv); } void @@ -308,7 +335,7 @@ soloanfree(struct mbuf *m, void *buf, si mutex_enter(&so_pendfree_lock); m->m_next = so_pendfree; so_pendfree = m; - cv_signal(&pendfree_thread_cv); + cv_broadcast(&socurkva_cv); mutex_exit(&so_pendfree_lock); } @@ -378,6 +405,7 @@ sokva_reclaim_callback(struct callback_e KASSERT(ce == &sokva_reclaimerentry); KASSERT(obj == NULL); + sodopendfree(); if (!vm_map_starved_p(kernel_map)) { return CALLBACK_CHAIN_ABORT; } @@ -395,15 +423,16 @@ getsombuf(struct socket *so, int type) } void -soinit() +soinit(void) { + + sysctl_kern_somaxkva_setup(); + mutex_init(&so_pendfree_lock, MUTEX_DEFAULT, IPL_VM); softnet_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE); cv_init(&socurkva_cv, "sokva"); - cv_init(&pendfree_thread_cv, "sopendfr"); soinit2(); - /* Set the initial adjusted socket buffer size. */ if (sb_max_set(sb_max)) panic("bad initial sb_max value: %lu", sb_max); @@ -412,15 +441,6 @@ soinit() &sokva_reclaimerentry, NULL, sokva_reclaim_callback); } -void -soinit1(void) -{ - int error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, - sopendfree_thread, NULL, &sopendfree_lwp, "sopendfree"); - if (error) - panic("soinit1 %d", error); -} - /* * Socket operation routines. * These routines are called by the routines in @@ -654,7 +674,7 @@ soclose(struct socket *so) if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio) goto drop; while (so->so_state & SS_ISCONNECTED) { - error = sowait(so, true, so->so_linger * hz); + error = sowait(so, so->so_linger * hz); if (error) break; } @@ -772,6 +792,7 @@ sodisconnect(struct socket *so) error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT, NULL, NULL, NULL, NULL); } + sodopendfree(); return (error); } @@ -803,6 +824,7 @@ sosend(struct socket *so, struct mbuf *a int error, s, dontroute, atomic; p = l->l_proc; + sodopendfree(); clen = 0; /* @@ -1071,6 +1093,9 @@ soreceive(struct socket *so, struct mbuf else flags = 0; + if ((flags & MSG_DONTWAIT) == 0) + sodopendfree(); + if (flags & MSG_OOB) { m = m_get(M_WAIT, MT_DATA); solock(so); @@ -1516,20 +1541,6 @@ soshutdown(struct socket *so, int how) return error; } -int -sodrain(struct socket *so) -{ - int error; - - solock(so); - so->so_state |= SS_ISDRAINING; - cv_broadcast(&so->so_cv); - error = soshutdown(so, SHUT_RDWR); - sounlock(so); - - return error; -} - void sorflush(struct socket *so) { @@ -2023,7 +2034,7 @@ sohasoutofband(struct socket *so) { fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so); - selnotify(&so->so_rcv.sb_sel, POLLPRI | POLLRDBAND, NOTE_SUBMIT); + selnotify(&so->so_rcv.sb_sel, POLLPRI | POLLRDBAND, 0); } static void @@ -2254,16 +2265,18 @@ sysctl_kern_somaxkva(SYSCTLFN_ARGS) return (error); } -SYSCTL_SETUP(sysctl_kern_somaxkva_setup, "sysctl kern.somaxkva setup") +static void +sysctl_kern_somaxkva_setup() { - sysctl_createv(clog, 0, NULL, NULL, + KASSERT(socket_sysctllog == NULL); + sysctl_createv(&socket_sysctllog, 0, NULL, NULL, CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL, NULL, 0, NULL, 0, CTL_KERN, CTL_EOL); - sysctl_createv(clog, 0, NULL, NULL, + sysctl_createv(&socket_sysctllog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "somaxkva", SYSCTL_DESCR("Maximum amount of kernel memory to be "