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