]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_exit.c
xnu-792.6.22.tar.gz
[apple/xnu.git] / bsd / kern / kern_exit.c
CommitLineData
1c79356b 1/*
e5568f75 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 * (c) UNIX System Laboratories, Inc.
27 * All or some portions of this file are derived from material licensed
28 * to the University of California by American Telephone and Telegraph
29 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
30 * the permission of UNIX System Laboratories, Inc.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 3. All advertising materials mentioning features or use of this software
41 * must display the following acknowledgement:
42 * This product includes software developed by the University of
43 * California, Berkeley and its contributors.
44 * 4. Neither the name of the University nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 *
60 * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94
61 */
62
63#include <machine/reg.h>
64#include <machine/psl.h>
65
66#include "compat_43.h"
67
68#include <sys/param.h>
69#include <sys/systm.h>
70#include <sys/ioctl.h>
91447636
A
71#include <sys/proc_internal.h>
72#include <sys/kauth.h>
1c79356b
A
73#include <sys/tty.h>
74#include <sys/time.h>
75#include <sys/resource.h>
76#include <sys/kernel.h>
1c79356b 77#include <sys/wait.h>
91447636
A
78#include <sys/file_internal.h>
79#include <sys/vnode_internal.h>
1c79356b
A
80#include <sys/syslog.h>
81#include <sys/malloc.h>
82#include <sys/resourcevar.h>
83#include <sys/ptrace.h>
84#include <sys/user.h>
55e303ae 85#include <sys/aio_kern.h>
91447636
A
86#include <sys/sysproto.h>
87#include <sys/signalvar.h>
88#include <sys/filedesc.h> /* fdfree */
89#include <sys/shm_internal.h> /* shmexit */
90#include <sys/acct.h> /* acct_process */
91#include <machine/spl.h>
e5568f75
A
92
93#include <bsm/audit_kernel.h>
94#include <bsm/audit_kevents.h>
1c79356b
A
95
96#include <mach/mach_types.h>
91447636
A
97
98#include <kern/kern_types.h>
99#include <kern/kalloc.h>
100#include <kern/task.h>
1c79356b 101#include <kern/thread.h>
9bccf70c 102#include <kern/sched_prim.h>
1c79356b 103#include <kern/assert.h>
9bccf70c
A
104#if KTRACE
105#include <sys/ktrace.h>
106#endif
1c79356b 107
91447636
A
108#include <mach/mach_types.h>
109#include <mach/task.h>
110#include <mach/thread_act.h>
111#include <mach/mach_traps.h> /* init_process */
112
1c79356b 113extern char init_task_failure_data[];
91447636 114int exit1(struct proc *, int, int *);
55e303ae 115void proc_prepareexit(struct proc *p);
91447636 116void vfork_exit(struct proc *p, int rv);
55e303ae 117void vproc_exit(struct proc *p);
91447636
A
118__private_extern__ void munge_rusage(struct rusage *a_rusage_p, struct user_rusage *a_user_rusage_p);
119
120/*
121 * Things which should have prototypes in headers, but don't
122 */
123void unix_syscall_return(int);
124void *get_bsduthreadarg(thread_t);
125void proc_exit(struct proc *p);
126int wait1continue(int result);
127int waitidcontinue(int result);
128int *get_bsduthreadrval(thread_t);
129kern_return_t sys_perf_notify(struct task *task, exception_data_t code,
130 mach_msg_type_number_t codeCnt);
131
132/*
133 * NOTE: Source and target may *NOT* overlap!
134 * XXX Should share code with bsd/dev/ppc/unix_signal.c
135 */
136static void
137siginfo_64to32(user_siginfo_t *in, siginfo_t *out)
138{
139 out->si_signo = in->si_signo;
140 out->si_errno = in->si_errno;
141 out->si_code = in->si_code;
142 out->si_pid = in->si_pid;
143 out->si_uid = in->si_uid;
144 out->si_status = in->si_status;
145 out->si_addr = CAST_DOWN(void *,in->si_addr);
146 /* following cast works for sival_int because of padding */
147 out->si_value.sival_ptr = CAST_DOWN(void *,in->si_value.sival_ptr);
148 out->si_band = in->si_band; /* range reduction */
149 out->pad[0] = in->pad[0]; /* mcontext.ss.r1 */
150}
1c79356b
A
151
152/*
153 * exit --
154 * Death of process.
155 */
1c79356b 156void
91447636 157exit(struct proc *p, struct exit_args *uap, int *retval)
1c79356b 158{
0b4e3aa0 159 exit1(p, W_EXITCODE(uap->rval, 0), retval);
1c79356b 160
9bccf70c 161 /* drop funnel before we return */
1c79356b
A
162 thread_funnel_set(kernel_flock, FALSE);
163 thread_exception_return();
164 /* NOTREACHED */
165 while (TRUE)
9bccf70c 166 thread_block(THREAD_CONTINUE_NULL);
1c79356b
A
167 /* NOTREACHED */
168}
169
170/*
171 * Exit: deallocate address space and other resources, change proc state
172 * to zombie, and unlink proc from allproc and parent's lists. Save exit
173 * status and rusage for wait(). Check for child processes and orphan them.
174 */
0b4e3aa0 175int
91447636 176exit1(struct proc *p, int rv, int *retval)
1c79356b 177{
91447636 178 thread_t self = current_thread();
1c79356b 179 struct task *task = p->task;
91447636 180 register int s;
1c79356b
A
181 struct uthread *ut;
182
183 /*
184 * If a thread in this task has already
185 * called exit(), then halt any others
186 * right here.
187 */
0b4e3aa0 188
55e303ae 189 ut = get_bsdthread_info(self);
91447636
A
190 if (ut->uu_flag & UT_VFORK) {
191 vfork_exit(p, rv);
55e303ae 192 vfork_return(self, p->p_pptr, p , retval);
0b4e3aa0
A
193 unix_syscall_return(0);
194 /* NOT REACHED */
195 }
e5568f75 196 AUDIT_SYSCALL_EXIT(0, p, ut); /* Exit is always successfull */
1c79356b
A
197 signal_lock(p);
198 while (p->exit_thread != self) {
199 if (sig_try_locked(p) <= 0) {
55e303ae 200 if (get_threadtask(self) != task) {
1c79356b 201 signal_unlock(p);
0b4e3aa0 202 return(0);
1c79356b
A
203 }
204 signal_unlock(p);
55e303ae 205 thread_terminate(self);
1c79356b
A
206 thread_funnel_set(kernel_flock, FALSE);
207 thread_exception_return();
208 /* NOTREACHED */
209 }
210 sig_lock_to_exit(p);
211 }
212 signal_unlock(p);
213 if (p->p_pid == 1) {
214 printf("pid 1 exited (signal %d, exit %d)",
215 WTERMSIG(rv), WEXITSTATUS(rv));
216 panic("init died\nState at Last Exception:\n\n%s",
217 init_task_failure_data);
218 }
219
220 s = splsched();
221 p->p_flag |= P_WEXIT;
222 splx(s);
55e303ae 223 proc_prepareexit(p);
1c79356b
A
224 p->p_xstat = rv;
225
226 /* task terminate will call proc_terminate and that cleans it up */
227 task_terminate_internal(task);
228
0b4e3aa0 229 return(0);
1c79356b
A
230}
231
232void
233proc_prepareexit(struct proc *p)
234{
1c79356b 235 struct uthread *ut;
55e303ae 236 exception_data_t code[EXCEPTION_CODE_MAX];
91447636 237 thread_t self = current_thread();
55e303ae 238
91447636
A
239 code[0] = (exception_data_t)0xFF000001; /* Set terminate code */
240 code[1] = (exception_data_t)p->p_pid; /* Pass out the pid */
241 /* Notify the perf server */
242 (void)sys_perf_notify(p->task, (exception_data_t)&code, 2);
1c79356b 243
1c79356b
A
244 /*
245 * Remove proc from allproc queue and from pidhash chain.
246 * Need to do this before we do anything that can block.
247 * Not doing causes things like mount() find this on allproc
248 * in partially cleaned state.
249 */
250 LIST_REMOVE(p, p_list);
55e303ae 251 LIST_INSERT_HEAD(&zombproc, p, p_list); /* Place onto zombproc. */
1c79356b
A
252 LIST_REMOVE(p, p_hash);
253
254#ifdef PGINPROF
255 vmsizmon();
256#endif
257 /*
258 * If parent is waiting for us to exit or exec,
259 * P_PPWAIT is set; we will wakeup the parent below.
260 */
261 p->p_flag &= ~(P_TRACED | P_PPWAIT);
91447636 262 p->p_sigignore = ~(sigcantmask);
1c79356b 263 p->p_siglist = 0;
55e303ae 264 ut = get_bsdthread_info(self);
9bccf70c
A
265 ut->uu_siglist = 0;
266 untimeout(realitexpire, (caddr_t)p->p_pid);
1c79356b
A
267}
268
269void
270proc_exit(struct proc *p)
271{
9bccf70c 272 register struct proc *q, *nq, *pp;
1c79356b 273 struct task *task = p->task;
91447636 274 register int s;
1c79356b
A
275 boolean_t funnel_state;
276
277 /* This can happen if thread_terminate of the single thread
278 * process
279 */
280
281 funnel_state = thread_funnel_set(kernel_flock, TRUE);
282 if( !(p->p_flag & P_WEXIT)) {
283 s = splsched();
284 p->p_flag |= P_WEXIT;
285 splx(s);
286 proc_prepareexit(p);
287 }
288
91447636
A
289 p->p_lflag |= P_LPEXIT;
290 /* XXX Zombie allocation may fail, in which case stats get lost */
1c79356b
A
291 MALLOC_ZONE(p->p_ru, struct rusage *,
292 sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
293
55e303ae
A
294 /*
295 * need to cancel async IO requests that can be cancelled and wait for those
296 * already active. MAY BLOCK!
297 */
298 _aio_exit( p );
299
1c79356b
A
300 /*
301 * Close open files and release open-file table.
302 * This may block!
303 */
304 fdfree(p);
305
306 /* Close ref SYSV Shared memory*/
307 if (p->vm_shm)
308 shmexit(p);
9bccf70c
A
309 /* Release SYSV semaphores */
310 semexit(p);
1c79356b
A
311
312 if (SESS_LEADER(p)) {
313 register struct session *sp = p->p_session;
314
315 if (sp->s_ttyvp) {
fa4905b1 316 struct vnode *ttyvp;
91447636 317 struct vfs_context context;
fa4905b1 318
1c79356b
A
319 /*
320 * Controlling process.
321 * Signal foreground pgrp,
322 * drain controlling terminal
323 * and revoke access to controlling terminal.
324 */
325 if (sp->s_ttyp->t_session == sp) {
326 if (sp->s_ttyp->t_pgrp)
327 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
328 (void) ttywait(sp->s_ttyp);
329 /*
330 * The tty could have been revoked
331 * if we blocked.
332 */
91447636
A
333 context.vc_proc = p;
334 context.vc_ucred = p->p_ucred;
1c79356b 335 if (sp->s_ttyvp)
91447636 336 VNOP_REVOKE(sp->s_ttyvp, REVOKEALL, &context);
1c79356b 337 }
fa4905b1 338 ttyvp = sp->s_ttyvp;
1c79356b 339 sp->s_ttyvp = NULL;
91447636
A
340 if (ttyvp) {
341 vnode_rele(ttyvp);
342 }
1c79356b
A
343 /*
344 * s_ttyp is not zero'd; we use this to indicate
345 * that the session once had a controlling terminal.
346 * (for logging and informational purposes)
347 */
348 }
349 sp->s_leader = NULL;
350 }
351
352 fixjobc(p, p->p_pgrp, 0);
353 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
9bccf70c
A
354 (void)acct_process(p);
355
1c79356b
A
356#if KTRACE
357 /*
358 * release trace file
359 */
91447636 360 p->p_traceflag = 0; /* don't trace the vnode_put() */
fa4905b1
A
361 if (p->p_tracep) {
362 struct vnode *tvp = p->p_tracep;
363 p->p_tracep = NULL;
91447636 364 vnode_rele(tvp);
fa4905b1 365 }
1c79356b
A
366#endif
367
91447636 368 while (q = p->p_children.lh_first) {
1c79356b
A
369 proc_reparent(q, initproc);
370 /*
371 * Traced processes are killed
372 * since their existence means someone is messing up.
373 */
374 if (q->p_flag & P_TRACED) {
375 q->p_flag &= ~P_TRACED;
376 if (q->sigwait_thread) {
1c79356b
A
377 /*
378 * The sigwait_thread could be stopped at a
379 * breakpoint. Wake it up to kill.
380 * Need to do this as it could be a thread which is not
381 * the first thread in the task. So any attempts to kill
382 * the process would result into a deadlock on q->sigwait.
383 */
91447636 384 thread_resume((thread_t)q->sigwait_thread);
55e303ae 385 clear_wait(q->sigwait_thread, THREAD_INTERRUPTED);
91447636 386 threadsignal((thread_t)q->sigwait_thread, SIGKILL, 0);
1c79356b
A
387 }
388 psignal(q, SIGKILL);
389 }
390 }
391
1c79356b
A
392 /*
393 * Save exit status and final rusage info, adding in child rusage
91447636
A
394 * info and self times. If we were unable to allocate a zombie
395 * structure, this information is lost.
1c79356b 396 */
91447636
A
397 if (p->p_ru != NULL) {
398 *p->p_ru = p->p_stats->p_ru;
1c79356b 399
91447636
A
400 timerclear(&p->p_ru->ru_utime);
401 timerclear(&p->p_ru->ru_stime);
1c79356b 402
91447636 403 if (task) {
1c79356b
A
404 task_basic_info_data_t tinfo;
405 task_thread_times_info_data_t ttimesinfo;
406 int task_info_stuff, task_ttimes_stuff;
407 struct timeval ut,st;
408
409 task_info_stuff = TASK_BASIC_INFO_COUNT;
410 task_info(task, TASK_BASIC_INFO,
91447636 411 (task_info_t)&tinfo, &task_info_stuff);
1c79356b
A
412 p->p_ru->ru_utime.tv_sec = tinfo.user_time.seconds;
413 p->p_ru->ru_utime.tv_usec = tinfo.user_time.microseconds;
414 p->p_ru->ru_stime.tv_sec = tinfo.system_time.seconds;
415 p->p_ru->ru_stime.tv_usec = tinfo.system_time.microseconds;
416
417 task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT;
418 task_info(task, TASK_THREAD_TIMES_INFO,
91447636 419 (task_info_t)&ttimesinfo, &task_ttimes_stuff);
1c79356b
A
420
421 ut.tv_sec = ttimesinfo.user_time.seconds;
422 ut.tv_usec = ttimesinfo.user_time.microseconds;
423 st.tv_sec = ttimesinfo.system_time.seconds;
424 st.tv_usec = ttimesinfo.system_time.microseconds;
425 timeradd(&ut,&p->p_ru->ru_utime,&p->p_ru->ru_utime);
426 timeradd(&st,&p->p_ru->ru_stime,&p->p_ru->ru_stime);
91447636 427 }
1c79356b 428
91447636
A
429 ruadd(p->p_ru, &p->p_stats->p_cru);
430 }
1c79356b
A
431
432 /*
433 * Free up profiling buffers.
434 */
435 {
436 struct uprof *p0 = &p->p_stats->p_prof, *p1, *pn;
437
438 p1 = p0->pr_next;
439 p0->pr_next = NULL;
440 p0->pr_scale = 0;
441
442 for (; p1 != NULL; p1 = pn) {
443 pn = p1->pr_next;
91447636 444 kfree(p1, sizeof *p1);
1c79356b
A
445 }
446 }
447
448 /*
449 * Other substructures are freed from wait().
450 */
451 FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_SUBPROC);
452 p->p_stats = NULL;
453
454 FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SUBPROC);
455 p->p_sigacts = NULL;
456
457 if (--p->p_limit->p_refcnt == 0)
458 FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
459 p->p_limit = NULL;
460
461 /*
462 * Finish up by terminating the task
463 * and halt this thread (only if a
464 * member of the task exiting).
465 */
466 p->task = TASK_NULL;
467 //task->proc = NULL;
468 set_bsdtask_info(task, NULL);
469
55e303ae
A
470 KNOTE(&p->p_klist, NOTE_EXIT);
471
1c79356b
A
472 /*
473 * Notify parent that we're gone.
474 */
9bccf70c 475 if (p->p_pptr->p_flag & P_NOCLDWAIT) {
91447636 476 struct proc *opp = p->p_pptr;
9bccf70c 477
55e303ae
A
478 /*
479 * Add child resource usage to parent before giving
91447636
A
480 * zombie to init. If we were unable to allocate a
481 * zombie structure, this information is lost.
55e303ae 482 */
91447636
A
483 if (p->p_ru != NULL)
484 ruadd(&p->p_pptr->p_stats->p_cru, p->p_ru);
55e303ae 485
9bccf70c
A
486 proc_reparent(p, initproc);
487 /* If there are no more children wakeup parent */
91447636
A
488 if (LIST_EMPTY(&opp->p_children))
489 wakeup((caddr_t)opp);
9bccf70c
A
490 }
491 /* should be fine as parent proc would be initproc */
492 pp = p->p_pptr;
493 if (pp != initproc) {
494 pp->si_pid = p->p_pid;
495 pp->si_status = p->p_xstat;
496 pp->si_code = CLD_EXITED;
91447636 497 pp->si_uid = p->p_ucred->cr_ruid;
9bccf70c 498 }
55e303ae 499 /* mark as a zombie */
1c79356b
A
500 p->p_stat = SZOMB;
501
91447636
A
502 psignal(pp, SIGCHLD);
503
1c79356b
A
504 /* and now wakeup the parent */
505 wakeup((caddr_t)p->p_pptr);
506
507 (void) thread_funnel_set(kernel_flock, funnel_state);
508}
509
510
91447636
A
511/*
512 * reap_child_process
513 *
514 * Description: Given a process from which all status information needed
515 * has already been extracted, if the process is a ptrace
516 * attach process, detach it and give it back to its real
517 * parent, else recover all resources remaining associated
518 * with it.
519 *
520 * Parameters: struct proc *parent Parent of process being reaped
521 * struct proc *child Process to reap
522 *
523 * Returns: 0 Process was not reaped because it
524 * came from an attach
525 * 1 Process was reaped
526 */
527static int
528reap_child_process(struct proc *parent, struct proc *child)
1c79356b 529{
91447636
A
530 struct proc *trace_parent; /* Traced parent process, if tracing */
531 struct vnode *tvp; /* Traced vnode pointer, if used */
1c79356b 532
91447636
A
533 /*
534 * If we got the child via a ptrace 'attach',
535 * we need to give it back to the old parent.
536 */
537 if (child->p_oppid && (trace_parent = pfind(child->p_oppid))) {
538 child->p_oppid = 0;
539 proc_reparent(child, trace_parent);
540 if (trace_parent != initproc) {
541 trace_parent->si_pid = child->p_pid;
542 trace_parent->si_status = child->p_xstat;
543 trace_parent->si_code = CLD_CONTINUED;
544 trace_parent->si_uid = child->p_ucred->cr_ruid;
545 }
546 psignal(trace_parent, SIGCHLD);
547 wakeup((caddr_t)trace_parent);
548 return (0);
549 }
550 child->p_xstat = 0;
551 if (child->p_ru) {
552 ruadd(&parent->p_stats->p_cru, child->p_ru);
553 FREE_ZONE(child->p_ru, sizeof *child->p_ru, M_ZOMBIE);
554 child->p_ru = NULL;
555 } else {
556 printf("Warning : lost p_ru for %s\n", child->p_comm);
557 }
1c79356b 558
91447636
A
559 /*
560 * Decrement the count of procs running with this uid.
561 */
562 (void)chgproccnt(child->p_ucred->cr_ruid, -1);
1c79356b 563
91447636
A
564 /*
565 * Free up credentials.
566 */
567 if (child->p_ucred != NOCRED) {
568 kauth_cred_t ucr = child->p_ucred;
569 child->p_ucred = NOCRED;
570 kauth_cred_rele(ucr);
571 }
1c79356b 572
91447636
A
573 /*
574 * Release reference to text vnode
575 */
576 tvp = child->p_textvp;
577 child->p_textvp = NULL;
578 if (tvp) {
579 vnode_rele(tvp);
580 }
581 /*
582 * Finally finished with old proc entry.
583 * Unlink it from its process group and free it.
584 */
585 leavepgrp(child);
586 LIST_REMOVE(child, p_list); /* off zombproc */
587 LIST_REMOVE(child, p_sibling);
b36670ce
A
588 child->p_lflag &= ~P_LWAITING;
589 wakeup(&child->p_stat);
1c79356b 590
91447636
A
591 lck_mtx_destroy(&child->p_mlock, proc_lck_grp);
592 lck_mtx_destroy(&child->p_fdmlock, proc_lck_grp);
593 FREE_ZONE(child, sizeof *child, M_PROC);
594 nprocs--;
595 return (1);
1c79356b
A
596}
597
1c79356b
A
598
599int
91447636 600wait1continue(int result)
1c79356b 601{
7b1edb79 602 void *vt;
91447636 603 thread_t thread;
7b1edb79
A
604 int *retval;
605 struct proc *p;
1c79356b 606
7b1edb79
A
607 if (result)
608 return(result);
1c79356b 609
7b1edb79 610 p = current_proc();
91447636
A
611 thread = current_thread();
612 vt = get_bsduthreadarg(thread);
613 retval = get_bsduthreadrval(thread);
614 return(wait4((struct proc *)p, (struct wait4_args *)vt, retval));
1c79356b
A
615}
616
617int
91447636 618wait4(struct proc *q, struct wait4_args *uap, register_t *retval)
1c79356b
A
619{
620 register int nfound;
91447636 621 register struct proc *p;
1c79356b
A
622 int status, error;
623
1c79356b
A
624 if (uap->pid == 0)
625 uap->pid = -q->p_pgid;
626
627loop:
628 nfound = 0;
629 for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) {
630 if (uap->pid != WAIT_ANY &&
631 p->p_pid != uap->pid &&
632 p->p_pgid != -(uap->pid))
633 continue;
634 nfound++;
91447636
A
635
636 /* XXX This is racy because we don't get the lock!!!! */
637
b36670ce 638 if (p->p_lflag & P_LWAITING) {
7b1edb79
A
639 (void)tsleep(&p->p_stat, PWAIT, "waitcoll", 0);
640 goto loop;
641 }
b36670ce 642 p->p_lflag |= P_LWAITING; /* only allow single thread to wait() */
7b1edb79 643
1c79356b
A
644 if (p->p_stat == SZOMB) {
645 retval[0] = p->p_pid;
1c79356b
A
646 if (uap->status) {
647 status = p->p_xstat; /* convert to int */
91447636
A
648 error = copyout((caddr_t)&status,
649 uap->status,
650 sizeof(status));
651 if (error) {
b36670ce 652 p->p_lflag &= ~P_LWAITING;
7b1edb79 653 wakeup(&p->p_stat);
1c79356b
A
654 return (error);
655 }
656 }
91447636
A
657 if (uap->rusage) {
658 if (p->p_ru == NULL) {
659 error = ENOMEM;
660 } else {
661 if (IS_64BIT_PROCESS(q)) {
662 struct user_rusage my_rusage;
663 munge_rusage(p->p_ru, &my_rusage);
664 error = copyout((caddr_t)&my_rusage,
665 uap->rusage,
666 sizeof (my_rusage));
667 }
668 else {
669 error = copyout((caddr_t)p->p_ru,
670 uap->rusage,
671 sizeof (struct rusage));
672 }
9bccf70c 673 }
91447636
A
674 /* information unavailable? */
675 if (error) {
b36670ce 676 p->p_lflag &= ~P_LWAITING;
91447636
A
677 wakeup(&p->p_stat);
678 return (error);
1c79356b 679 }
1c79356b
A
680 }
681
91447636 682 /* Clean up */
b36670ce
A
683 if (!reap_child_process(q, p)) {
684 p->p_lflag &= ~P_LWAITING;
685 wakeup(&p->p_stat);
686 }
91447636 687
1c79356b
A
688 return (0);
689 }
690 if (p->p_stat == SSTOP && (p->p_flag & P_WAITED) == 0 &&
691 (p->p_flag & P_TRACED || uap->options & WUNTRACED)) {
692 p->p_flag |= P_WAITED;
693 retval[0] = p->p_pid;
1c79356b
A
694 if (uap->status) {
695 status = W_STOPCODE(p->p_xstat);
696 error = copyout((caddr_t)&status,
91447636 697 uap->status,
1c79356b
A
698 sizeof(status));
699 } else
700 error = 0;
b36670ce 701 p->p_lflag &= ~P_LWAITING;
7b1edb79 702 wakeup(&p->p_stat);
1c79356b
A
703 return (error);
704 }
b36670ce 705 p->p_lflag &= ~P_LWAITING;
7b1edb79 706 wakeup(&p->p_stat);
1c79356b 707 }
7b1edb79 708 if (nfound == 0)
1c79356b 709 return (ECHILD);
7b1edb79 710
1c79356b
A
711 if (uap->options & WNOHANG) {
712 retval[0] = 0;
1c79356b
A
713 return (0);
714 }
715
91447636
A
716 if ((error = tsleep0((caddr_t)q, PWAIT | PCATCH, "wait", 0, wait1continue)))
717 return (error);
718
719 goto loop;
720}
721
722
723int
724waitidcontinue(int result)
725{
726 void *vt;
727 thread_t thread;
728 int *retval;
729 struct proc *p;
730
731 if (result)
732 return(result);
733
734 p = current_proc();
735 thread = current_thread();
736 vt = get_bsduthreadarg(thread);
737 retval = get_bsduthreadrval(thread);
738 return(waitid((struct proc *)p, (struct waitid_args *)vt, retval));
739}
740
741/*
742 * Description: Suspend the calling thread until one child of the process
743 * containing the calling thread changes state.
744 *
745 * Parameters: uap->idtype one of P_PID, P_PGID, P_ALL
746 * uap->id pid_t or gid_t or ignored
747 * uap->infop Address of signinfo_t struct in
748 * user space into which to return status
749 * uap->options flag values
750 *
751 * Returns: 0 Success
752 * !0 Error returning status to user space
753 */
754int
755waitid(struct proc *q, struct waitid_args *uap, register_t *retval)
756{
757 user_siginfo_t collect64; /* siginfo data to return to caller */
758
759 register int nfound;
760 register struct proc *p;
761 int error;
762
763loop:
764 nfound = 0;
765 for (p = q->p_children.lh_first; p != 0; p = p->p_sibling.le_next) {
766 switch(uap->idtype) {
767 case P_PID: /* child with process ID equal to... */
768 if (p->p_pid != (pid_t)uap->id)
769 continue;
770 break;
771 case P_PGID: /* child with process group ID equal to... */
772 if (p->p_pgid != (pid_t)uap->id)
773 continue;
774 break;
775 case P_ALL: /* any child */
776 break;
777 }
778
779 /* XXX This is racy because we don't get the lock!!!! */
780
781 /*
782 * Wait collision; go to sleep and restart; used to maintain
783 * the single return for waited process guarantee.
784 */
b36670ce 785 if (p->p_lflag & P_LWAITING) {
91447636
A
786 (void)tsleep(&p->p_stat, PWAIT, "waitidcoll", 0);
787 goto loop;
788 }
b36670ce 789 p->p_lflag |= P_LWAITING; /* mark busy */
91447636
A
790
791 nfound++;
792
793 /*
794 * Types of processes we are interested in
795 *
796 * XXX Don't know what to do for WCONTINUED?!?
797 */
798 switch(p->p_stat) {
799 case SZOMB: /* Exited */
800 if (!(uap->options & WEXITED))
801 break;
802
803 /* Collect "siginfo" information for caller */
804 collect64.si_signo = 0;
805 collect64.si_code = 0;
806 collect64.si_errno = 0;
807 collect64.si_pid = 0;
808 collect64.si_uid = 0;
809 collect64.si_addr = 0;
810 collect64.si_status = p->p_xstat;
811 collect64.si_band = 0;
812
813 if (IS_64BIT_PROCESS(p)) {
814 error = copyout((caddr_t)&collect64,
815 uap->infop,
816 sizeof(collect64));
817 } else {
818 siginfo_t collect;
819 siginfo_64to32(&collect64,&collect);
820 error = copyout((caddr_t)&collect,
821 uap->infop,
822 sizeof(collect));
823 }
824 /* information unavailable? */
825 if (error) {
b36670ce 826 p->p_lflag &= ~P_LWAITING;
91447636
A
827 wakeup(&p->p_stat);
828 return (error);
829 }
830
831 /* Prevent other process for waiting for this event? */
832 if (!(uap->options & WNOWAIT)) {
833 /* Clean up */
b36670ce
A
834 if (!reap_child_process(q, p)) {
835 p->p_lflag &= ~P_LWAITING;
836 wakeup(&p->p_stat);
837 }
91447636
A
838 }
839
840 return (0);
841
842 case SSTOP: /* Stopped */
843 /*
844 * If we are not interested in stopped processes, then
845 * ignore this one.
846 */
847 if (!(uap->options & WSTOPPED))
848 break;
849
850 /*
851 * If someone has already waited it, we lost a race
852 * to be the one to return status.
853 */
854 if ((p->p_flag & P_WAITED) != 0)
855 break;
856
857 /*
858 * If this is not a traced process, and they haven't
859 * indicated an interest in untraced processes, then
860 * ignore this one.
861 */
862 if (!(p->p_flag & P_TRACED) && !(uap->options & WUNTRACED))
863 break;
864
865 /* Collect "siginfo" information for caller */
866 collect64.si_signo = 0;
867 collect64.si_code = 0;
868 collect64.si_errno = 0;
869 collect64.si_pid = 0;
870 collect64.si_uid = 0;
871 collect64.si_addr = 0;
872 collect64.si_status = p->p_xstat;
873 collect64.si_band = 0;
874
875 if (IS_64BIT_PROCESS(p)) {
876 error = copyout((caddr_t)&collect64,
877 uap->infop,
878 sizeof(collect64));
879 } else {
880 siginfo_t collect;
881 siginfo_64to32(&collect64,&collect);
882 error = copyout((caddr_t)&collect,
883 uap->infop,
884 sizeof(collect));
885 }
886 /* information unavailable? */
887 if (error) {
b36670ce 888 p->p_lflag &= ~P_LWAITING;
91447636
A
889 wakeup(&p->p_stat);
890 return (error);
891 }
892
893 /* Prevent other process for waiting for this event? */
894 if (!(uap->options & WNOWAIT)) {
895 p->p_flag |= P_WAITED;
896 }
897
b36670ce 898 p->p_lflag &= ~P_LWAITING;
91447636
A
899 wakeup(&p->p_stat);
900 return (0);
901
902 default: /* All others */
903 /* ...meaning Continued */
904 if (!(uap->options & WCONTINUED))
905 break;
906
907 /*
908 * If the flag isn't set, then this process has not
909 * been stopped and continued, or the status has
910 * already been reaped by another caller of waitid().
911 */
912 if ((p->p_flag & P_CONTINUED) == 0)
913 break;
914
915 /* Collect "siginfo" information for caller */
916 collect64.si_signo = 0;
917 collect64.si_code = 0;
918 collect64.si_errno = 0;
919 collect64.si_pid = 0;
920 collect64.si_uid = 0;
921 collect64.si_addr = 0;
922 collect64.si_status = p->p_xstat;
923 collect64.si_band = 0;
924
925 if (IS_64BIT_PROCESS(p)) {
926 error = copyout((caddr_t)&collect64,
927 uap->infop,
928 sizeof(collect64));
929 } else {
930 siginfo_t collect;
931 siginfo_64to32(&collect64,&collect);
932 error = copyout((caddr_t)&collect,
933 uap->infop,
934 sizeof(collect));
935 }
936 /* information unavailable? */
937 if (error) {
b36670ce 938 p->p_lflag &= ~P_LWAITING;
91447636
A
939 wakeup(&p->p_stat);
940 return (error);
941 }
942
943 /* Prevent other process for waiting for this event? */
944 if (!(uap->options & WNOWAIT)) {
945 p->p_flag &= ~P_CONTINUED;
946 }
947
b36670ce 948 p->p_lflag &= ~P_LWAITING;
91447636
A
949 wakeup(&p->p_stat);
950 return (0);
951
952 break;
953 }
954
955
956 /* Not a process we are interested in; go on to next child */
b36670ce 957 p->p_lflag &= ~P_LWAITING;
91447636
A
958 wakeup(&p->p_stat);
959 }
960
961 /* No child processes that could possibly satisfy the request? */
962 if (nfound == 0)
963 return (ECHILD);
964
965 if (uap->options & WNOHANG) {
966 retval[0] = 0;
967 return (0);
968 }
969
970 if ((error = tsleep0((caddr_t)q, PWAIT | PCATCH, "waitid", 0, waitidcontinue)))
1c79356b 971 return (error);
7b1edb79 972
1c79356b
A
973 goto loop;
974}
975
976/*
977 * make process 'parent' the new parent of process 'child'.
978 */
979void
91447636 980proc_reparent(struct proc *child, struct proc *parent)
1c79356b
A
981{
982
983 if (child->p_pptr == parent)
984 return;
985
986 LIST_REMOVE(child, p_sibling);
987 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
988 child->p_pptr = parent;
91447636
A
989
990 if (initproc == parent && child->p_stat == SZOMB)
991 psignal(initproc, SIGCHLD);
1c79356b
A
992}
993
1c79356b
A
994/*
995 * Make the current process an "init" process, meaning
996 * that it doesn't have a parent, and that it won't be
997 * gunned down by kill(-1, 0).
998 */
7b1edb79 999kern_return_t
91447636 1000init_process(__unused struct init_process_args *args)
1c79356b
A
1001{
1002 register struct proc *p = current_proc();
1003
e5568f75 1004 AUDIT_MACH_SYSCALL_ENTER(AUE_INITPROCESS);
91447636 1005 if (suser(kauth_cred_get(), &p->p_acflag)) {
e5568f75 1006 AUDIT_MACH_SYSCALL_EXIT(KERN_NO_ACCESS);
1c79356b 1007 return(KERN_NO_ACCESS);
e5568f75 1008 }
1c79356b
A
1009
1010 if (p->p_pid != 1 && p->p_pgid != p->p_pid)
1011 enterpgrp(p, p->p_pid, 0);
1012 p->p_flag |= P_SYSTEM;
1013
1014 /*
1015 * Take us out of the sibling chain, and
1016 * out of our parent's child chain.
1017 */
1018 LIST_REMOVE(p, p_sibling);
1019 p->p_sibling.le_prev = NULL;
1020 p->p_sibling.le_next = NULL;
1021 p->p_pptr = kernproc;
1022
e5568f75 1023 AUDIT_MACH_SYSCALL_EXIT(KERN_SUCCESS);
1c79356b
A
1024 return(KERN_SUCCESS);
1025}
1026
7b1edb79 1027
0b4e3aa0
A
1028/*
1029 * Exit: deallocate address space and other resources, change proc state
1030 * to zombie, and unlink proc from allproc and parent's lists. Save exit
1031 * status and rusage for wait(). Check for child processes and orphan them.
1032 */
1033
91447636
A
1034void
1035vfork_exit(struct proc *p, int rv)
0b4e3aa0 1036{
91447636
A
1037 thread_t self = current_thread();
1038#ifdef FIXME
0b4e3aa0 1039 struct task *task = p->task;
91447636
A
1040#endif
1041 register int s;
0b4e3aa0 1042 struct uthread *ut;
55e303ae 1043 exception_data_t code[EXCEPTION_CODE_MAX];
0b4e3aa0 1044
91447636
A
1045 /*
1046 * If a thread in this task has already
1047 * called exit(), then halt any others
1048 * right here.
1049 */
1050
1051 ut = get_bsdthread_info(self);
1052#ifdef FIXME
1053 signal_lock(p);
1054 while (p->exit_thread != self) {
1055 if (sig_try_locked(p) <= 0) {
1056 if (get_threadtask(self) != task) {
1057 signal_unlock(p);
1058 return;
1059 }
1060 signal_unlock(p);
1061 thread_terminate(self);
1062 thread_funnel_set(kernel_flock, FALSE);
1063 thread_exception_return();
1064 /* NOTREACHED */
1065 }
1066 sig_lock_to_exit(p);
1067 }
1068 signal_unlock(p);
1069 if (p->p_pid == 1) {
1070 printf("pid 1 exited (signal %d, exit %d)",
1071 WTERMSIG(rv), WEXITSTATUS(rv));
1072panic("init died\nState at Last Exception:\n\n%s", init_task_failure_data);
1073 }
1074#endif /* FIXME */
1075
0b4e3aa0
A
1076 s = splsched();
1077 p->p_flag |= P_WEXIT;
91447636 1078 p->p_lflag |= P_LPEXIT;
0b4e3aa0 1079 splx(s);
55e303ae 1080
91447636
A
1081 code[0] = (exception_data_t)0xFF000001; /* Set terminate code */
1082 code[1] = (exception_data_t)p->p_pid; /* Pass out the pid */
1083 /* Notify the perf server */
1084 (void)sys_perf_notify(p->task, (exception_data_t)&code, 2);
55e303ae 1085
0b4e3aa0
A
1086 /*
1087 * Remove proc from allproc queue and from pidhash chain.
1088 * Need to do this before we do anything that can block.
1089 * Not doing causes things like mount() find this on allproc
1090 * in partially cleaned state.
1091 */
1092 LIST_REMOVE(p, p_list);
55e303ae 1093 LIST_INSERT_HEAD(&zombproc, p, p_list); /* Place onto zombproc. */
0b4e3aa0
A
1094 LIST_REMOVE(p, p_hash);
1095 /*
1096 * If parent is waiting for us to exit or exec,
1097 * P_PPWAIT is set; we will wakeup the parent below.
1098 */
1099 p->p_flag &= ~(P_TRACED | P_PPWAIT);
1100 p->p_sigignore = ~0;
1101 p->p_siglist = 0;
1102
9bccf70c
A
1103 ut->uu_siglist = 0;
1104 untimeout(realitexpire, (caddr_t)p->p_pid);
0b4e3aa0
A
1105
1106 p->p_xstat = rv;
1107
55e303ae 1108 vproc_exit(p);
0b4e3aa0
A
1109}
1110
0b4e3aa0
A
1111void
1112vproc_exit(struct proc *p)
1113{
9bccf70c 1114 register struct proc *q, *nq, *pp;
91447636 1115#ifdef FIXME
0b4e3aa0 1116 struct task *task = p->task;
91447636 1117#endif
0b4e3aa0 1118
91447636 1119 /* XXX Zombie allocation may fail, in which case stats get lost */
0b4e3aa0
A
1120 MALLOC_ZONE(p->p_ru, struct rusage *,
1121 sizeof (*p->p_ru), M_ZOMBIE, M_WAITOK);
1122
1123 /*
1124 * Close open files and release open-file table.
1125 * This may block!
1126 */
1127 fdfree(p);
1128
0b4e3aa0
A
1129 if (SESS_LEADER(p)) {
1130 register struct session *sp = p->p_session;
1131
1132 if (sp->s_ttyvp) {
fa4905b1 1133 struct vnode *ttyvp;
91447636 1134 struct vfs_context context;
fa4905b1 1135
0b4e3aa0
A
1136 /*
1137 * Controlling process.
1138 * Signal foreground pgrp,
1139 * drain controlling terminal
1140 * and revoke access to controlling terminal.
1141 */
1142 if (sp->s_ttyp->t_session == sp) {
1143 if (sp->s_ttyp->t_pgrp)
1144 pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
1145 (void) ttywait(sp->s_ttyp);
1146 /*
1147 * The tty could have been revoked
1148 * if we blocked.
1149 */
91447636
A
1150 context.vc_proc = p;
1151 context.vc_ucred = p->p_ucred;
0b4e3aa0 1152 if (sp->s_ttyvp)
91447636 1153 VNOP_REVOKE(sp->s_ttyvp, REVOKEALL, &context);
0b4e3aa0 1154 }
fa4905b1 1155 ttyvp = sp->s_ttyvp;
0b4e3aa0 1156 sp->s_ttyvp = NULL;
91447636
A
1157 if (ttyvp) {
1158 vnode_rele(ttyvp);
1159 }
0b4e3aa0
A
1160 /*
1161 * s_ttyp is not zero'd; we use this to indicate
1162 * that the session once had a controlling terminal.
1163 * (for logging and informational purposes)
1164 */
1165 }
1166 sp->s_leader = NULL;
1167 }
1168
1169 fixjobc(p, p->p_pgrp, 0);
1170 p->p_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY;
9bccf70c 1171
0b4e3aa0
A
1172#if KTRACE
1173 /*
1174 * release trace file
1175 */
91447636 1176 p->p_traceflag = 0; /* don't trace the vnode_rele() */
fa4905b1
A
1177 if (p->p_tracep) {
1178 struct vnode *tvp = p->p_tracep;
1179 p->p_tracep = NULL;
91447636 1180 vnode_rele(tvp);
fa4905b1 1181 }
0b4e3aa0
A
1182#endif
1183
91447636 1184 while (q = p->p_children.lh_first) {
0b4e3aa0
A
1185 proc_reparent(q, initproc);
1186 /*
1187 * Traced processes are killed
1188 * since their existence means someone is messing up.
1189 */
1190 if (q->p_flag & P_TRACED) {
1191 q->p_flag &= ~P_TRACED;
1192 if (q->sigwait_thread) {
0b4e3aa0
A
1193 /*
1194 * The sigwait_thread could be stopped at a
1195 * breakpoint. Wake it up to kill.
1196 * Need to do this as it could be a thread which is not
1197 * the first thread in the task. So any attempts to kill
1198 * the process would result into a deadlock on q->sigwait.
1199 */
91447636 1200 thread_resume((thread_t)q->sigwait_thread);
55e303ae 1201 clear_wait(q->sigwait_thread, THREAD_INTERRUPTED);
91447636 1202 threadsignal((thread_t)q->sigwait_thread, SIGKILL, 0);
0b4e3aa0
A
1203 }
1204 psignal(q, SIGKILL);
1205 }
1206 }
1207
0b4e3aa0
A
1208 /*
1209 * Save exit status and final rusage info, adding in child rusage
91447636
A
1210 * info and self times. If we were unable to allocate a zombie
1211 * structure, this information is lost.
0b4e3aa0 1212 */
91447636
A
1213 if (p->p_ru != NULL) {
1214 *p->p_ru = p->p_stats->p_ru;
1215 timerclear(&p->p_ru->ru_utime);
1216 timerclear(&p->p_ru->ru_stime);
0b4e3aa0
A
1217
1218#ifdef FIXME
91447636 1219 if (task) {
0b4e3aa0
A
1220 task_basic_info_data_t tinfo;
1221 task_thread_times_info_data_t ttimesinfo;
1222 int task_info_stuff, task_ttimes_stuff;
1223 struct timeval ut,st;
1224
1225 task_info_stuff = TASK_BASIC_INFO_COUNT;
1226 task_info(task, TASK_BASIC_INFO,
1227 &tinfo, &task_info_stuff);
1228 p->p_ru->ru_utime.tv_sec = tinfo.user_time.seconds;
1229 p->p_ru->ru_utime.tv_usec = tinfo.user_time.microseconds;
1230 p->p_ru->ru_stime.tv_sec = tinfo.system_time.seconds;
1231 p->p_ru->ru_stime.tv_usec = tinfo.system_time.microseconds;
1232
1233 task_ttimes_stuff = TASK_THREAD_TIMES_INFO_COUNT;
1234 task_info(task, TASK_THREAD_TIMES_INFO,
1235 &ttimesinfo, &task_ttimes_stuff);
1236
1237 ut.tv_sec = ttimesinfo.user_time.seconds;
1238 ut.tv_usec = ttimesinfo.user_time.microseconds;
1239 st.tv_sec = ttimesinfo.system_time.seconds;
1240 st.tv_usec = ttimesinfo.system_time.microseconds;
1241 timeradd(&ut,&p->p_ru->ru_utime,&p->p_ru->ru_utime);
91447636
A
1242 timeradd(&st,&p->p_ru->ru_stime,&p->p_ru->ru_stime);
1243 }
0b4e3aa0
A
1244#endif /* FIXME */
1245
91447636
A
1246 ruadd(p->p_ru, &p->p_stats->p_cru);
1247 }
0b4e3aa0
A
1248
1249 /*
1250 * Free up profiling buffers.
1251 */
1252 {
1253 struct uprof *p0 = &p->p_stats->p_prof, *p1, *pn;
1254
1255 p1 = p0->pr_next;
1256 p0->pr_next = NULL;
1257 p0->pr_scale = 0;
1258
1259 for (; p1 != NULL; p1 = pn) {
1260 pn = p1->pr_next;
91447636 1261 kfree(p1, sizeof *p1);
0b4e3aa0
A
1262 }
1263 }
1264
1265 /*
1266 * Other substructures are freed from wait().
1267 */
1268 FREE_ZONE(p->p_stats, sizeof *p->p_stats, M_SUBPROC);
1269 p->p_stats = NULL;
1270
1271 FREE_ZONE(p->p_sigacts, sizeof *p->p_sigacts, M_SUBPROC);
1272 p->p_sigacts = NULL;
1273
1274 if (--p->p_limit->p_refcnt == 0)
1275 FREE_ZONE(p->p_limit, sizeof *p->p_limit, M_SUBPROC);
1276 p->p_limit = NULL;
1277
1278 /*
1279 * Finish up by terminating the task
1280 * and halt this thread (only if a
1281 * member of the task exiting).
1282 */
1283 p->task = TASK_NULL;
1284
1285 /*
1286 * Notify parent that we're gone.
1287 */
9bccf70c
A
1288 pp = p->p_pptr;
1289 if (pp != initproc) {
1290 pp->si_pid = p->p_pid;
1291 pp->si_status = p->p_xstat;
1292 pp->si_code = CLD_EXITED;
91447636 1293 pp->si_uid = p->p_ucred->cr_ruid;
9bccf70c 1294 }
55e303ae 1295 /* mark as a zombie */
0b4e3aa0
A
1296 p->p_stat = SZOMB;
1297
91447636
A
1298 psignal(p->p_pptr, SIGCHLD);
1299
0b4e3aa0
A
1300 /* and now wakeup the parent */
1301 wakeup((caddr_t)p->p_pptr);
0b4e3aa0 1302}
91447636
A
1303
1304
1305/*
1306 * munge_rusage
1307 * LP64 support - long is 64 bits if we are dealing with a 64 bit user
1308 * process. We munge the kernel (32 bit) version of rusage into the
1309 * 64 bit version.
1310 */
1311__private_extern__ void
1312munge_rusage(struct rusage *a_rusage_p, struct user_rusage *a_user_rusage_p)
1313{
1314 /* timeval changes size, so utime and stime need special handling */
1315 a_user_rusage_p->ru_utime.tv_sec = a_rusage_p->ru_utime.tv_sec;
1316 a_user_rusage_p->ru_utime.tv_usec = a_rusage_p->ru_utime.tv_usec;
1317 a_user_rusage_p->ru_stime.tv_sec = a_rusage_p->ru_stime.tv_sec;
1318 a_user_rusage_p->ru_stime.tv_usec = a_rusage_p->ru_stime.tv_usec;
1319 /*
1320 * everything else can be a direct assign, since there is no loss
1321 * of precision implied boing 32->64.
1322 */
1323 a_user_rusage_p->ru_maxrss = a_rusage_p->ru_maxrss;
1324 a_user_rusage_p->ru_ixrss = a_rusage_p->ru_ixrss;
1325 a_user_rusage_p->ru_idrss = a_rusage_p->ru_idrss;
1326 a_user_rusage_p->ru_isrss = a_rusage_p->ru_isrss;
1327 a_user_rusage_p->ru_minflt = a_rusage_p->ru_minflt;
1328 a_user_rusage_p->ru_majflt = a_rusage_p->ru_majflt;
1329 a_user_rusage_p->ru_nswap = a_rusage_p->ru_nswap;
1330 a_user_rusage_p->ru_inblock = a_rusage_p->ru_inblock;
1331 a_user_rusage_p->ru_oublock = a_rusage_p->ru_oublock;
1332 a_user_rusage_p->ru_msgsnd = a_rusage_p->ru_msgsnd;
1333 a_user_rusage_p->ru_msgrcv = a_rusage_p->ru_msgrcv;
1334 a_user_rusage_p->ru_nsignals = a_rusage_p->ru_nsignals;
1335 a_user_rusage_p->ru_nvcsw = a_rusage_p->ru_nvcsw;
1336 a_user_rusage_p->ru_nivcsw = a_rusage_p->ru_nivcsw;
1337}