Reverse r196640 and r196644 for now.
This commit is contained in:
parent
b6b2d1bf88
commit
f25fa6abb2
@ -119,6 +119,9 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
|
||||
#ifdef __XSCALE__
|
||||
#ifndef CPU_XSCALE_CORE3
|
||||
pmap_use_minicache(td2->td_kstack, td2->td_kstack_pages * PAGE_SIZE);
|
||||
if (td2->td_altkstack)
|
||||
pmap_use_minicache(td2->td_altkstack, td2->td_altkstack_pages *
|
||||
PAGE_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
td2->td_pcb = pcb2;
|
||||
|
@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_kdtrace.h"
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_kstack_pages.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -277,29 +276,25 @@ fork1(td, flags, pages, procp)
|
||||
|
||||
mem_charged = 0;
|
||||
vm2 = NULL;
|
||||
if (pages == 0)
|
||||
pages = KSTACK_PAGES;
|
||||
/* Allocate new proc. */
|
||||
newproc = uma_zalloc(proc_zone, M_WAITOK);
|
||||
td2 = FIRST_THREAD_IN_PROC(newproc);
|
||||
if (td2 == NULL) {
|
||||
td2 = thread_alloc(pages);
|
||||
if (TAILQ_EMPTY(&newproc->p_threads)) {
|
||||
td2 = thread_alloc();
|
||||
if (td2 == NULL) {
|
||||
error = ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
proc_linkup(newproc, td2);
|
||||
} else {
|
||||
if (td2->td_kstack == 0 || td2->td_kstack_pages != pages) {
|
||||
if (td2->td_kstack != 0)
|
||||
vm_thread_dispose(td2);
|
||||
if (!thread_alloc_stack(td2, pages)) {
|
||||
error = ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
} else
|
||||
td2 = FIRST_THREAD_IN_PROC(newproc);
|
||||
|
||||
/* Allocate and switch to an alternate kstack if specified. */
|
||||
if (pages != 0) {
|
||||
if (!vm_thread_new_altkstack(td2, pages)) {
|
||||
error = ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & RFMEM) == 0) {
|
||||
vm2 = vmspace_fork(p1->p_vmspace, &mem_charged);
|
||||
if (vm2 == NULL) {
|
||||
|
@ -256,7 +256,7 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p,
|
||||
}
|
||||
|
||||
/* Initialize our new td */
|
||||
newtd = thread_alloc(pages);
|
||||
newtd = thread_alloc();
|
||||
if (newtd == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
@ -282,6 +282,9 @@ kthread_add(void (*func)(void *), void *arg, struct proc *p,
|
||||
|
||||
newtd->td_pflags |= TDP_KTHREAD;
|
||||
newtd->td_ucred = crhold(p->p_ucred);
|
||||
/* Allocate and switch to an alternate kstack if specified. */
|
||||
if (pages != 0)
|
||||
vm_thread_new_altkstack(newtd, pages);
|
||||
|
||||
/* this code almost the same as create_thread() in kern_thr.c */
|
||||
PROC_LOCK(p);
|
||||
|
@ -203,6 +203,14 @@ proc_dtor(void *mem, int size, void *arg)
|
||||
#endif
|
||||
/* Free all OSD associated to this thread. */
|
||||
osd_thread_exit(td);
|
||||
|
||||
/* Dispose of an alternate kstack, if it exists.
|
||||
* XXX What if there are more than one thread in the proc?
|
||||
* The first thread in the proc is special and not
|
||||
* freed, so you gotta do this here.
|
||||
*/
|
||||
if (((p->p_flag & P_KTHREAD) != 0) && (td->td_altkstack != 0))
|
||||
vm_thread_dispose_altkstack(td);
|
||||
}
|
||||
EVENTHANDLER_INVOKE(process_dtor, p);
|
||||
if (p->p_ksi != NULL)
|
||||
@ -759,6 +767,8 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
|
||||
FOREACH_THREAD_IN_PROC(p, td0) {
|
||||
if (!TD_IS_SWAPPED(td0))
|
||||
kp->ki_rssize += td0->td_kstack_pages;
|
||||
if (td0->td_altkstack_obj != NULL)
|
||||
kp->ki_rssize += td0->td_altkstack_pages;
|
||||
}
|
||||
kp->ki_swrss = vm->vm_swrss;
|
||||
kp->ki_tsize = vm->vm_tsize;
|
||||
|
@ -176,7 +176,7 @@ create_thread(struct thread *td, mcontext_t *ctx,
|
||||
}
|
||||
|
||||
/* Initialize our td */
|
||||
newtd = thread_alloc(0);
|
||||
newtd = thread_alloc();
|
||||
if (newtd == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
|
@ -283,7 +283,7 @@ thread_reap(void)
|
||||
* Allocate a thread.
|
||||
*/
|
||||
struct thread *
|
||||
thread_alloc(int pages)
|
||||
thread_alloc(void)
|
||||
{
|
||||
struct thread *td;
|
||||
|
||||
@ -291,7 +291,7 @@ thread_alloc(int pages)
|
||||
|
||||
td = (struct thread *)uma_zalloc(thread_zone, M_WAITOK);
|
||||
KASSERT(td->td_kstack == 0, ("thread_alloc got thread with kstack"));
|
||||
if (!vm_thread_new(td, pages)) {
|
||||
if (!vm_thread_new(td, 0)) {
|
||||
uma_zfree(thread_zone, td);
|
||||
return (NULL);
|
||||
}
|
||||
@ -299,17 +299,6 @@ thread_alloc(int pages)
|
||||
return (td);
|
||||
}
|
||||
|
||||
int
|
||||
thread_alloc_stack(struct thread *td, int pages)
|
||||
{
|
||||
|
||||
KASSERT(td->td_kstack == 0,
|
||||
("thread_alloc_stack called on a thread with kstack"));
|
||||
if (!vm_thread_new(td, pages))
|
||||
return (0);
|
||||
cpu_thread_alloc(td);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deallocate a thread.
|
||||
@ -323,6 +312,8 @@ thread_free(struct thread *td)
|
||||
cpuset_rel(td->td_cpuset);
|
||||
td->td_cpuset = NULL;
|
||||
cpu_thread_free(td);
|
||||
if (td->td_altkstack != 0)
|
||||
vm_thread_dispose_altkstack(td);
|
||||
if (td->td_kstack != 0)
|
||||
vm_thread_dispose(td);
|
||||
uma_zfree(thread_zone, td);
|
||||
|
@ -267,6 +267,9 @@ struct thread {
|
||||
struct vm_object *td_kstack_obj;/* (a) Kstack object. */
|
||||
vm_offset_t td_kstack; /* (a) Kernel VA of kstack. */
|
||||
int td_kstack_pages; /* (a) Size of the kstack. */
|
||||
struct vm_object *td_altkstack_obj;/* (a) Alternate kstack object. */
|
||||
vm_offset_t td_altkstack; /* (a) Kernel VA of alternate kstack. */
|
||||
int td_altkstack_pages; /* (a) Size of alternate kstack. */
|
||||
volatile u_int td_critnest; /* (k*) Critical section nest level. */
|
||||
struct mdthread td_md; /* (k) Any machine-dependent fields. */
|
||||
struct td_sched *td_sched; /* (*) Scheduler-specific data. */
|
||||
@ -847,8 +850,7 @@ void cpu_thread_exit(struct thread *);
|
||||
void cpu_thread_free(struct thread *);
|
||||
void cpu_thread_swapin(struct thread *);
|
||||
void cpu_thread_swapout(struct thread *);
|
||||
struct thread *thread_alloc(int pages);
|
||||
int thread_alloc_stack(struct thread *, int pages);
|
||||
struct thread *thread_alloc(void);
|
||||
void thread_exit(void) __dead2;
|
||||
void thread_free(struct thread *td);
|
||||
void thread_link(struct thread *td, struct proc *p);
|
||||
|
@ -80,7 +80,9 @@ int vm_fault_quick(caddr_t v, int prot);
|
||||
struct sf_buf *vm_imgact_map_page(vm_object_t object, vm_ooffset_t offset);
|
||||
void vm_imgact_unmap_page(struct sf_buf *sf);
|
||||
void vm_thread_dispose(struct thread *td);
|
||||
void vm_thread_dispose_altkstack(struct thread *td);
|
||||
int vm_thread_new(struct thread *td, int pages);
|
||||
int vm_thread_new_altkstack(struct thread *td, int pages);
|
||||
void vm_thread_swapin(struct thread *td);
|
||||
void vm_thread_swapout(struct thread *td);
|
||||
#endif /* _KERNEL */
|
||||
|
138
sys/vm/vm_glue.c
138
sys/vm/vm_glue.c
@ -77,7 +77,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sx.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sys/eventhandler.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ktr.h>
|
||||
#include <sys/unistd.h>
|
||||
@ -309,20 +308,6 @@ vm_imgact_unmap_page(struct sf_buf *sf)
|
||||
vm_page_unlock_queues();
|
||||
}
|
||||
|
||||
struct kstack_cache_entry {
|
||||
vm_object_t ksobj;
|
||||
struct kstack_cache_entry *next_ks_entry;
|
||||
};
|
||||
|
||||
static struct kstack_cache_entry *kstack_cache;
|
||||
static int kstack_cache_size = 128;
|
||||
static int kstacks;
|
||||
static struct mtx kstack_cache_mtx;
|
||||
SYSCTL_INT(_vm, OID_AUTO, kstack_cache_size, CTLFLAG_RW, &kstack_cache_size, 0,
|
||||
"");
|
||||
SYSCTL_INT(_vm, OID_AUTO, kstacks, CTLFLAG_RD, &kstacks, 0,
|
||||
"");
|
||||
|
||||
#ifndef KSTACK_MAX_PAGES
|
||||
#define KSTACK_MAX_PAGES 32
|
||||
#endif
|
||||
@ -338,7 +323,6 @@ vm_thread_new(struct thread *td, int pages)
|
||||
vm_object_t ksobj;
|
||||
vm_offset_t ks;
|
||||
vm_page_t m, ma[KSTACK_MAX_PAGES];
|
||||
struct kstack_cache_entry *ks_ce;
|
||||
int i;
|
||||
|
||||
/* Bounds check */
|
||||
@ -346,22 +330,6 @@ vm_thread_new(struct thread *td, int pages)
|
||||
pages = KSTACK_PAGES;
|
||||
else if (pages > KSTACK_MAX_PAGES)
|
||||
pages = KSTACK_MAX_PAGES;
|
||||
|
||||
if (pages == KSTACK_PAGES) {
|
||||
mtx_lock(&kstack_cache_mtx);
|
||||
if (kstack_cache != NULL) {
|
||||
ks_ce = kstack_cache;
|
||||
kstack_cache = ks_ce->next_ks_entry;
|
||||
mtx_unlock(&kstack_cache_mtx);
|
||||
|
||||
td->td_kstack_obj = ks_ce->ksobj;
|
||||
td->td_kstack = (vm_offset_t)ks_ce;
|
||||
td->td_kstack_pages = KSTACK_PAGES;
|
||||
return (1);
|
||||
}
|
||||
mtx_unlock(&kstack_cache_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate an object for the kstack.
|
||||
*/
|
||||
@ -377,8 +345,7 @@ vm_thread_new(struct thread *td, int pages)
|
||||
vm_object_deallocate(ksobj);
|
||||
return (0);
|
||||
}
|
||||
|
||||
atomic_add_int(&kstacks, 1);
|
||||
|
||||
if (KSTACK_GUARD_PAGES != 0) {
|
||||
pmap_qremove(ks, KSTACK_GUARD_PAGES);
|
||||
ks += KSTACK_GUARD_PAGES * PAGE_SIZE;
|
||||
@ -409,13 +376,20 @@ vm_thread_new(struct thread *td, int pages)
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages)
|
||||
/*
|
||||
* Dispose of a thread's kernel stack.
|
||||
*/
|
||||
void
|
||||
vm_thread_dispose(struct thread *td)
|
||||
{
|
||||
vm_object_t ksobj;
|
||||
vm_offset_t ks;
|
||||
vm_page_t m;
|
||||
int i;
|
||||
int i, pages;
|
||||
|
||||
atomic_add_int(&kstacks, -1);
|
||||
pages = td->td_kstack_pages;
|
||||
ksobj = td->td_kstack_obj;
|
||||
ks = td->td_kstack;
|
||||
pmap_qremove(ks, pages);
|
||||
VM_OBJECT_LOCK(ksobj);
|
||||
for (i = 0; i < pages; i++) {
|
||||
@ -431,66 +405,9 @@ vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages)
|
||||
vm_object_deallocate(ksobj);
|
||||
kmem_free(kernel_map, ks - (KSTACK_GUARD_PAGES * PAGE_SIZE),
|
||||
(pages + KSTACK_GUARD_PAGES) * PAGE_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispose of a thread's kernel stack.
|
||||
*/
|
||||
void
|
||||
vm_thread_dispose(struct thread *td)
|
||||
{
|
||||
vm_object_t ksobj;
|
||||
vm_offset_t ks;
|
||||
struct kstack_cache_entry *ks_ce;
|
||||
int pages;
|
||||
|
||||
pages = td->td_kstack_pages;
|
||||
ksobj = td->td_kstack_obj;
|
||||
ks = td->td_kstack;
|
||||
if (pages == KSTACK_PAGES && kstacks <= kstack_cache_size) {
|
||||
ks_ce = (struct kstack_cache_entry *)ks;
|
||||
ks_ce->ksobj = ksobj;
|
||||
mtx_lock(&kstack_cache_mtx);
|
||||
ks_ce->next_ks_entry = ks_ce;
|
||||
kstack_cache = ks_ce;
|
||||
mtx_unlock(&kstack_cache_mtx);
|
||||
return;
|
||||
}
|
||||
vm_thread_stack_dispose(ksobj, ks, pages);
|
||||
td->td_kstack = 0;
|
||||
td->td_kstack_pages = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
vm_thread_stack_lowmem(void *nulll)
|
||||
{
|
||||
struct kstack_cache_entry *ks_ce, *ks_ce1;
|
||||
|
||||
mtx_lock(&kstack_cache_mtx);
|
||||
ks_ce = kstack_cache;
|
||||
kstack_cache = NULL;
|
||||
mtx_unlock(&kstack_cache_mtx);
|
||||
|
||||
while (ks_ce != NULL) {
|
||||
ks_ce1 = ks_ce;
|
||||
ks_ce = ks_ce->next_ks_entry;
|
||||
|
||||
vm_thread_stack_dispose(ks_ce1->ksobj, (vm_offset_t)ks_ce1,
|
||||
KSTACK_PAGES);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
kstack_cache_init(void *nulll)
|
||||
{
|
||||
|
||||
EVENTHANDLER_REGISTER(vm_lowmem, vm_thread_stack_lowmem, NULL,
|
||||
EVENTHANDLER_PRI_ANY);
|
||||
}
|
||||
|
||||
MTX_SYSINIT(kstack_cache, &kstack_cache_mtx, "kstkch", MTX_DEF);
|
||||
SYSINIT(vm_kstacks, SI_SUB_KTHREAD_INIT, SI_ORDER_ANY, kstack_cache_init, NULL);
|
||||
|
||||
/*
|
||||
* Allow a thread's kernel stack to be paged out.
|
||||
*/
|
||||
@ -550,6 +467,37 @@ vm_thread_swapin(struct thread *td)
|
||||
cpu_thread_swapin(td);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a variable-sized alternate kstack.
|
||||
*/
|
||||
int
|
||||
vm_thread_new_altkstack(struct thread *td, int pages)
|
||||
{
|
||||
|
||||
td->td_altkstack = td->td_kstack;
|
||||
td->td_altkstack_obj = td->td_kstack_obj;
|
||||
td->td_altkstack_pages = td->td_kstack_pages;
|
||||
|
||||
return (vm_thread_new(td, pages));
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the original kstack.
|
||||
*/
|
||||
void
|
||||
vm_thread_dispose_altkstack(struct thread *td)
|
||||
{
|
||||
|
||||
vm_thread_dispose(td);
|
||||
|
||||
td->td_kstack = td->td_altkstack;
|
||||
td->td_kstack_obj = td->td_altkstack_obj;
|
||||
td->td_kstack_pages = td->td_altkstack_pages;
|
||||
td->td_altkstack = 0;
|
||||
td->td_altkstack_obj = NULL;
|
||||
td->td_altkstack_pages = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement fork's actions on an address space.
|
||||
* Here we arrange for the address space to be copied or referenced,
|
||||
|
Loading…
Reference in New Issue
Block a user