DragonFly kernel List (threaded) for 2010-02
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]
trap_pfault growstack vs vm_fault ordering?
Hi,
Currently trap_pfault for each of the three DragonFly platforms
attempts to grow the stack region (via growstack()) before attempting
vm_fault. For any faults not in stack growth regions, this will result
in lots of work (3 crit_enter/crit_exit pairs, a number of zone
allocations). Would it be worth moving the stack growth call into
vm_fault, after the vm_map_lookup call?
Here is a patch that does this:
(to sys/platform/<T>/<A>/trap.c):
--- trap.c.orig 2010-02-26 06:17:34 -0800
+++ trap.c 2010-02-26 06:17:54 -0800
@@ -989,21 +989,6 @@
PHOLD(lp->lwp_proc);
- /*
- * Grow the stack if necessary
- */
- /* grow_stack returns false only if va falls into
- * a growable stack region and the stack growth
- * fails. It returns true if va was not within
- * a growable stack region, or if the stack
- * growth succeeded.
- */
- if (!grow_stack(lp->lwp_proc, va)) {
- rv = KERN_FAILURE;
- PRELE(lp->lwp_proc);
- goto nogo;
- }
-
/*
* Issue fault
*/
fault_flags = 0;
To vm/vm_fault.c:
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 0fae064..7fd0998 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -223,12 +223,14 @@ vm_fault(vm_map_t map, vm_offset_t vaddr,
vm_prot_t fault_type, int fault_flags)
int result;
vm_pindex_t first_pindex;
struct faultstate fs;
+ int growstack;
mycpu->gd_cnt.v_vm_faults++;
fs.didlimit = 0;
fs.hardfault = 0;
fs.fault_flags = fault_flags;
+ growstack = 1;
RetryFault:
/*
@@ -256,10 +258,21 @@ RetryFault:
* to do a user wiring we have more work to do.
*/
if (result != KERN_SUCCESS) {
- if (result != KERN_PROTECTION_FAILURE)
- return result;
- if ((fs.fault_flags & VM_FAULT_WIRE_MASK) != VM_FAULT_USER_WIRE)
- return result;
+ if (result != KERN_PROTECTION_FAILURE ||
+ (fs.fault_flags & VM_FAULT_WIRE_MASK) != VM_FAULT_USER_WIRE)
+ {
+ if (growstack &&
+ result == KERN_INVALID_ADDRESS &&
+ map != &kernel_map &&
+ curproc != NULL) {
+ result = vm_map_growstack(curproc, vaddr);
+ if (result != KERN_SUCCESS)
+ return (KERN_FAILURE);
+ growstack = 0;
+ goto RetryFault;
+ }
+ return (result);
+ }
/*
* If we are user-wiring a r/w segment, and it is COW, then
I'm not currently setup to measure the speed differences or the
distribution of faults, to know whether this is a good idea... does
this seem reasonable?
Thanks,
-- vs
[
Date Prev][
Date Next]
[
Thread Prev][
Thread Next]
[
Date Index][
Thread Index]