version 1.88, 2003/09/14 23:45:16 |
version 1.93, 2004/03/17 10:03:26 |
Line 90 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 90 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/resourcevar.h> |
#include <sys/resourcevar.h> |
#include <sys/pool.h> |
#include <sys/pool.h> |
#include <sys/event.h> |
#include <sys/event.h> |
|
#include <sys/poll.h> |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
|
|
|
soinit(void) |
soinit(void) |
{ |
{ |
|
|
|
/* Set the initial adjusted socket buffer size. */ |
|
if (sb_max_set(sb_max)) |
|
panic("bad initial sb_max value: %lu\n", sb_max); |
|
|
pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0, |
pool_init(&socket_pool, sizeof(struct socket), 0, 0, 0, |
"sockpl", NULL); |
"sockpl", NULL); |
|
|
Line 142 int use_sosend_loan = 0; |
|
Line 147 int use_sosend_loan = 0; |
|
int use_sosend_loan = 1; |
int use_sosend_loan = 1; |
#endif |
#endif |
|
|
|
struct simplelock so_pendfree_slock = SIMPLELOCK_INITIALIZER; |
struct mbuf *so_pendfree; |
struct mbuf *so_pendfree; |
|
|
#ifndef SOMAXKVA |
#ifndef SOMAXKVA |
Line 155 int sokvawaiters; |
|
Line 161 int sokvawaiters; |
|
#define SOCK_LOAN_CHUNK 65536 |
#define SOCK_LOAN_CHUNK 65536 |
|
|
static size_t sodopendfree(struct socket *); |
static size_t sodopendfree(struct socket *); |
|
static size_t sodopendfreel(struct socket *); |
|
|
|
/* |
|
* sokvaalloc: allocate kva for loan. |
|
*/ |
|
|
vaddr_t |
vaddr_t |
sokvaalloc(vsize_t len, struct socket *so) |
sokvaalloc(vsize_t len, struct socket *so) |
Line 162 sokvaalloc(vsize_t len, struct socket *s |
|
Line 173 sokvaalloc(vsize_t len, struct socket *s |
|
vaddr_t lva; |
vaddr_t lva; |
int s; |
int s; |
|
|
|
/* |
|
* reserve kva. |
|
*/ |
|
|
|
s = splvm(); |
|
simple_lock(&so_pendfree_slock); |
while (socurkva + len > somaxkva) { |
while (socurkva + len > somaxkva) { |
if (sodopendfree(so)) |
size_t freed; |
|
|
|
/* |
|
* try to do pendfree. |
|
*/ |
|
|
|
freed = sodopendfreel(so); |
|
|
|
/* |
|
* if some kva was freed, try again. |
|
*/ |
|
|
|
if (freed) |
continue; |
continue; |
|
|
SOSEND_COUNTER_INCR(&sosend_kvalimit); |
SOSEND_COUNTER_INCR(&sosend_kvalimit); |
s = splvm(); |
|
sokvawaiters++; |
sokvawaiters++; |
(void) tsleep(&socurkva, PVM, "sokva", 0); |
(void) ltsleep(&socurkva, PVM, "sokva", 0, &so_pendfree_slock); |
sokvawaiters--; |
sokvawaiters--; |
splx(s); |
|
} |
} |
|
socurkva += len; |
|
simple_unlock(&so_pendfree_slock); |
|
splx(s); |
|
|
|
/* |
|
* allocate kva. |
|
*/ |
|
|
lva = uvm_km_valloc_wait(kernel_map, len); |
lva = uvm_km_valloc_wait(kernel_map, len); |
if (lva == 0) |
if (lva == 0) |
return (0); |
return (0); |
socurkva += len; |
|
|
|
return lva; |
return lva; |
} |
} |
|
|
|
/* |
|
* sokvafree: free kva for loan. |
|
*/ |
|
|
void |
void |
sokvafree(vaddr_t sva, vsize_t len) |
sokvafree(vaddr_t sva, vsize_t len) |
{ |
{ |
|
int s; |
|
|
|
/* |
|
* free kva. |
|
*/ |
|
|
uvm_km_free(kernel_map, sva, len); |
uvm_km_free(kernel_map, sva, len); |
|
|
|
/* |
|
* unreserve kva. |
|
*/ |
|
|
|
s = splvm(); |
|
simple_lock(&so_pendfree_slock); |
socurkva -= len; |
socurkva -= len; |
if (sokvawaiters) |
if (sokvawaiters) |
wakeup(&socurkva); |
wakeup(&socurkva); |
|
simple_unlock(&so_pendfree_slock); |
|
splx(s); |
} |
} |
|
|
static void |
static void |
Line 223 sodoloanfree(struct vm_page **pgs, caddr |
|
Line 275 sodoloanfree(struct vm_page **pgs, caddr |
|
static size_t |
static size_t |
sodopendfree(struct socket *so) |
sodopendfree(struct socket *so) |
{ |
{ |
struct mbuf *m; |
|
size_t rv = 0; |
|
int s; |
int s; |
|
size_t rv; |
|
|
s = splvm(); |
s = splvm(); |
|
simple_lock(&so_pendfree_slock); |
|
rv = sodopendfreel(so); |
|
simple_unlock(&so_pendfree_slock); |
|
splx(s); |
|
|
for (;;) { |
return rv; |
m = so_pendfree; |
} |
if (m == NULL) |
|
break; |
|
so_pendfree = m->m_next; |
|
splx(s); |
|
|
|
rv += m->m_ext.ext_size; |
/* |
sodoloanfree((m->m_flags & M_EXT_PAGES) ? |
* sodopendfreel: free mbufs on "pendfree" list. |
m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf, |
* unlock and relock so_pendfree_slock when freeing mbufs. |
m->m_ext.ext_size); |
* |
s = splvm(); |
* => called with so_pendfree_slock held. |
pool_cache_put(&mbpool_cache, m); |
* => called at splvm. |
} |
*/ |
|
|
|
static size_t |
|
sodopendfreel(struct socket *so) |
|
{ |
|
size_t rv = 0; |
|
|
|
LOCK_ASSERT(simple_lock_held(&so_pendfree_slock)); |
|
|
for (;;) { |
for (;;) { |
m = so->so_pendfree; |
struct mbuf *m; |
|
struct mbuf *next; |
|
|
|
m = so_pendfree; |
if (m == NULL) |
if (m == NULL) |
break; |
break; |
so->so_pendfree = m->m_next; |
so_pendfree = NULL; |
splx(s); |
simple_unlock(&so_pendfree_slock); |
|
/* XXX splx */ |
|
|
|
for (; m != NULL; m = next) { |
|
next = m->m_next; |
|
|
|
rv += m->m_ext.ext_size; |
|
sodoloanfree((m->m_flags & M_EXT_PAGES) ? |
|
m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf, |
|
m->m_ext.ext_size); |
|
pool_cache_put(&mbpool_cache, m); |
|
} |
|
|
rv += m->m_ext.ext_size; |
/* XXX splvm */ |
sodoloanfree((m->m_flags & M_EXT_PAGES) ? |
simple_lock(&so_pendfree_slock); |
m->m_ext.ext_pgs : NULL, m->m_ext.ext_buf, |
|
m->m_ext.ext_size); |
|
s = splvm(); |
|
pool_cache_put(&mbpool_cache, m); |
|
} |
} |
|
|
splx(s); |
|
return (rv); |
return (rv); |
} |
} |
|
|
void |
void |
soloanfree(struct mbuf *m, caddr_t buf, size_t size, void *arg) |
soloanfree(struct mbuf *m, caddr_t buf, size_t size, void *arg) |
{ |
{ |
struct socket *so = arg; |
|
int s; |
int s; |
|
|
if (m == NULL) { |
if (m == NULL) { |
|
|
|
/* |
|
* called from MEXTREMOVE. |
|
*/ |
|
|
sodoloanfree(NULL, buf, size); |
sodoloanfree(NULL, buf, size); |
return; |
return; |
} |
} |
|
|
|
/* |
|
* postpone freeing mbuf. |
|
* |
|
* we can't do it in interrupt context |
|
* because we need to put kva back to kernel_map. |
|
*/ |
|
|
s = splvm(); |
s = splvm(); |
m->m_next = so->so_pendfree; |
simple_lock(&so_pendfree_slock); |
so->so_pendfree = m; |
m->m_next = so_pendfree; |
splx(s); |
so_pendfree = m; |
if (sokvawaiters) |
if (sokvawaiters) |
wakeup(&socurkva); |
wakeup(&socurkva); |
|
simple_unlock(&so_pendfree_slock); |
|
splx(s); |
} |
} |
|
|
static long |
static long |
Line 430 solisten(struct socket *so, int backlog) |
|
Line 510 solisten(struct socket *so, int backlog) |
|
void |
void |
sofree(struct socket *so) |
sofree(struct socket *so) |
{ |
{ |
struct mbuf *m; |
|
|
|
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) |
if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0) |
return; |
return; |
Line 445 sofree(struct socket *so) |
|
Line 524 sofree(struct socket *so) |
|
} |
} |
sbrelease(&so->so_snd); |
sbrelease(&so->so_snd); |
sorflush(so); |
sorflush(so); |
while ((m = so->so_pendfree) != NULL) { |
|
so->so_pendfree = m->m_next; |
|
m->m_next = so_pendfree; |
|
so_pendfree = m; |
|
} |
|
pool_put(&socket_pool, so); |
pool_put(&socket_pool, so); |
} |
} |
|
|
Line 1506 sogetopt(struct socket *so, int level, i |
|
Line 1580 sogetopt(struct socket *so, int level, i |
|
void |
void |
sohasoutofband(struct socket *so) |
sohasoutofband(struct socket *so) |
{ |
{ |
struct proc *p; |
fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so); |
ksiginfo_t ksi; |
|
memset(&ksi, 0, sizeof(ksi)); |
|
ksi.ksi_signo = SIGURG; |
|
ksi.ksi_band = POLLPRI|POLLRDBAND; |
|
ksi.ksi_code = POLL_PRI; |
|
|
|
if (so->so_pgid < 0) |
|
kgsignal(-so->so_pgid, &ksi, so); |
|
else if (so->so_pgid > 0 && (p = pfind(so->so_pgid)) != 0) |
|
kpsignal(p, &ksi, so); |
|
selwakeup(&so->so_rcv.sb_sel); |
selwakeup(&so->so_rcv.sb_sel); |
} |
} |
|
|