Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/proc/proc_fork.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pid_alloc
  2. newproc
  3. sys_fork
  4. cleanup
  5. vfork_start
  6. vfork_end

   1 /*
   2  * Copyright (c) 2005-2006, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 /*
  31  * fork.c - fork() support
  32  */
  33 
  34 #include <sys/prex.h>
  35 #include <ipc/proc.h>
  36 #include <sys/list.h>
  37 
  38 #include <unistd.h>
  39 #include <errno.h>
  40 #include <stdlib.h>
  41 #include <string.h>
  42 
  43 #include "proc.h"
  44 
  45 static int vfork_start(struct proc *);
  46 
  47 /*
  48  * PID previously allocated.
  49  *
  50  * Note: The following pids are reserved by default.
  51  *   pid = 0: Process server
  52  *   pid = 1: Init process
  53  */
  54 static pid_t last_pid = 1;
  55 
  56 /*
  57  * Assign new pid.
  58  * Returns pid on sucess, or 0 on failure.
  59  */
  60 static pid_t
  61 pid_alloc(void)
  62 {
  63         pid_t pid;
  64 
  65         pid = last_pid + 1;
  66         if (pid >= PID_MAX)
  67                 pid = 1;
  68         while (pid != last_pid) {
  69                 if (p_find(pid) == NULL)
  70                         break;
  71                 if (++pid >= PID_MAX)
  72                         pid = 1;
  73         }
  74         if (pid == last_pid)
  75                 return 0;
  76         last_pid = pid;
  77         return pid;
  78 }
  79 
  80 /*
  81  * Create a new process.
  82  */
  83 int
  84 newproc(struct proc *p, pid_t pid, task_t task)
  85 {
  86         struct pgrp *pg;
  87 
  88         pg = curproc->p_pgrp;
  89 
  90         if (pid == 0) {
  91                 pid = pid_alloc();
  92                 if (pid == 0) {
  93                         /* Too many processes */
  94                         return EAGAIN;
  95                 }
  96         }
  97         /*
  98          * make proc entry for new proc
  99          */
 100         p->p_parent = curproc;
 101         p->p_pgrp = pg;
 102         p->p_stat = SRUN;
 103         p->p_exitcode = 0;
 104         p->p_pid = pid;
 105         p->p_task = task;
 106         p->p_vforked = 0;
 107         p->p_invfork = 0;
 108 
 109         list_init(&p->p_children);
 110         p_add(p);
 111         list_insert(&curproc->p_children, &p->p_sibling);
 112         list_insert(&pg->pg_members, &p->p_pgrp_link);
 113         list_insert(&allproc, &p->p_link);
 114 
 115         return 0;
 116 }
 117 
 118 /*
 119  * fork() support.
 120  *
 121  * It creates new process data and update all process relations.
 122  * The task creation and the thread creation are done by the
 123  * fork() library stub.
 124  */
 125 int
 126 sys_fork(task_t child, int vfork, pid_t *retval)
 127 {
 128         struct proc *p;
 129         int error;
 130 
 131         DPRINTF(("proc: fork child=%x vfork=%d\n", child, vfork));
 132 
 133         if (vfork && curproc->p_invfork) {
 134                 DPRINTF(("proc: vfork under vfork!\n"));
 135                 return EINVAL;
 136         }
 137 
 138         if (task_to_proc(child) != NULL) {
 139                 DPRINTF(("proc: process already exists\n"));
 140                 return EINVAL;
 141         }
 142 
 143         if ((p = malloc(sizeof(struct proc))) == NULL)
 144                 return ENOMEM;
 145         memset(p, 0, sizeof(*p));
 146 
 147         error = newproc(p, 0, child);
 148         if (error)
 149                 return error;
 150 
 151         if (vfork) {
 152                 vfork_start(curproc);
 153                 p->p_invfork = 1;
 154         }
 155 
 156         DPRINTF(("proc: fork newpid=%d\n", p->p_pid));
 157         *retval = p->p_pid;
 158         return 0;
 159 }
 160 
 161 /*
 162  * Clean up all resource created by fork().
 163  */
 164 void
 165 cleanup(struct proc *p)
 166 {
 167         struct proc *pp;
 168 
 169         DPRINTF(("proc: cleanup pid=%d\n", p->p_pid));
 170         pp = p->p_parent;
 171         list_remove(&p->p_sibling);
 172         list_remove(&p->p_pgrp_link);
 173         list_remove(&p->p_link);
 174         free(p);
 175 }
 176 
 177 static int
 178 vfork_start(struct proc *p)
 179 {
 180         void *stack;
 181 
 182         /*
 183          * Save parent's stack
 184          */
 185         DPRINTF(("proc: vfork_start stack=%x\n", p->p_stackbase));
 186 
 187         if (vm_allocate(p->p_task, &stack, DFLSTKSZ, 1) != 0) {
 188                 DPRINTF(("proc: failed to allocate save stack\n"));
 189                 return ENOMEM;
 190         }
 191 
 192         memcpy(stack, p->p_stackbase, DFLSTKSZ);
 193         p->p_stacksaved = stack;
 194 
 195         p->p_vforked = 1;
 196         return 0;
 197 }
 198 
 199 void
 200 vfork_end(struct proc *p)
 201 {
 202 
 203         DPRINTF(("proc: vfork_end org=%x saved=%x\n", p->p_stackbase,
 204                  p->p_stacksaved));
 205         /*
 206          * Restore parent's stack
 207          */
 208         memcpy(p->p_stackbase, p->p_stacksaved, DFLSTKSZ);
 209         vm_free(p->p_task, p->p_stacksaved);
 210 
 211         /*
 212          * Resume parent
 213          */
 214         p->p_vforked = 0;
 215         task_resume(p->p_task);
 216 }

/* [<][>][^][v][top][bottom][index][help] */