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