diff options
author | alc <alc@FreeBSD.org> | 1999-03-07 21:25:42 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 1999-03-07 21:25:42 +0000 |
commit | 65b8ae094477c6bee23ab43fa32dba44f3b9fd75 (patch) | |
tree | 47361a3fb9f3beaf6573a71c32275037cbcdb3d5 /sys/vm | |
parent | e36037abffd75e59c147b7ff7f223a2763b1cd60 (diff) | |
download | FreeBSD-src-65b8ae094477c6bee23ab43fa32dba44f3b9fd75.zip FreeBSD-src-65b8ae094477c6bee23ab43fa32dba44f3b9fd75.tar.gz |
Change vm_map_growstack to acquire and hold a read lock (instead of a write
lock) until it actually needs to modify the vm_map.
Note: it is legal to modify vm_map::hint without holding a write lock.
Submitted by: "Richard Seaman, Jr." <dick@tar.com> with minor changes
by myself.
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_map.c | 28 |
1 files changed, 17 insertions, 11 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 4f6a359..b449ed0 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.152 1999/02/24 21:26:25 dillon Exp $ + * $Id: vm_map.c,v 1.153 1999/03/02 05:43:17 alc Exp $ */ /* @@ -659,18 +659,18 @@ vm_map_growstack (struct proc *p, vm_offset_t addr) vm_offset_t end; int grow_amount; int rv; - int is_procstack = 0; - - vm_map_lock(map); + 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(map); + vm_map_unlock_read(map); return (KERN_SUCCESS); } if ((stack_entry = prev_entry->next) == &map->header) { - vm_map_unlock(map); + vm_map_unlock_read(map); return (KERN_SUCCESS); } if (prev_entry == &map->header) @@ -688,14 +688,14 @@ vm_map_growstack (struct proc *p, vm_offset_t addr) if (stack_entry->avail_ssize < 1 || addr >= stack_entry->start || addr < stack_entry->start - stack_entry->avail_ssize) { - vm_map_unlock(map); + 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(map); + vm_map_unlock_read(map); return (KERN_NO_SPACE); } @@ -709,20 +709,23 @@ vm_map_growstack (struct proc *p, vm_offset_t addr) * 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); } - if (addr >= (vm_offset_t)vm->vm_maxsaddr) - is_procstack = 1; + 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(map); + vm_map_unlock_read(map); return (KERN_NO_SPACE); } @@ -737,6 +740,9 @@ vm_map_growstack (struct proc *p, vm_offset_t addr) vm->vm_ssize; } + if (vm_map_lock_upgrade(map)) + goto Retry; + /* Get the preliminary new entry start value */ addr = stack_entry->start - grow_amount; |