version 1.89.2.3, 2007/02/26 09:12:28 |
version 1.89.2.4, 2007/09/03 14:47:06 |
Line 84 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 84 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/resourcevar.h> |
#include <sys/resourcevar.h> |
#include <sys/buf.h> |
#include <sys/buf.h> |
#include <sys/user.h> |
#include <sys/user.h> |
|
#include <sys/syncobj.h> |
|
#include <sys/cpu.h> |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
|
|
#include <machine/cpu.h> |
|
|
|
/* |
/* |
* local prototypes |
* local prototypes |
*/ |
*/ |
|
|
static void uvm_swapout(struct lwp *); |
static void uvm_swapout(struct lwp *); |
|
|
#define UVM_NUAREA_MAX 16 |
#define UVM_NUAREA_HIWAT 20 |
static vaddr_t uvm_uareas; |
#define UVM_NUAREA_LOWAT 16 |
static int uvm_nuarea; |
|
static struct simplelock uvm_uareas_slock = SIMPLELOCK_INITIALIZER; |
|
#define UAREA_NEXTFREE(uarea) (*(vaddr_t *)(UAREA_TO_USER(uarea))) |
#define UAREA_NEXTFREE(uarea) (*(vaddr_t *)(UAREA_TO_USER(uarea))) |
|
|
static void uvm_uarea_free(vaddr_t); |
void uvm_uarea_free(vaddr_t); |
|
|
/* |
/* |
* XXXCDC: do these really belong here? |
* XXXCDC: do these really belong here? |
Line 114 static void uvm_uarea_free(vaddr_t); |
|
Line 113 static void uvm_uarea_free(vaddr_t); |
|
*/ |
*/ |
|
|
bool |
bool |
uvm_kernacc(caddr_t addr, size_t len, int rw) |
uvm_kernacc(void *addr, size_t len, int rw) |
{ |
{ |
bool rv; |
bool rv; |
vaddr_t saddr, eaddr; |
vaddr_t saddr, eaddr; |
Line 143 uvm_kernacc(caddr_t addr, size_t len, in |
|
Line 142 uvm_kernacc(caddr_t addr, size_t len, in |
|
* we can ensure the change takes place properly. |
* we can ensure the change takes place properly. |
*/ |
*/ |
void |
void |
uvm_chgkprot(caddr_t addr, size_t len, int rw) |
uvm_chgkprot(void *addr, size_t len, int rw) |
{ |
{ |
vm_prot_t prot; |
vm_prot_t prot; |
paddr_t pa; |
paddr_t pa; |
Line 280 uvm_lwp_fork(struct lwp *l1, struct lwp |
|
Line 279 uvm_lwp_fork(struct lwp *l1, struct lwp |
|
} |
} |
|
|
/* |
/* |
|
* uvm_cpu_attach: initialize per-CPU data structures. |
|
*/ |
|
|
|
void |
|
uvm_cpu_attach(struct cpu_info *ci) |
|
{ |
|
|
|
mutex_init(&ci->ci_data.cpu_uarea_lock, MUTEX_DEFAULT, IPL_NONE); |
|
ci->ci_data.cpu_uarea_cnt = 0; |
|
ci->ci_data.cpu_uarea_list = 0; |
|
} |
|
|
|
/* |
* uvm_uarea_alloc: allocate a u-area |
* uvm_uarea_alloc: allocate a u-area |
*/ |
*/ |
|
|
bool |
bool |
uvm_uarea_alloc(vaddr_t *uaddrp) |
uvm_uarea_alloc(vaddr_t *uaddrp) |
{ |
{ |
|
struct cpu_info *ci; |
vaddr_t uaddr; |
vaddr_t uaddr; |
|
|
#ifndef USPACE_ALIGN |
#ifndef USPACE_ALIGN |
#define USPACE_ALIGN 0 |
#define USPACE_ALIGN 0 |
#endif |
#endif |
|
|
simple_lock(&uvm_uareas_slock); |
ci = curcpu(); |
if (uvm_nuarea > 0) { |
|
uaddr = uvm_uareas; |
if (ci->ci_data.cpu_uarea_cnt > 0) { |
uvm_uareas = UAREA_NEXTFREE(uaddr); |
mutex_enter(&ci->ci_data.cpu_uarea_lock); |
uvm_nuarea--; |
if (ci->ci_data.cpu_uarea_cnt == 0) { |
simple_unlock(&uvm_uareas_slock); |
mutex_exit(&ci->ci_data.cpu_uarea_lock); |
*uaddrp = uaddr; |
} else { |
return true; |
uaddr = ci->ci_data.cpu_uarea_list; |
} else { |
ci->ci_data.cpu_uarea_list = UAREA_NEXTFREE(uaddr); |
simple_unlock(&uvm_uareas_slock); |
ci->ci_data.cpu_uarea_cnt--; |
*uaddrp = uvm_km_alloc(kernel_map, USPACE, USPACE_ALIGN, |
mutex_exit(&ci->ci_data.cpu_uarea_lock); |
UVM_KMF_PAGEABLE); |
*uaddrp = uaddr; |
return false; |
return true; |
|
} |
} |
} |
|
|
|
*uaddrp = uvm_km_alloc(kernel_map, USPACE, USPACE_ALIGN, |
|
UVM_KMF_PAGEABLE); |
|
return false; |
} |
} |
|
|
/* |
/* |
* uvm_uarea_free: free a u-area; never blocks |
* uvm_uarea_free: free a u-area |
*/ |
*/ |
|
|
static inline void |
void |
uvm_uarea_free(vaddr_t uaddr) |
uvm_uarea_free(vaddr_t uaddr) |
{ |
{ |
simple_lock(&uvm_uareas_slock); |
struct cpu_info *ci; |
UAREA_NEXTFREE(uaddr) = uvm_uareas; |
|
uvm_uareas = uaddr; |
ci = curcpu(); |
uvm_nuarea++; |
|
simple_unlock(&uvm_uareas_slock); |
mutex_enter(&ci->ci_data.cpu_uarea_lock); |
|
UAREA_NEXTFREE(uaddr) = ci->ci_data.cpu_uarea_list; |
|
ci->ci_data.cpu_uarea_list = uaddr; |
|
ci->ci_data.cpu_uarea_cnt++; |
|
mutex_exit(&ci->ci_data.cpu_uarea_lock); |
} |
} |
|
|
/* |
/* |
* uvm_uarea_drain: return memory of u-areas over limit |
* uvm_uarea_drain: return memory of u-areas over limit |
* back to system |
* back to system |
|
* |
|
* => if asked to drain as much as possible, drain all cpus. |
|
* => if asked to drain to low water mark, drain local cpu only. |
*/ |
*/ |
|
|
void |
void |
uvm_uarea_drain(bool empty) |
uvm_uarea_drain(bool empty) |
{ |
{ |
int leave = empty ? 0 : UVM_NUAREA_MAX; |
CPU_INFO_ITERATOR cii; |
vaddr_t uaddr; |
struct cpu_info *ci; |
|
vaddr_t uaddr, nuaddr; |
if (uvm_nuarea <= leave) |
int count; |
|
|
|
if (empty) { |
|
for (CPU_INFO_FOREACH(cii, ci)) { |
|
mutex_enter(&ci->ci_data.cpu_uarea_lock); |
|
count = ci->ci_data.cpu_uarea_cnt; |
|
uaddr = ci->ci_data.cpu_uarea_list; |
|
ci->ci_data.cpu_uarea_cnt = 0; |
|
ci->ci_data.cpu_uarea_list = 0; |
|
mutex_exit(&ci->ci_data.cpu_uarea_lock); |
|
|
|
while (count != 0) { |
|
nuaddr = UAREA_NEXTFREE(uaddr); |
|
uvm_km_free(kernel_map, uaddr, USPACE, |
|
UVM_KMF_PAGEABLE); |
|
uaddr = nuaddr; |
|
count--; |
|
} |
|
} |
return; |
return; |
|
} |
|
|
simple_lock(&uvm_uareas_slock); |
ci = curcpu(); |
while(uvm_nuarea > leave) { |
if (ci->ci_data.cpu_uarea_cnt > UVM_NUAREA_HIWAT) { |
uaddr = uvm_uareas; |
mutex_enter(&ci->ci_data.cpu_uarea_lock); |
uvm_uareas = UAREA_NEXTFREE(uaddr); |
while (ci->ci_data.cpu_uarea_cnt > UVM_NUAREA_LOWAT) { |
uvm_nuarea--; |
uaddr = ci->ci_data.cpu_uarea_list; |
simple_unlock(&uvm_uareas_slock); |
ci->ci_data.cpu_uarea_list = UAREA_NEXTFREE(uaddr); |
uvm_km_free(kernel_map, uaddr, USPACE, UVM_KMF_PAGEABLE); |
ci->ci_data.cpu_uarea_cnt--; |
simple_lock(&uvm_uareas_slock); |
mutex_exit(&ci->ci_data.cpu_uarea_lock); |
|
uvm_km_free(kernel_map, uaddr, USPACE, |
|
UVM_KMF_PAGEABLE); |
|
mutex_enter(&ci->ci_data.cpu_uarea_lock); |
|
} |
|
mutex_exit(&ci->ci_data.cpu_uarea_lock); |
} |
} |
simple_unlock(&uvm_uareas_slock); |
|
} |
} |
|
|
/* |
/* |
Line 420 int swapdebug = 0; |
|
Line 468 int swapdebug = 0; |
|
|
|
/* |
/* |
* uvm_swapin: swap in an lwp's u-area. |
* uvm_swapin: swap in an lwp's u-area. |
|
* |
|
* - must be called with the LWP's swap lock held. |
|
* - naturally, must not be called with l == curlwp |
*/ |
*/ |
|
|
void |
void |
Line 428 uvm_swapin(struct lwp *l) |
|
Line 479 uvm_swapin(struct lwp *l) |
|
vaddr_t addr; |
vaddr_t addr; |
int error; |
int error; |
|
|
|
KASSERT(mutex_owned(&l->l_swaplock)); |
|
KASSERT(l != curlwp); |
|
|
addr = USER_TO_UAREA(l->l_addr); |
addr = USER_TO_UAREA(l->l_addr); |
/* make L_INMEM true */ |
/* make L_INMEM true */ |
error = uvm_fault_wire(kernel_map, addr, addr + USPACE, |
error = uvm_fault_wire(kernel_map, addr, addr + USPACE, |
Line 443 uvm_swapin(struct lwp *l) |
|
Line 497 uvm_swapin(struct lwp *l) |
|
cpu_swapin(l); |
cpu_swapin(l); |
lwp_lock(l); |
lwp_lock(l); |
if (l->l_stat == LSRUN) |
if (l->l_stat == LSRUN) |
setrunqueue(l); |
sched_enqueue(l, false); |
l->l_flag |= LW_INMEM; |
l->l_flag |= LW_INMEM; |
l->l_swtime = 0; |
l->l_swtime = 0; |
lwp_unlock(l); |
lwp_unlock(l); |
Line 463 uvm_kick_scheduler(void) |
|
Line 517 uvm_kick_scheduler(void) |
|
if (uvm.swap_running == false) |
if (uvm.swap_running == false) |
return; |
return; |
|
|
mutex_enter(&uvm.scheduler_mutex); |
mutex_enter(&uvm_scheduler_mutex); |
uvm.scheduler_kicked = true; |
uvm.scheduler_kicked = true; |
cv_signal(&uvm.scheduler_cv); |
cv_signal(&uvm.scheduler_cv); |
mutex_exit(&uvm.scheduler_mutex); |
mutex_exit(&uvm_scheduler_mutex); |
} |
} |
|
|
/* |
/* |
Line 486 uvm_scheduler(void) |
|
Line 540 uvm_scheduler(void) |
|
|
|
l = curlwp; |
l = curlwp; |
lwp_lock(l); |
lwp_lock(l); |
lwp_changepri(l, PVM); |
l->l_priority = PVM; |
|
l->l_usrpri = PVM; |
lwp_unlock(l); |
lwp_unlock(l); |
|
|
for (;;) { |
for (;;) { |
#ifdef DEBUG |
#ifdef DEBUG |
mutex_enter(&uvm.scheduler_mutex); |
mutex_enter(&uvm_scheduler_mutex); |
while (!enableswap) |
while (!enableswap) |
cv_wait(&uvm.scheduler_cv, &uvm.scheduler_mutex); |
cv_wait(&uvm.scheduler_cv, &uvm_scheduler_mutex); |
mutex_exit(&uvm.scheduler_mutex); |
mutex_exit(&uvm_scheduler_mutex); |
#endif |
#endif |
ll = NULL; /* process to choose */ |
ll = NULL; /* process to choose */ |
ppri = INT_MIN; /* its priority */ |
ppri = INT_MIN; /* its priority */ |
|
|
mutex_enter(&proclist_mutex); |
mutex_enter(&proclist_lock); |
LIST_FOREACH(l, &alllwp, l_list) { |
LIST_FOREACH(l, &alllwp, l_list) { |
/* is it a runnable swapped out process? */ |
/* is it a runnable swapped out process? */ |
if (l->l_stat == LSRUN && !(l->l_flag & LW_INMEM)) { |
if (l->l_stat == LSRUN && !(l->l_flag & LW_INMEM)) { |
Line 511 uvm_scheduler(void) |
|
Line 566 uvm_scheduler(void) |
|
} |
} |
} |
} |
} |
} |
mutex_exit(&proclist_mutex); |
|
#ifdef DEBUG |
#ifdef DEBUG |
if (swapdebug & SDB_FOLLOW) |
if (swapdebug & SDB_FOLLOW) |
printf("scheduler: running, procp %p pri %d\n", ll, |
printf("scheduler: running, procp %p pri %d\n", ll, |
Line 521 uvm_scheduler(void) |
|
Line 575 uvm_scheduler(void) |
|
* Nothing to do, back to sleep |
* Nothing to do, back to sleep |
*/ |
*/ |
if ((l = ll) == NULL) { |
if ((l = ll) == NULL) { |
mutex_enter(&uvm.scheduler_mutex); |
mutex_exit(&proclist_lock); |
|
mutex_enter(&uvm_scheduler_mutex); |
if (uvm.scheduler_kicked == false) |
if (uvm.scheduler_kicked == false) |
cv_wait(&uvm.scheduler_cv, |
cv_wait(&uvm.scheduler_cv, |
&uvm.scheduler_mutex); |
&uvm_scheduler_mutex); |
uvm.scheduler_kicked = false; |
uvm.scheduler_kicked = false; |
mutex_exit(&uvm.scheduler_mutex); |
mutex_exit(&uvm_scheduler_mutex); |
continue; |
continue; |
} |
} |
|
|
Line 545 uvm_scheduler(void) |
|
Line 600 uvm_scheduler(void) |
|
l->l_proc->p_comm, l->l_addr, ppri, |
l->l_proc->p_comm, l->l_addr, ppri, |
uvmexp.free); |
uvmexp.free); |
#endif |
#endif |
|
mutex_enter(&l->l_swaplock); |
|
mutex_exit(&proclist_lock); |
uvm_swapin(l); |
uvm_swapin(l); |
|
mutex_exit(&l->l_swaplock); |
|
continue; |
} else { |
} else { |
/* |
/* |
* not enough memory, jab the pageout daemon and |
* not enough memory, jab the pageout daemon and |
* wait til the coast is clear |
* wait til the coast is clear |
*/ |
*/ |
|
mutex_exit(&proclist_lock); |
#ifdef DEBUG |
#ifdef DEBUG |
if (swapdebug & SDB_FOLLOW) |
if (swapdebug & SDB_FOLLOW) |
printf("scheduler: no room for pid %d(%s)," |
printf("scheduler: no room for pid %d(%s)," |
Line 571 uvm_scheduler(void) |
|
Line 631 uvm_scheduler(void) |
|
* swappable: is LWP "l" swappable? |
* swappable: is LWP "l" swappable? |
*/ |
*/ |
|
|
#define swappable(l) \ |
static bool |
(((l)->l_flag & (LW_INMEM)) && \ |
swappable(struct lwp *l) |
((((l)->l_flag) & (LW_SYSTEM | LW_WEXIT)) == 0) && \ |
{ |
(l)->l_holdcnt == 0) |
|
|
if ((l->l_flag & (LW_INMEM|LW_RUNNING|LW_SYSTEM|LW_WEXIT)) != LW_INMEM) |
|
return false; |
|
if (l->l_holdcnt != 0) |
|
return false; |
|
if (l->l_syncobj == &rw_syncobj || l->l_syncobj == &mutex_syncobj) |
|
return false; |
|
return true; |
|
} |
|
|
/* |
/* |
* swapout_threads: find threads that can be swapped and unwire their |
* swapout_threads: find threads that can be swapped and unwire their |
Line 595 uvm_swapout_threads(void) |
|
Line 663 uvm_swapout_threads(void) |
|
int outpri, outpri2; |
int outpri, outpri2; |
int didswap = 0; |
int didswap = 0; |
extern int maxslp; |
extern int maxslp; |
|
bool gotit; |
|
|
/* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */ |
/* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */ |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
Line 608 uvm_swapout_threads(void) |
|
Line 678 uvm_swapout_threads(void) |
|
*/ |
*/ |
outl = outl2 = NULL; |
outl = outl2 = NULL; |
outpri = outpri2 = 0; |
outpri = outpri2 = 0; |
mutex_enter(&proclist_mutex); /* XXXSMP */ |
|
|
restart: |
|
mutex_enter(&proclist_lock); |
LIST_FOREACH(l, &alllwp, l_list) { |
LIST_FOREACH(l, &alllwp, l_list) { |
KASSERT(l->l_proc != NULL); |
KASSERT(l->l_proc != NULL); |
lwp_lock(l); |
if (!mutex_tryenter(&l->l_swaplock)) |
|
continue; |
if (!swappable(l)) { |
if (!swappable(l)) { |
lwp_unlock(l); |
mutex_exit(&l->l_swaplock); |
continue; |
continue; |
} |
} |
switch (l->l_stat) { |
switch (l->l_stat) { |
Line 630 uvm_swapout_threads(void) |
|
Line 703 uvm_swapout_threads(void) |
|
case LSSLEEP: |
case LSSLEEP: |
case LSSTOP: |
case LSSTOP: |
if (l->l_slptime >= maxslp) { |
if (l->l_slptime >= maxslp) { |
/* uvm_swapout() will release the lock. */ |
mutex_exit(&proclist_lock); |
uvm_swapout(l); |
uvm_swapout(l); |
|
/* |
|
* Locking in the wrong direction - |
|
* try to prevent the LWP from exiting. |
|
*/ |
|
gotit = mutex_tryenter(&proclist_lock); |
|
mutex_exit(&l->l_swaplock); |
didswap++; |
didswap++; |
|
if (!gotit) |
|
goto restart; |
continue; |
continue; |
} else if (l->l_slptime > outpri) { |
} else if (l->l_slptime > outpri) { |
outl = l; |
outl = l; |
Line 640 uvm_swapout_threads(void) |
|
Line 721 uvm_swapout_threads(void) |
|
} |
} |
break; |
break; |
} |
} |
lwp_unlock(l); |
mutex_exit(&l->l_swaplock); |
} |
} |
|
|
/* |
/* |
* If we didn't get rid of any real duds, toss out the next most |
* If we didn't get rid of any real duds, toss out the next most |
* likely sleeping/stopped or running candidate. We only do this |
* likely sleeping/stopped or running candidate. We only do this |
Line 656 uvm_swapout_threads(void) |
|
Line 738 uvm_swapout_threads(void) |
|
printf("swapout_threads: no duds, try procp %p\n", l); |
printf("swapout_threads: no duds, try procp %p\n", l); |
#endif |
#endif |
if (l) { |
if (l) { |
/* uvm_swapout() will release the lock. */ |
mutex_enter(&l->l_swaplock); |
lwp_lock(l); |
mutex_exit(&proclist_lock); |
uvm_swapout(l); |
if (swappable(l)) |
|
uvm_swapout(l); |
|
mutex_exit(&l->l_swaplock); |
|
return; |
} |
} |
} |
} |
|
|
mutex_exit(&proclist_mutex); |
mutex_exit(&proclist_lock); |
|
|
} |
} |
|
|
/* |
/* |
Line 671 uvm_swapout_threads(void) |
|
Line 755 uvm_swapout_threads(void) |
|
* |
* |
* - currently "swapout" means "unwire U-area" and "pmap_collect()" |
* - currently "swapout" means "unwire U-area" and "pmap_collect()" |
* the pmap. |
* the pmap. |
* - must be called with the LWP locked, and will release the lock. |
* - must be called with l->l_swaplock held. |
* - XXXCDC: should deactivate all process' private anonymous memory |
* - XXXCDC: should deactivate all process' private anonymous memory |
*/ |
*/ |
|
|
Line 681 uvm_swapout(struct lwp *l) |
|
Line 765 uvm_swapout(struct lwp *l) |
|
vaddr_t addr; |
vaddr_t addr; |
struct proc *p = l->l_proc; |
struct proc *p = l->l_proc; |
|
|
LOCK_ASSERT(lwp_locked(l, NULL)); |
KASSERT(mutex_owned(&l->l_swaplock)); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
if (swapdebug & SDB_SWAPOUT) |
if (swapdebug & SDB_SWAPOUT) |
Line 693 uvm_swapout(struct lwp *l) |
|
Line 777 uvm_swapout(struct lwp *l) |
|
/* |
/* |
* Mark it as (potentially) swapped out. |
* Mark it as (potentially) swapped out. |
*/ |
*/ |
if (l->l_stat == LSONPROC) { |
lwp_lock(l); |
|
if (!swappable(l)) { |
KDASSERT(l->l_cpu != curcpu()); |
KDASSERT(l->l_cpu != curcpu()); |
lwp_unlock(l); |
lwp_unlock(l); |
return; |
return; |
Line 701 uvm_swapout(struct lwp *l) |
|
Line 786 uvm_swapout(struct lwp *l) |
|
l->l_flag &= ~LW_INMEM; |
l->l_flag &= ~LW_INMEM; |
l->l_swtime = 0; |
l->l_swtime = 0; |
if (l->l_stat == LSRUN) |
if (l->l_stat == LSRUN) |
remrunqueue(l); |
sched_dequeue(l); |
lwp_unlock(l); |
lwp_unlock(l); |
p->p_stats->p_ru.ru_nswap++; /* XXXSMP */ |
p->p_stats->p_ru.ru_nswap++; /* XXXSMP */ |
++uvmexp.swapouts; |
++uvmexp.swapouts; |
|
|
mutex_exit(&proclist_mutex); /* XXXSMP */ |
|
|
|
/* |
/* |
* Do any machine-specific actions necessary before swapout. |
* Do any machine-specific actions necessary before swapout. |
* This can include saving floating point state, etc. |
* This can include saving floating point state, etc. |
Line 720 uvm_swapout(struct lwp *l) |
|
Line 803 uvm_swapout(struct lwp *l) |
|
addr = USER_TO_UAREA(l->l_addr); |
addr = USER_TO_UAREA(l->l_addr); |
uvm_fault_unwire(kernel_map, addr, addr + USPACE); /* !L_INMEM */ |
uvm_fault_unwire(kernel_map, addr, addr + USPACE); /* !L_INMEM */ |
pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map)); |
pmap_collect(vm_map_pmap(&p->p_vmspace->vm_map)); |
|
} |
|
|
|
/* |
|
* uvm_lwp_hold: prevent lwp "l" from being swapped out, and bring |
|
* back into memory if it is currently swapped. |
|
*/ |
|
|
|
void |
|
uvm_lwp_hold(struct lwp *l) |
|
{ |
|
|
|
/* XXXSMP mutex_enter(&l->l_swaplock); */ |
|
if (l->l_holdcnt++ == 0 && (l->l_flag & LW_INMEM) == 0) |
|
uvm_swapin(l); |
|
/* XXXSMP mutex_exit(&l->l_swaplock); */ |
|
} |
|
|
|
/* |
|
* uvm_lwp_rele: release a hold on lwp "l". when the holdcount |
|
* drops to zero, it's eligable to be swapped. |
|
*/ |
|
|
|
void |
|
uvm_lwp_rele(struct lwp *l) |
|
{ |
|
|
|
KASSERT(l->l_holdcnt != 0); |
|
|
mutex_enter(&proclist_mutex); /* XXXSMP */ |
/* XXXSMP mutex_enter(&l->l_swaplock); */ |
|
l->l_holdcnt--; |
|
/* XXXSMP mutex_exit(&l->l_swaplock); */ |
} |
} |
|
|
#ifdef COREDUMP |
#ifdef COREDUMP |