1 2 #define _SYSTEM 1 3 4 #include <minix/callnr.h> 5 #include <minix/com.h> 6 #include <minix/config.h> 7 #include <minix/const.h> 8 #include <minix/ds.h> 9 #include <minix/endpoint.h> 10 #include <minix/minlib.h> 11 #include <minix/type.h> 12 #include <minix/ipc.h> 13 #include <minix/sysutil.h> 14 #include <minix/syslib.h> 15 #include <minix/debug.h> 16 #include <minix/bitmap.h> 17 18 #include <string.h> 19 #include <errno.h> 20 #include <assert.h> 21 22 #include "glo.h" 23 #include "vm.h" 24 #include "proto.h" 25 #include "util.h" 26 #include "sanitycheck.h" 27 #include "region.h" 28 29 /*===========================================================================* 30 * do_fork * 31 *===========================================================================*/ 32 int do_fork(message *msg) 33 { 34 int r, proc, childproc; 35 struct vmproc *vmp, *vmc; 36 pt_t origpt; 37 vir_bytes msgaddr; 38 39 SANITYCHECK(SCL_FUNCTIONS); 40 41 if(vm_isokendpt(msg->VMF_ENDPOINT, &proc) != OK) { 42 printf("VM: bogus endpoint VM_FORK %d\n", msg->VMF_ENDPOINT); 43 SANITYCHECK(SCL_FUNCTIONS); 44 return EINVAL; 45 } 46 47 childproc = msg->VMF_SLOTNO; 48 if(childproc < 0 || childproc >= NR_PROCS) { 49 printf("VM: bogus slotno VM_FORK %d\n", msg->VMF_SLOTNO); 50 SANITYCHECK(SCL_FUNCTIONS); 51 return EINVAL; 52 } 53 54 vmp = &vmproc[proc]; /* parent */ 55 vmc = &vmproc[childproc]; /* child */ 56 assert(vmc->vm_slot == childproc); 57 58 /* The child is basically a copy of the parent. */ 59 origpt = vmc->vm_pt; 60 *vmc = *vmp; 61 vmc->vm_slot = childproc; 62 region_init(&vmc->vm_regions_avl); 63 vmc->vm_endpoint = NONE; /* In case someone tries to use it. */ 64 vmc->vm_pt = origpt; 65 66 #if VMSTATS 67 vmc->vm_bytecopies = 0; 68 #endif 69 70 if(pt_new(&vmc->vm_pt) != OK) { 71 return ENOMEM; 72 } 73 74 SANITYCHECK(SCL_DETAIL); 75 76 if(map_proc_copy(vmc, vmp) != OK) { 77 printf("VM: fork: map_proc_copy failed\n"); 78 pt_free(&vmc->vm_pt); 79 return(ENOMEM); 80 } 81 82 /* Only inherit these flags. */ 83 vmc->vm_flags &= VMF_INUSE; 84 85 /* Deal with ACLs. */ 86 acl_fork(vmc); 87 88 /* Tell kernel about the (now successful) FORK. */ 89 if((r=sys_fork(vmp->vm_endpoint, childproc, 90 &vmc->vm_endpoint, PFF_VMINHIBIT, &msgaddr)) != OK) { 91 panic("do_fork can't sys_fork: %d", r); 92 } 93 94 if((r=pt_bind(&vmc->vm_pt, vmc)) != OK) 95 panic("fork can't pt_bind: %d", r); 96 97 { 98 vir_bytes vir; 99 /* making these messages writable is an optimisation 100 * and its return value needn't be checked. 101 */ 102 vir = msgaddr; 103 if (handle_memory_once(vmc, vir, sizeof(message), 1) != OK) 104 panic("do_fork: handle_memory for child failed\n"); 105 vir = msgaddr; 106 if (handle_memory_once(vmp, vir, sizeof(message), 1) != OK) 107 panic("do_fork: handle_memory for parent failed\n"); 108 } 109 110 /* Inform caller of new child endpoint. */ 111 msg->VMF_CHILD_ENDPOINT = vmc->vm_endpoint; 112 113 SANITYCHECK(SCL_FUNCTIONS); 114 return OK; 115 } 116 117