|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1989, 1991, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * (c) UNIX System Laboratories, Inc. ! 30: * All or some portions of this file are derived from material licensed ! 31: * to the University of California by American Telephone and Telegraph ! 32: * Co. or Unix System Laboratories, Inc. and are reproduced herein with ! 33: * the permission of UNIX System Laboratories, Inc. ! 34: * ! 35: * Redistribution and use in source and binary forms, with or without ! 36: * modification, are permitted provided that the following conditions ! 37: * are met: ! 38: * 1. Redistributions of source code must retain the above copyright ! 39: * notice, this list of conditions and the following disclaimer. ! 40: * 2. Redistributions in binary form must reproduce the above copyright ! 41: * notice, this list of conditions and the following disclaimer in the ! 42: * documentation and/or other materials provided with the distribution. ! 43: * 3. All advertising materials mentioning features or use of this software ! 44: * must display the following acknowledgement: ! 45: * This product includes software developed by the University of ! 46: * California, Berkeley and its contributors. ! 47: * 4. Neither the name of the University nor the names of its contributors ! 48: * may be used to endorse or promote products derived from this software ! 49: * without specific prior written permission. ! 50: * ! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 61: * SUCH DAMAGE. ! 62: * ! 63: * @(#)kern_fork.c 8.8 (Berkeley) 2/14/95 ! 64: */ ! 65: ! 66: #include <sys/param.h> ! 67: #include <sys/systm.h> ! 68: #include <sys/filedesc.h> ! 69: #include <sys/kernel.h> ! 70: #include <sys/malloc.h> ! 71: #include <sys/proc.h> ! 72: #include <sys/user.h> ! 73: #include <sys/resourcevar.h> ! 74: #include <sys/vnode.h> ! 75: #include <sys/file.h> ! 76: #include <sys/acct.h> ! 77: #include <sys/ktrace.h> ! 78: ! 79: #import <mach/mach_types.h> ! 80: #import <kern/mach_param.h> ! 81: ! 82: #import <machine/spl.h> ! 83: ! 84: thread_t cloneproc(), procdup(); ! 85: ! 86: #define DOFORK 0x1 /* fork() system call */ ! 87: #define DOVFORK 0x2 /* vfork() system call */ ! 88: static int fork1(struct proc *, long, register_t *); ! 89: ! 90: /* ! 91: * fork system call. ! 92: */ ! 93: int ! 94: fork(p, uap, retval) ! 95: struct proc *p; ! 96: void *uap; ! 97: register_t *retval; ! 98: { ! 99: return (fork1(p, (long)DOFORK, retval)); ! 100: } ! 101: ! 102: /* ! 103: * vfork system call ! 104: */ ! 105: int ! 106: vfork(p, uap, retval) ! 107: struct proc *p; ! 108: void *uap; ! 109: register_t *retval; ! 110: { ! 111: return (fork1(p, (long)DOVFORK, retval)); ! 112: } ! 113: ! 114: static int ! 115: fork1(p1, flags, retval) ! 116: struct proc *p1; ! 117: long flags; ! 118: register_t *retval; ! 119: { ! 120: register struct proc *p2; ! 121: register uid_t uid; ! 122: thread_t newth, self = current_thread(); ! 123: int s, count; ! 124: ! 125: /* ! 126: * Although process entries are dynamically created, we still keep ! 127: * a global limit on the maximum number we will create. Don't allow ! 128: * a nonprivileged user to use the last process; don't let root ! 129: * exceed the limit. The variable nprocs is the current number of ! 130: * processes, maxproc is the limit. ! 131: */ ! 132: uid = p1->p_cred->p_ruid; ! 133: if ((nprocs >= maxproc - 1 && uid != 0) || nprocs >= maxproc) { ! 134: tablefull("proc"); ! 135: retval[1] = 0; ! 136: return (EAGAIN); ! 137: } ! 138: ! 139: /* ! 140: * Increment the count of procs running with this uid. Don't allow ! 141: * a nonprivileged user to exceed their current limit. ! 142: */ ! 143: count = chgproccnt(uid, 1); ! 144: if (uid != 0 && count > p1->p_rlimit[RLIMIT_NPROC].rlim_cur) { ! 145: (void)chgproccnt(uid, -1); ! 146: return (EAGAIN); ! 147: } ! 148: ! 149: newth = cloneproc(p1); ! 150: thread_dup(self, newth); ! 151: p2 = newth->task->proc; ! 152: s = splhigh(); ! 153: p2->p_stats->p_start = time; ! 154: splx(s); ! 155: p2->p_acflag = AFORK; ! 156: ! 157: /* ! 158: * Preserve synchronization semantics of vfork. If waiting for ! 159: * child to exec or exit, set P_PPWAIT on child, and sleep on our ! 160: * proc (in case of exit). ! 161: */ ! 162: if (flags == DOVFORK) ! 163: p2->p_flag |= P_PPWAIT; ! 164: ! 165: (void) thread_resume(newth); ! 166: ! 167: while (p2->p_flag & P_PPWAIT) ! 168: tsleep(p1, PWAIT, "ppwait", 0); ! 169: ! 170: retval[0] = p2->p_pid; ! 171: retval[1] = 0; /* mark parent */ ! 172: ! 173: return (0); ! 174: } ! 175: ! 176: /* ! 177: * cloneproc() ! 178: * ! 179: * Create a new process from a specified process. ! 180: */ ! 181: thread_t ! 182: cloneproc(p1) ! 183: register struct proc *p1; ! 184: { ! 185: register struct proc *p2, *newproc; ! 186: static int nextpid = 0, pidchecked = 0; ! 187: thread_t th; ! 188: ! 189: /* Allocate new proc. */ ! 190: MALLOC_ZONE(newproc, struct proc *, ! 191: sizeof *newproc, M_PROC, M_WAITOK); ! 192: MALLOC_ZONE(newproc->p_cred, struct pcred *, ! 193: sizeof *newproc->p_cred, M_SUBPROC, M_WAITOK); ! 194: MALLOC_ZONE(newproc->p_stats, struct pstats *, ! 195: sizeof *newproc->p_stats, M_SUBPROC, M_WAITOK); ! 196: MALLOC_ZONE(newproc->p_sigacts, struct sigacts *, ! 197: sizeof *newproc->p_sigacts, M_SUBPROC, M_WAITOK); ! 198: ! 199: /* ! 200: * Find an unused process ID. We remember a range of unused IDs ! 201: * ready to use (from nextpid+1 through pidchecked-1). ! 202: */ ! 203: nextpid++; ! 204: retry: ! 205: /* ! 206: * If the process ID prototype has wrapped around, ! 207: * restart somewhat above 0, as the low-numbered procs ! 208: * tend to include daemons that don't exit. ! 209: */ ! 210: if (nextpid >= PID_MAX) { ! 211: nextpid = 100; ! 212: pidchecked = 0; ! 213: } ! 214: if (nextpid >= pidchecked) { ! 215: int doingzomb = 0; ! 216: ! 217: pidchecked = PID_MAX; ! 218: /* ! 219: * Scan the active and zombie procs to check whether this pid ! 220: * is in use. Remember the lowest pid that's greater ! 221: * than nextpid, so we can avoid checking for a while. ! 222: */ ! 223: p2 = allproc.lh_first; ! 224: again: ! 225: for (; p2 != 0; p2 = p2->p_list.le_next) { ! 226: while (p2->p_pid == nextpid || ! 227: p2->p_pgrp->pg_id == nextpid) { ! 228: nextpid++; ! 229: if (nextpid >= pidchecked) ! 230: goto retry; ! 231: } ! 232: if (p2->p_pid > nextpid && pidchecked > p2->p_pid) ! 233: pidchecked = p2->p_pid; ! 234: if (p2->p_pgrp->pg_id > nextpid && ! 235: pidchecked > p2->p_pgrp->pg_id) ! 236: pidchecked = p2->p_pgrp->pg_id; ! 237: } ! 238: if (!doingzomb) { ! 239: doingzomb = 1; ! 240: p2 = zombproc.lh_first; ! 241: goto again; ! 242: } ! 243: } ! 244: ! 245: nprocs++; ! 246: p2 = newproc; ! 247: p2->p_stat = SIDL; ! 248: p2->p_pid = nextpid; ! 249: ! 250: /* ! 251: * Make a proc table entry for the new process. ! 252: * Start by zeroing the section of proc that is zero-initialized, ! 253: * then copy the section that is copied directly from the parent. ! 254: */ ! 255: bzero(&p2->p_startzero, ! 256: (unsigned) ((caddr_t)&p2->p_endzero - (caddr_t)&p2->p_startzero)); ! 257: bcopy(&p1->p_startcopy, &p2->p_startcopy, ! 258: (unsigned) ((caddr_t)&p2->p_endcopy - (caddr_t)&p2->p_startcopy)); ! 259: ! 260: /* ! 261: * Duplicate sub-structures as needed. ! 262: * Increase reference counts on shared objects. ! 263: * The p_stats and p_sigacts substructs are set in vm_fork. ! 264: */ ! 265: p2->p_flag = P_INMEM; ! 266: if (p1->p_flag & P_PROFIL) ! 267: startprofclock(p2); ! 268: bcopy(p1->p_cred, p2->p_cred, sizeof(*p2->p_cred)); ! 269: p2->p_cred->p_refcnt = 1; ! 270: crhold(p1->p_ucred); ! 271: lockinit(&p2->p_cred->pc_lock, PLOCK, "proc cred", 0, 0); ! 272: ! 273: /* bump references to the text vnode (for procfs) */ ! 274: p2->p_textvp = p1->p_textvp; ! 275: if (p2->p_textvp) ! 276: VREF(p2->p_textvp); ! 277: ! 278: p2->p_fd = fdcopy(p1); ! 279: /* ! 280: * If p_limit is still copy-on-write, bump refcnt, ! 281: * otherwise get a copy that won't be modified. ! 282: * (If PL_SHAREMOD is clear, the structure is shared ! 283: * copy-on-write.) ! 284: */ ! 285: if (p1->p_limit->p_lflags & PL_SHAREMOD) ! 286: p2->p_limit = limcopy(p1->p_limit); ! 287: else { ! 288: p2->p_limit = p1->p_limit; ! 289: p2->p_limit->p_refcnt++; ! 290: } ! 291: ! 292: bzero(&p2->p_stats->pstat_startzero, ! 293: (unsigned) ((caddr_t)&p2->p_stats->pstat_endzero - ! 294: (caddr_t)&p2->p_stats->pstat_startzero)); ! 295: bcopy(&p1->p_stats->pstat_startcopy, &p2->p_stats->pstat_startcopy, ! 296: ((caddr_t)&p2->p_stats->pstat_endcopy - ! 297: (caddr_t)&p2->p_stats->pstat_startcopy)); ! 298: ! 299: if (p1->p_sigacts != NULL) ! 300: (void)memcpy(p2->p_sigacts, ! 301: p1->p_sigacts, sizeof *p2->p_sigacts); ! 302: else ! 303: (void)memset(p2->p_sigacts, 0, sizeof *p2->p_sigacts); ! 304: ! 305: if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) ! 306: p2->p_flag |= P_CONTROLT; ! 307: ! 308: p2->p_xstat = 0; ! 309: p2->p_ru = NULL; ! 310: ! 311: p2->p_debugger = 0; /* don't inherit */ ! 312: simple_lock_init(&p2->siglock); ! 313: p2->sigwait = FALSE; ! 314: p2->sigwait_thread = NULL; ! 315: p2->exit_thread = NULL; ! 316: p2->user_stack = p1->user_stack; ! 317: ! 318: #if KTRACE ! 319: /* ! 320: * Copy traceflag and tracefile if enabled. ! 321: * If not inherited, these were zeroed above. ! 322: */ ! 323: if (p1->p_traceflag&KTRFAC_INHERIT) { ! 324: p2->p_traceflag = p1->p_traceflag; ! 325: if ((p2->p_tracep = p1->p_tracep) != NULL) ! 326: VREF(p2->p_tracep); ! 327: } ! 328: #endif ! 329: ! 330: th = procdup(p2, p1); /* child, parent */ ! 331: LIST_INSERT_AFTER(p1, p2, p_pglist); ! 332: p2->p_pptr = p1; ! 333: LIST_INSERT_HEAD(&p1->p_children, p2, p_sibling); ! 334: LIST_INIT(&p2->p_children); ! 335: LIST_INSERT_HEAD(&allproc, p2, p_list); ! 336: LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash); ! 337: TAILQ_INIT(&p2->p_evlist); ! 338: /* ! 339: * Make child runnable, set start time. ! 340: */ ! 341: p2->p_stat = SRUN; ! 342: ! 343: return(th); ! 344: } ! 345: ! 346: struct zone *u_thread_zone; ! 347: ! 348: void ! 349: uzone_init() ! 350: { ! 351: u_thread_zone = zinit(sizeof(struct uthread), ! 352: THREAD_MAX * sizeof(struct uthread), ! 353: THREAD_CHUNK * sizeof(struct uthread), ! 354: FALSE, "uthreads"); ! 355: } ! 356: ! 357: void ! 358: uthread_free(uthread) ! 359: struct uthread *uthread; ! 360: { ! 361: zfree(u_thread_zone, (vm_offset_t) uthread); ! 362: } ! 363:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.