diff options
author | alc <alc@FreeBSD.org> | 1999-06-17 00:39:26 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 1999-06-17 00:39:26 +0000 |
commit | 9fb63b7080a91371dcc62c3cf600d5828dd4d2b3 (patch) | |
tree | 5c6b43e1b86c4d51c152cb4117bead42b91521f2 /sys/vm/vm_map.c | |
parent | bdb6bd306668664987b44d9b695607419b006dd2 (diff) | |
download | FreeBSD-src-9fb63b7080a91371dcc62c3cf600d5828dd4d2b3.zip FreeBSD-src-9fb63b7080a91371dcc62c3cf600d5828dd4d2b3.tar.gz |
Move vm_map_stack and vm_map_growstack after the definition
of the vm_map_clip_end macro. (The next commit will modify
vm_map_stack and vm_map_growstack to use vm_map_clip_end.)
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r-- | sys/vm/vm_map.c | 408 |
1 files changed, 204 insertions, 204 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index e8dc45c..f20a29e 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $Id: vm_map.c,v 1.166 1999/06/12 23:10:38 alc Exp $ + * $Id: vm_map.c,v 1.167 1999/06/17 00:27:39 alc Exp $ */ /* @@ -556,209 +556,6 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset, return (KERN_SUCCESS); } -int -vm_map_stack (vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, - vm_prot_t prot, vm_prot_t max, int cow) -{ - vm_map_entry_t prev_entry; - vm_map_entry_t new_stack_entry; - vm_size_t init_ssize; - int rv; - - if (VM_MIN_ADDRESS > 0 && addrbos < VM_MIN_ADDRESS) - return (KERN_NO_SPACE); - - if (max_ssize < SGROWSIZ) - init_ssize = max_ssize; - else - init_ssize = SGROWSIZ; - - vm_map_lock(map); - - /* If addr is already mapped, no go */ - if (vm_map_lookup_entry(map, addrbos, &prev_entry)) { - vm_map_unlock(map); - return (KERN_NO_SPACE); - } - - /* If we can't accomodate max_ssize in the current mapping, - * no go. However, we need to be aware that subsequent user - * mappings might map into the space we have reserved for - * stack, and currently this space is not protected. - * - * Hopefully we will at least detect this condition - * when we try to grow the stack. - */ - if ((prev_entry->next != &map->header) && - (prev_entry->next->start < addrbos + max_ssize)) { - vm_map_unlock(map); - return (KERN_NO_SPACE); - } - - /* We initially map a stack of only init_ssize. We will - * grow as needed later. Since this is to be a grow - * down stack, we map at the top of the range. - * - * Note: we would normally expect prot and max to be - * VM_PROT_ALL, and cow to be 0. Possibly we should - * eliminate these as input parameters, and just - * pass these values here in the insert call. - */ - rv = vm_map_insert(map, NULL, 0, addrbos + max_ssize - init_ssize, - addrbos + max_ssize, prot, max, cow); - - /* Now set the avail_ssize amount */ - if (rv == KERN_SUCCESS){ - new_stack_entry = prev_entry->next; - if (new_stack_entry->end != addrbos + max_ssize || - new_stack_entry->start != addrbos + max_ssize - init_ssize) - panic ("Bad entry start/end for new stack entry"); - else - new_stack_entry->avail_ssize = max_ssize - init_ssize; - } - - vm_map_unlock(map); - return (rv); -} - -/* Attempts to grow a vm stack entry. Returns KERN_SUCCESS if the - * desired address is already mapped, or if we successfully grow - * the stack. Also returns KERN_SUCCESS if addr is outside the - * stack range (this is strange, but preserves compatibility with - * the grow function in vm_machdep.c). - */ -int -vm_map_growstack (struct proc *p, vm_offset_t addr) -{ - vm_map_entry_t prev_entry; - vm_map_entry_t stack_entry; - vm_map_entry_t new_stack_entry; - struct vmspace *vm = p->p_vmspace; - vm_map_t map = &vm->vm_map; - vm_offset_t end; - int grow_amount; - int rv; - int is_procstack; -Retry: - vm_map_lock_read(map); - - /* If addr is already in the entry range, no need to grow.*/ - if (vm_map_lookup_entry(map, addr, &prev_entry)) { - vm_map_unlock_read(map); - return (KERN_SUCCESS); - } - - if ((stack_entry = prev_entry->next) == &map->header) { - vm_map_unlock_read(map); - return (KERN_SUCCESS); - } - if (prev_entry == &map->header) - end = stack_entry->start - stack_entry->avail_ssize; - else - end = prev_entry->end; - - /* This next test mimics the old grow function in vm_machdep.c. - * It really doesn't quite make sense, but we do it anyway - * for compatibility. - * - * If not growable stack, return success. This signals the - * caller to proceed as he would normally with normal vm. - */ - if (stack_entry->avail_ssize < 1 || - addr >= stack_entry->start || - addr < stack_entry->start - stack_entry->avail_ssize) { - vm_map_unlock_read(map); - return (KERN_SUCCESS); - } - - /* Find the minimum grow amount */ - grow_amount = roundup (stack_entry->start - addr, PAGE_SIZE); - if (grow_amount > stack_entry->avail_ssize) { - vm_map_unlock_read(map); - return (KERN_NO_SPACE); - } - - /* If there is no longer enough space between the entries - * nogo, and adjust the available space. Note: this - * should only happen if the user has mapped into the - * stack area after the stack was created, and is - * probably an error. - * - * This also effectively destroys any guard page the user - * might have intended by limiting the stack size. - */ - if (grow_amount > stack_entry->start - end) { - if (vm_map_lock_upgrade(map)) - goto Retry; - - stack_entry->avail_ssize = stack_entry->start - end; - - vm_map_unlock(map); - return (KERN_NO_SPACE); - } - - is_procstack = addr >= (vm_offset_t)vm->vm_maxsaddr; - - /* If this is the main process stack, see if we're over the - * stack limit. - */ - if (is_procstack && (vm->vm_ssize + grow_amount > - p->p_rlimit[RLIMIT_STACK].rlim_cur)) { - vm_map_unlock_read(map); - return (KERN_NO_SPACE); - } - - /* Round up the grow amount modulo SGROWSIZ */ - grow_amount = roundup (grow_amount, SGROWSIZ); - if (grow_amount > stack_entry->avail_ssize) { - grow_amount = stack_entry->avail_ssize; - } - if (is_procstack && (vm->vm_ssize + grow_amount > - p->p_rlimit[RLIMIT_STACK].rlim_cur)) { - grow_amount = p->p_rlimit[RLIMIT_STACK].rlim_cur - - vm->vm_ssize; - } - - if (vm_map_lock_upgrade(map)) - goto Retry; - - /* Get the preliminary new entry start value */ - addr = stack_entry->start - grow_amount; - - /* If this puts us into the previous entry, cut back our growth - * to the available space. Also, see the note above. - */ - if (addr < end) { - stack_entry->avail_ssize = stack_entry->start - end; - addr = end; - } - - rv = vm_map_insert(map, NULL, 0, addr, stack_entry->start, - stack_entry->protection, - stack_entry->max_protection, - 0); - - /* Adjust the available stack space by the amount we grew. */ - if (rv == KERN_SUCCESS) { - new_stack_entry = prev_entry->next; - if (new_stack_entry->end != stack_entry->start || - new_stack_entry->start != addr) - panic ("Bad stack grow start/end in new stack entry"); - else { - new_stack_entry->avail_ssize = stack_entry->avail_ssize - - (new_stack_entry->end - - new_stack_entry->start); - if (is_procstack) - vm->vm_ssize += new_stack_entry->end - - new_stack_entry->start; - } - } - - vm_map_unlock(map); - return (rv); - -} - /* * Find sufficient space for `length' bytes in the given map, starting at * `start'. The map must be locked. Returns 0 on success, 1 on no space. @@ -2336,6 +2133,209 @@ vmspace_fork(vm1) return (vm2); } +int +vm_map_stack (vm_map_t map, vm_offset_t addrbos, vm_size_t max_ssize, + vm_prot_t prot, vm_prot_t max, int cow) +{ + vm_map_entry_t prev_entry; + vm_map_entry_t new_stack_entry; + vm_size_t init_ssize; + int rv; + + if (VM_MIN_ADDRESS > 0 && addrbos < VM_MIN_ADDRESS) + return (KERN_NO_SPACE); + + if (max_ssize < SGROWSIZ) + init_ssize = max_ssize; + else + init_ssize = SGROWSIZ; + + vm_map_lock(map); + + /* If addr is already mapped, no go */ + if (vm_map_lookup_entry(map, addrbos, &prev_entry)) { + vm_map_unlock(map); + return (KERN_NO_SPACE); + } + + /* If we can't accomodate max_ssize in the current mapping, + * no go. However, we need to be aware that subsequent user + * mappings might map into the space we have reserved for + * stack, and currently this space is not protected. + * + * Hopefully we will at least detect this condition + * when we try to grow the stack. + */ + if ((prev_entry->next != &map->header) && + (prev_entry->next->start < addrbos + max_ssize)) { + vm_map_unlock(map); + return (KERN_NO_SPACE); + } + + /* We initially map a stack of only init_ssize. We will + * grow as needed later. Since this is to be a grow + * down stack, we map at the top of the range. + * + * Note: we would normally expect prot and max to be + * VM_PROT_ALL, and cow to be 0. Possibly we should + * eliminate these as input parameters, and just + * pass these values here in the insert call. + */ + rv = vm_map_insert(map, NULL, 0, addrbos + max_ssize - init_ssize, + addrbos + max_ssize, prot, max, cow); + + /* Now set the avail_ssize amount */ + if (rv == KERN_SUCCESS){ + new_stack_entry = prev_entry->next; + if (new_stack_entry->end != addrbos + max_ssize || + new_stack_entry->start != addrbos + max_ssize - init_ssize) + panic ("Bad entry start/end for new stack entry"); + else + new_stack_entry->avail_ssize = max_ssize - init_ssize; + } + + vm_map_unlock(map); + return (rv); +} + +/* Attempts to grow a vm stack entry. Returns KERN_SUCCESS if the + * desired address is already mapped, or if we successfully grow + * the stack. Also returns KERN_SUCCESS if addr is outside the + * stack range (this is strange, but preserves compatibility with + * the grow function in vm_machdep.c). + */ +int +vm_map_growstack (struct proc *p, vm_offset_t addr) +{ + vm_map_entry_t prev_entry; + vm_map_entry_t stack_entry; + vm_map_entry_t new_stack_entry; + struct vmspace *vm = p->p_vmspace; + vm_map_t map = &vm->vm_map; + vm_offset_t end; + int grow_amount; + int rv; + int is_procstack; +Retry: + vm_map_lock_read(map); + + /* If addr is already in the entry range, no need to grow.*/ + if (vm_map_lookup_entry(map, addr, &prev_entry)) { + vm_map_unlock_read(map); + return (KERN_SUCCESS); + } + + if ((stack_entry = prev_entry->next) == &map->header) { + vm_map_unlock_read(map); + return (KERN_SUCCESS); + } + if (prev_entry == &map->header) + end = stack_entry->start - stack_entry->avail_ssize; + else + end = prev_entry->end; + + /* This next test mimics the old grow function in vm_machdep.c. + * It really doesn't quite make sense, but we do it anyway + * for compatibility. + * + * If not growable stack, return success. This signals the + * caller to proceed as he would normally with normal vm. + */ + if (stack_entry->avail_ssize < 1 || + addr >= stack_entry->start || + addr < stack_entry->start - stack_entry->avail_ssize) { + vm_map_unlock_read(map); + return (KERN_SUCCESS); + } + + /* Find the minimum grow amount */ + grow_amount = roundup (stack_entry->start - addr, PAGE_SIZE); + if (grow_amount > stack_entry->avail_ssize) { + vm_map_unlock_read(map); + return (KERN_NO_SPACE); + } + + /* If there is no longer enough space between the entries + * nogo, and adjust the available space. Note: this + * should only happen if the user has mapped into the + * stack area after the stack was created, and is + * probably an error. + * + * This also effectively destroys any guard page the user + * might have intended by limiting the stack size. + */ + if (grow_amount > stack_entry->start - end) { + if (vm_map_lock_upgrade(map)) + goto Retry; + + stack_entry->avail_ssize = stack_entry->start - end; + + vm_map_unlock(map); + return (KERN_NO_SPACE); + } + + is_procstack = addr >= (vm_offset_t)vm->vm_maxsaddr; + + /* If this is the main process stack, see if we're over the + * stack limit. + */ + if (is_procstack && (vm->vm_ssize + grow_amount > + p->p_rlimit[RLIMIT_STACK].rlim_cur)) { + vm_map_unlock_read(map); + return (KERN_NO_SPACE); + } + + /* Round up the grow amount modulo SGROWSIZ */ + grow_amount = roundup (grow_amount, SGROWSIZ); + if (grow_amount > stack_entry->avail_ssize) { + grow_amount = stack_entry->avail_ssize; + } + if (is_procstack && (vm->vm_ssize + grow_amount > + p->p_rlimit[RLIMIT_STACK].rlim_cur)) { + grow_amount = p->p_rlimit[RLIMIT_STACK].rlim_cur - + vm->vm_ssize; + } + + if (vm_map_lock_upgrade(map)) + goto Retry; + + /* Get the preliminary new entry start value */ + addr = stack_entry->start - grow_amount; + + /* If this puts us into the previous entry, cut back our growth + * to the available space. Also, see the note above. + */ + if (addr < end) { + stack_entry->avail_ssize = stack_entry->start - end; + addr = end; + } + + rv = vm_map_insert(map, NULL, 0, addr, stack_entry->start, + stack_entry->protection, + stack_entry->max_protection, + 0); + + /* Adjust the available stack space by the amount we grew. */ + if (rv == KERN_SUCCESS) { + new_stack_entry = prev_entry->next; + if (new_stack_entry->end != stack_entry->start || + new_stack_entry->start != addr) + panic ("Bad stack grow start/end in new stack entry"); + else { + new_stack_entry->avail_ssize = stack_entry->avail_ssize - + (new_stack_entry->end - + new_stack_entry->start); + if (is_procstack) + vm->vm_ssize += new_stack_entry->end - + new_stack_entry->start; + } + } + + vm_map_unlock(map); + return (rv); + +} + /* * Unshare the specified VM space for exec. If other processes are * mapped to it, then create a new one. The new vmspace is null. |