diff options
author | scottl <scottl@FreeBSD.org> | 2002-10-02 07:44:29 +0000 |
---|---|---|
committer | scottl <scottl@FreeBSD.org> | 2002-10-02 07:44:29 +0000 |
commit | 3a150bca9cc1b9ca767ca73d95fd54081237210b (patch) | |
tree | 0a9cc28f7570a42ae4e5df4cfc55dee42c36d9d8 /sys/alpha/alpha/pmap.c | |
parent | 734ef490b8cfe3acc5f45425a63fac5e7c5173a3 (diff) | |
download | FreeBSD-src-3a150bca9cc1b9ca767ca73d95fd54081237210b.zip FreeBSD-src-3a150bca9cc1b9ca767ca73d95fd54081237210b.tar.gz |
Some kernel threads try to do significant work, and the default KSTACK_PAGES
doesn't give them enough stack to do much before blowing away the pcb.
This adds MI and MD code to allow the allocation of an alternate kstack
who's size can be speficied when calling kthread_create. Passing the
value 0 prevents the alternate kstack from being created. Note that the
ia64 MD code is missing for now, and PowerPC was only partially written
due to the pmap.c being incomplete there.
Though this patch does not modify anything to make use of the alternate
kstack, acpi and usb are good candidates.
Reviewed by: jake, peter, jhb
Diffstat (limited to 'sys/alpha/alpha/pmap.c')
-rw-r--r-- | sys/alpha/alpha/pmap.c | 71 |
1 files changed, 61 insertions, 10 deletions
diff --git a/sys/alpha/alpha/pmap.c b/sys/alpha/alpha/pmap.c index 72db2bf..df7f181 100644 --- a/sys/alpha/alpha/pmap.c +++ b/sys/alpha/alpha/pmap.c @@ -898,12 +898,16 @@ retry: return m; } +#ifndef KSTACK_MAX_PAGES +#define KSTACK_MAX_PAGES 32 +#endif + /* * Create the kernel stack for a new thread. * This routine directly affects the fork perf for a process and thread. */ void -pmap_new_thread(struct thread *td) +pmap_new_thread(struct thread *td, int pages) { int i; vm_object_t ksobj; @@ -911,15 +915,21 @@ pmap_new_thread(struct thread *td) vm_page_t m; pt_entry_t *ptek, oldpte; + /* Bounds check */ + if (pages <= 1) + pages = KSTACK_PAGES; + else if (pages > KSTACK_MAX_PAGES) + pages = KSTACK_MAX_PAGES; + /* * allocate object for the kstack */ - ksobj = vm_object_allocate(OBJT_DEFAULT, KSTACK_PAGES); + ksobj = vm_object_allocate(OBJT_DEFAULT, pages); td->td_kstack_obj = ksobj; #ifdef KSTACK_GUARD /* get a kernel virtual address for the kstack for this thread */ - ks = kmem_alloc_nofault(kernel_map, (KSTACK_PAGES + 1) * PAGE_SIZE); + ks = kmem_alloc_nofault(kernel_map, (pages + 1) * PAGE_SIZE); if (ks == NULL) panic("pmap_new_thread: kstack allocation failed"); @@ -935,17 +945,23 @@ pmap_new_thread(struct thread *td) ptek++; #else /* get a kernel virtual address for the kstack for this thread */ - ks = kmem_alloc_nofault(kernel_map, KSTACK_PAGES * PAGE_SIZE); + ks = kmem_alloc_nofault(kernel_map, pages * PAGE_SIZE); if (ks == NULL) panic("pmap_new_thread: kstack allocation failed"); td->td_kstack = ks; ptek = vtopte(ks); #endif /* + * Knowing the number of pages allocated is useful when you + * want to deallocate them. + */ + td->td_kstack_pages = pages; + + /* * For the length of the stack, link in a real page of ram for each * page of stack. */ - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages; i++) { /* * Get a kernel stack page */ @@ -976,15 +992,17 @@ pmap_dispose_thread(td) struct thread *td; { int i; + int pages; vm_object_t ksobj; vm_offset_t ks; vm_page_t m; pt_entry_t *ptek; + pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; ks = td->td_kstack; ptek = vtopte(ks); - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages; i++) { m = vm_page_lookup(ksobj, i); if (m == NULL) panic("pmap_dispose_thread: kstack already missing?"); @@ -1002,14 +1020,43 @@ pmap_dispose_thread(td) * address map. */ #ifdef KSTACK_GUARD - kmem_free(kernel_map, ks - PAGE_SIZE, (KSTACK_PAGES + 1) * PAGE_SIZE); + kmem_free(kernel_map, ks - PAGE_SIZE, (pages + 1) * PAGE_SIZE); #else - kmem_free(kernel_map, ks, KSTACK_PAGES * PAGE_SIZE); + kmem_free(kernel_map, ks, pages * PAGE_SIZE); #endif vm_object_deallocate(ksobj); } /* + * Set up a variable sized alternate kstack. + */ +void +pmap_new_altkstack(struct thread *td, int pages) +{ + /* shuffle the original stack */ + td->td_altkstack_obj = td->td_kstack_obj; + td->td_altkstack = td->td_kstack; + td->td_altkstack_pages = td->td_kstack_pages; + + pmap_new_thread(td, pages); +} + +void +pmap_dispose_altkstack(td) + struct thread *td; +{ + pmap_dispose_thread(td); + + /* restore the original kstack */ + 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; +} + +/* * Allow the kernel stack for a thread to be prejudicially paged out. */ void @@ -1017,6 +1064,7 @@ pmap_swapout_thread(td) struct thread *td; { int i; + int pages; vm_object_t ksobj; vm_offset_t ks; vm_page_t m; @@ -1026,9 +1074,10 @@ pmap_swapout_thread(td) */ alpha_fpstate_save(td, 1); + pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; ks = td->td_kstack; - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages; i++) { m = vm_page_lookup(ksobj, i); if (m == NULL) panic("pmap_swapout_thread: kstack already missing?"); @@ -1048,13 +1097,15 @@ pmap_swapin_thread(td) struct thread *td; { int i, rv; + int pages; vm_object_t ksobj; vm_offset_t ks; vm_page_t m; + pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; ks = td->td_kstack; - for (i = 0; i < KSTACK_PAGES; i++) { + for (i = 0; i < pages; i++) { m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY); pmap_kenter(ks + i * PAGE_SIZE, VM_PAGE_TO_PHYS(m)); if (m->valid != VM_PAGE_BITS_ALL) { |