| version 1.92, 2004/03/17 09:58:15 |
version 1.93, 2004/03/17 10:03:26 |
| Line 147 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 160 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 167 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 228 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); |
| |
|
| |
return rv; |
| |
} |
| |
|
| |
/* |
| |
* sodopendfreel: free mbufs on "pendfree" list. |
| |
* unlock and relock so_pendfree_slock when freeing mbufs. |
| |
* |
| |
* => called with so_pendfree_slock held. |
| |
* => called at splvm. |
| |
*/ |
| |
|
| |
static size_t |
| |
sodopendfreel(struct socket *so) |
| |
{ |
| |
size_t rv = 0; |
| |
|
| |
LOCK_ASSERT(simple_lock_held(&so_pendfree_slock)); |
| |
|
| for (;;) { |
for (;;) { |
| |
struct mbuf *m; |
| |
struct mbuf *next; |
| |
|
| m = so_pendfree; |
m = so_pendfree; |
| if (m == NULL) |
if (m == NULL) |
| break; |
break; |
| 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); |
| } |
} |
| |
|
| Line 259 soloanfree(struct mbuf *m, caddr_t buf, |
|
| Line 336 soloanfree(struct mbuf *m, caddr_t buf, |
|
| 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(); |
| |
simple_lock(&so_pendfree_slock); |
| m->m_next = so_pendfree; |
m->m_next = so_pendfree; |
| so_pendfree = m; |
so_pendfree = m; |
| splx(s); |
|
| if (sokvawaiters) |
if (sokvawaiters) |
| wakeup(&socurkva); |
wakeup(&socurkva); |
| |
simple_unlock(&so_pendfree_slock); |
| |
splx(s); |
| } |
} |
| |
|
| static long |
static long |