* vmspace_fork: * Create a new process vmspace structure and vm_map * based on those of an existing process. The new map * is based on the old map, according to the inheritance * values on the regions in that map. * * XXX It might be worth coalescing the entries added to the new vmspace. * * The source map must not be locked. */
| 4275 | * The source map must not be locked. |
| 4276 | */ |
| 4277 | struct vmspace * |
| 4278 | vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge) |
| 4279 | { |
| 4280 | struct vmspace *vm2; |
| 4281 | vm_map_t new_map, old_map; |
| 4282 | vm_map_entry_t new_entry, old_entry; |
| 4283 | vm_object_t object; |
| 4284 | int error, locked; |
| 4285 | vm_inherit_t inh; |
| 4286 | |
| 4287 | old_map = &vm1->vm_map; |
| 4288 | /* Copy immutable fields of vm1 to vm2. */ |
| 4289 | vm2 = vmspace_alloc(vm_map_min(old_map), vm_map_max(old_map), |
| 4290 | pmap_pinit); |
| 4291 | if (vm2 == NULL) |
| 4292 | return (NULL); |
| 4293 | |
| 4294 | vm2->vm_taddr = vm1->vm_taddr; |
| 4295 | vm2->vm_daddr = vm1->vm_daddr; |
| 4296 | vm2->vm_maxsaddr = vm1->vm_maxsaddr; |
| 4297 | vm_map_lock(old_map); |
| 4298 | if (old_map->busy) |
| 4299 | vm_map_wait_busy(old_map); |
| 4300 | new_map = &vm2->vm_map; |
| 4301 | locked = vm_map_trylock(new_map); /* trylock to silence WITNESS */ |
| 4302 | KASSERT(locked, ("vmspace_fork: lock failed")); |
| 4303 | |
| 4304 | error = pmap_vmspace_copy(new_map->pmap, old_map->pmap); |
| 4305 | if (error != 0) { |
| 4306 | sx_xunlock(&old_map->lock); |
| 4307 | sx_xunlock(&new_map->lock); |
| 4308 | vm_map_process_deferred(); |
| 4309 | vmspace_free(vm2); |
| 4310 | return (NULL); |
| 4311 | } |
| 4312 | |
| 4313 | new_map->anon_loc = old_map->anon_loc; |
| 4314 | new_map->flags |= old_map->flags & (MAP_ASLR | MAP_ASLR_IGNSTART | |
| 4315 | MAP_WXORX); |
| 4316 | |
| 4317 | VM_MAP_ENTRY_FOREACH(old_entry, old_map) { |
| 4318 | if ((old_entry->eflags & MAP_ENTRY_IS_SUB_MAP) != 0) |
| 4319 | panic("vm_map_fork: encountered a submap"); |
| 4320 | |
| 4321 | inh = old_entry->inheritance; |
| 4322 | if ((old_entry->eflags & MAP_ENTRY_GUARD) != 0 && |
| 4323 | inh != VM_INHERIT_NONE) |
| 4324 | inh = VM_INHERIT_COPY; |
| 4325 | |
| 4326 | switch (inh) { |
| 4327 | case VM_INHERIT_NONE: |
| 4328 | break; |
| 4329 | |
| 4330 | case VM_INHERIT_SHARE: |
| 4331 | /* |
| 4332 | * Clone the entry, creating the shared object if |
| 4333 | * necessary. |
| 4334 | */ |
no test coverage detected