Exemple #1
0
/*
 * Implement fork's actions on an address space.
 * Here we arrange for the address space to be copied or referenced,
 * allocate a user struct (pcb and kernel stack), then call the
 * machine-dependent layer to fill those in and make the new process
 * ready to run.  The new process is set up so that it returns directly
 * to user mode to avoid stack copying and relocation problems.
 *
 * No requirements.
 */
void
vm_fork(struct proc *p1, struct proc *p2, int flags)
{
	if ((flags & RFPROC) == 0) {
		/*
		 * Divorce the memory, if it is shared, essentially
		 * this changes shared memory amongst threads, into
		 * COW locally.
		 */
		if ((flags & RFMEM) == 0) {
			if (p1->p_vmspace->vm_sysref.refcnt > 1) {
				vmspace_unshare(p1);
			}
		}
		cpu_fork(ONLY_LWP_IN_PROC(p1), NULL, flags);
		return;
	}

	if (flags & RFMEM) {
		vmspace_ref(p1->p_vmspace);
		p2->p_vmspace = p1->p_vmspace;
	}

	while (vm_page_count_severe()) {
		vm_wait(0);
	}

	if ((flags & RFMEM) == 0) {
		p2->p_vmspace = vmspace_fork(p1->p_vmspace);

		pmap_pinit2(vmspace_pmap(p2->p_vmspace));

		if (p1->p_vmspace->vm_shm)
			shmfork(p1, p2);
	}

	pmap_init_proc(p2);
}
Exemple #2
0
/*
 * Create a kernel process/thread/whatever.  It shares it's address space
 * with proc0 - ie: kernel only.
 *
 * XXX only the SMB protocol uses this, we should convert this mess to a
 * pure thread when possible.
 */
int
smb_kthread_create(void (*func)(void *), void *arg,
		   struct proc **newpp, int flags, const char *fmt, ...)
{
	int error;
	__va_list ap;
	struct proc *p2;
	struct lwp *lp2;

	error = fork1(&lwp0, RFMEM | RFFDG | RFPROC | flags, &p2);
	if (error)
		return error;

	/* save a global descriptor, if desired */
	if (newpp != NULL)
		*newpp = p2;

	/* this is a non-swapped system process */
	p2->p_flags |= P_SYSTEM;
	p2->p_sigacts->ps_flag |= PS_NOCLDWAIT;

	lp2 = ONLY_LWP_IN_PROC(p2);

	/* set up arg0 for 'ps', et al */
	__va_start(ap, fmt);
	kvsnprintf(p2->p_comm, sizeof(p2->p_comm), fmt, ap);
	__va_end(ap);

	lp2->lwp_thread->td_ucred = crhold(proc0.p_ucred);

	/* call the processes' main()... */
	cpu_set_fork_handler(lp2,
			     (void (*)(void *, struct trapframe *))func, arg);
	start_forked_proc(&lwp0, p2);

	return 0;
}