2005-02-27 01:58:54 +03:00
|
|
|
/* $NetBSD: mach_exec.c,v 1.55 2005/02/26 23:10:19 perry Exp $ */
|
2001-07-14 06:10:59 +04:00
|
|
|
|
|
|
|
/*-
|
2003-01-01 18:18:25 +03:00
|
|
|
* Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
|
2001-07-14 06:10:59 +04:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
2003-01-01 18:18:25 +03:00
|
|
|
* by Christos Zoulas and Emmanuel Dreyfus.
|
2001-07-14 06:10:59 +04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the NetBSD
|
|
|
|
* Foundation, Inc. and its contributors.
|
|
|
|
* 4. Neither the name of The NetBSD Foundation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2001-11-13 05:07:52 +03:00
|
|
|
#include <sys/cdefs.h>
|
2005-02-27 01:58:54 +03:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.55 2005/02/26 23:10:19 perry Exp $");
|
2003-06-23 15:00:59 +04:00
|
|
|
|
|
|
|
#include "opt_syscall_debug.h"
|
2001-11-13 05:07:52 +03:00
|
|
|
|
2001-07-14 06:10:59 +04:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/exec.h>
|
2002-12-13 02:18:20 +03:00
|
|
|
#include <sys/queue.h>
|
We now have the exact stack initial stack layout of Darwin:
macho_hdr, argc, *argv, NULL, *envp, NULL, progname, NULL,
*progname, **argv, **envp
Where progname is a pointer to the program name as given in the first
argument to execve(), and macho_hdr a pointer to the Mach-O header at
the beginning of the executable file.
2002-11-21 22:53:40 +03:00
|
|
|
#include <sys/exec_macho.h>
|
2001-07-14 06:10:59 +04:00
|
|
|
#include <sys/malloc.h>
|
|
|
|
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
|
2002-11-12 22:01:18 +03:00
|
|
|
#include <uvm/uvm_extern.h>
|
|
|
|
#include <uvm/uvm_param.h>
|
|
|
|
|
2001-07-14 06:10:59 +04:00
|
|
|
#include <compat/mach/mach_types.h>
|
2002-12-13 02:18:20 +03:00
|
|
|
#include <compat/mach/mach_message.h>
|
2002-12-15 03:40:24 +03:00
|
|
|
#include <compat/mach/mach_port.h>
|
2002-12-13 02:18:20 +03:00
|
|
|
#include <compat/mach/mach_semaphore.h>
|
2003-03-29 14:04:08 +03:00
|
|
|
#include <compat/mach/mach_notify.h>
|
2001-07-14 06:10:59 +04:00
|
|
|
#include <compat/mach/mach_exec.h>
|
|
|
|
|
2002-12-15 03:40:24 +03:00
|
|
|
static int mach_cold = 1; /* Have we initialized COMPAT_MACH structures? */
|
|
|
|
static void mach_init(void);
|
2002-12-07 18:33:01 +03:00
|
|
|
|
2001-07-14 06:10:59 +04:00
|
|
|
extern struct sysent sysent[];
|
|
|
|
#ifdef SYSCALL_DEBUG
|
|
|
|
extern const char * const syscallnames[];
|
|
|
|
#endif
|
|
|
|
#ifndef __HAVE_SYSCALL_INTERN
|
2002-11-29 00:21:32 +03:00
|
|
|
void syscall(void);
|
2001-07-14 06:10:59 +04:00
|
|
|
#else
|
2002-11-29 00:21:32 +03:00
|
|
|
void mach_syscall_intern(struct proc *);
|
2001-07-14 06:10:59 +04:00
|
|
|
#endif
|
|
|
|
|
2004-03-26 20:34:18 +03:00
|
|
|
#ifdef COMPAT_16
|
2003-09-10 20:44:56 +04:00
|
|
|
extern char sigcode[], esigcode[];
|
2003-08-24 21:52:28 +04:00
|
|
|
struct uvm_object *emul_mach_object;
|
2003-09-10 20:44:56 +04:00
|
|
|
#endif
|
2003-08-24 21:52:28 +04:00
|
|
|
|
2001-07-14 06:10:59 +04:00
|
|
|
const struct emul emul_mach = {
|
|
|
|
"mach",
|
|
|
|
"/emul/mach",
|
|
|
|
#ifndef __HAVE_MINIMAL_EMUL
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
SYS_syscall,
|
2002-11-01 22:26:21 +03:00
|
|
|
SYS_NSYSENT,
|
2001-07-14 06:10:59 +04:00
|
|
|
#endif
|
|
|
|
sysent,
|
|
|
|
#ifdef SYSCALL_DEBUG
|
|
|
|
syscallnames,
|
|
|
|
#else
|
|
|
|
NULL,
|
|
|
|
#endif
|
|
|
|
sendsig,
|
First work on Mach exceptions. Things that can turn into signals on UNIX
may turn into exceptions on Mach: a small message sent by the kernel to
the task that requested the exception.
On Darwin, when an exception is sent, no signal can be delivered.
TODO: more exceptions: arithmetic, bad instructions, emulation, s
software, and syscalls (plain and Mach). There is also RPC alert, but
I have no idea about what it is.
While we are there, remove some user ktrace in notification code, and add
a NODEF qualifier in mach_services.master: it will be used for notifications
and exceptions, where the kernel is always client and never server: we
don't want the message to be displayed as "unimplemented xxx" in kdump (thus
UNIMPL is not good), but we don't want to generate the server prototype
(therefore, STD is not good either). NODEF will declare it normally in the
name tables without creating the prototype.
2003-11-17 04:52:14 +03:00
|
|
|
mach_trapsignal,
|
2003-12-20 22:01:29 +03:00
|
|
|
NULL,
|
2004-03-26 20:34:18 +03:00
|
|
|
#ifdef COMPAT_16
|
2001-07-14 06:10:59 +04:00
|
|
|
sigcode,
|
|
|
|
esigcode,
|
2003-08-24 21:52:28 +04:00
|
|
|
&emul_mach_object,
|
2003-09-10 20:44:56 +04:00
|
|
|
#else
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
#endif
|
2001-09-18 23:36:32 +04:00
|
|
|
setregs,
|
2002-12-07 18:33:01 +03:00
|
|
|
mach_e_proc_exec,
|
|
|
|
mach_e_proc_fork,
|
|
|
|
mach_e_proc_exit,
|
2003-12-20 22:43:17 +03:00
|
|
|
mach_e_lwp_fork,
|
|
|
|
mach_e_lwp_exit,
|
2001-07-14 06:10:59 +04:00
|
|
|
#ifdef __HAVE_SYSCALL_INTERN
|
|
|
|
mach_syscall_intern,
|
|
|
|
#else
|
|
|
|
syscall,
|
|
|
|
#endif
|
- Introduce a e_fault field in struct proc to provide emulation specific
memory fault handler. IRIX uses irix_vm_fault, and all other emulation
use NULL, which means to use uvm_fault.
- While we are there, explicitely set to NULL the uninitialized fields in
struct emul: e_fault and e_sysctl on most ports
- e_fault is used by the trap handler, for now only on mips. In order to avoid
intrusive modifications in UVM, the function pointed by e_fault does not
has exactly the same protoype as uvm_fault:
int uvm_fault __P((struct vm_map *, vaddr_t, vm_fault_t, vm_prot_t));
int e_fault __P((struct proc *, vaddr_t, vm_fault_t, vm_prot_t));
- In IRIX share groups, all the VM space is shared, except one page.
This bounds us to have different VM spaces and synchronize modifications
to the VM space accross share group members. We need an IRIX specific hook
to the page fault handler in order to propagate VM space modifications
caused by page faults.
2002-09-22 01:14:54 +04:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2001-07-14 06:10:59 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy arguments onto the stack in the normal way, but add some
|
|
|
|
* extra information in case of dynamic binding.
|
2005-02-27 01:58:54 +03:00
|
|
|
* XXX This needs a cleanup: it is not used anymore by the Darwin
|
|
|
|
* emulation, and it probably contains Darwin specific bits.
|
2001-07-14 06:10:59 +04:00
|
|
|
*/
|
2001-07-30 01:26:07 +04:00
|
|
|
int
|
2003-06-30 02:28:00 +04:00
|
|
|
exec_mach_copyargs(p, pack, arginfo, stackp, argp)
|
|
|
|
struct proc *p;
|
2002-12-07 18:33:01 +03:00
|
|
|
struct exec_package *pack;
|
|
|
|
struct ps_strings *arginfo;
|
|
|
|
char **stackp;
|
|
|
|
void *argp;
|
2001-07-14 06:10:59 +04:00
|
|
|
{
|
We now have the exact stack initial stack layout of Darwin:
macho_hdr, argc, *argv, NULL, *envp, NULL, progname, NULL,
*progname, **argv, **envp
Where progname is a pointer to the program name as given in the first
argument to execve(), and macho_hdr a pointer to the Mach-O header at
the beginning of the executable file.
2002-11-21 22:53:40 +03:00
|
|
|
struct exec_macho_emul_arg *emea;
|
2003-01-01 18:18:25 +03:00
|
|
|
struct exec_macho_object_header *macho_hdr;
|
2001-07-14 06:10:59 +04:00
|
|
|
size_t len;
|
|
|
|
size_t zero = 0;
|
2001-07-30 01:26:07 +04:00
|
|
|
int error;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
2003-01-01 18:18:25 +03:00
|
|
|
*stackp = (char *)(((unsigned long)*stackp - 1) & ~0xfUL);
|
2001-07-14 06:10:59 +04:00
|
|
|
|
2003-01-01 18:18:25 +03:00
|
|
|
emea = (struct exec_macho_emul_arg *)pack->ep_emul_arg;
|
|
|
|
macho_hdr = (struct exec_macho_object_header *)emea->macho_hdr;
|
2005-02-27 01:58:54 +03:00
|
|
|
if ((error = copyout(&macho_hdr, *stackp, sizeof(macho_hdr))) != 0)
|
2002-11-12 22:01:18 +03:00
|
|
|
return error;
|
2005-02-27 01:58:54 +03:00
|
|
|
|
2003-01-01 18:18:25 +03:00
|
|
|
*stackp += sizeof(macho_hdr);
|
2002-11-12 22:01:18 +03:00
|
|
|
|
2003-06-30 02:28:00 +04:00
|
|
|
if ((error = copyargs(p, pack, arginfo, stackp, argp)) != 0) {
|
2001-07-30 01:26:07 +04:00
|
|
|
DPRINTF(("mach: copyargs failed\n"));
|
|
|
|
return error;
|
|
|
|
}
|
2001-07-14 06:10:59 +04:00
|
|
|
|
2003-01-01 18:18:25 +03:00
|
|
|
if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
|
2001-07-30 01:26:07 +04:00
|
|
|
return error;
|
|
|
|
*stackp += sizeof(zero);
|
2001-07-14 06:10:59 +04:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
if ((error = copyoutstr(emea->filename,
|
We now have the exact stack initial stack layout of Darwin:
macho_hdr, argc, *argv, NULL, *envp, NULL, progname, NULL,
*progname, **argv, **envp
Where progname is a pointer to the program name as given in the first
argument to execve(), and macho_hdr a pointer to the Mach-O header at
the beginning of the executable file.
2002-11-21 22:53:40 +03:00
|
|
|
*stackp, MAXPATHLEN, &len)) != 0) {
|
2001-07-30 01:26:07 +04:00
|
|
|
DPRINTF(("mach: copyout path failed\n"));
|
|
|
|
return error;
|
|
|
|
}
|
2001-10-28 07:47:27 +03:00
|
|
|
*stackp += len + 1;
|
|
|
|
|
|
|
|
/* We don't need this anymore */
|
We now have the exact stack initial stack layout of Darwin:
macho_hdr, argc, *argv, NULL, *envp, NULL, progname, NULL,
*progname, **argv, **envp
Where progname is a pointer to the program name as given in the first
argument to execve(), and macho_hdr a pointer to the Mach-O header at
the beginning of the executable file.
2002-11-21 22:53:40 +03:00
|
|
|
free(pack->ep_emul_arg, M_EXEC);
|
2001-10-28 07:47:27 +03:00
|
|
|
pack->ep_emul_arg = NULL;
|
2001-07-14 06:10:59 +04:00
|
|
|
|
|
|
|
len = len % sizeof(zero);
|
|
|
|
if (len) {
|
2005-02-27 01:58:54 +03:00
|
|
|
if ((error = copyout(&zero, *stackp, len)) != 0)
|
2001-07-30 01:26:07 +04:00
|
|
|
return error;
|
|
|
|
*stackp += len;
|
2001-07-14 06:10:59 +04:00
|
|
|
}
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
if ((error = copyout(&zero, *stackp, sizeof(zero))) != 0)
|
2001-07-30 01:26:07 +04:00
|
|
|
return error;
|
|
|
|
*stackp += sizeof(zero);
|
2001-07-14 06:10:59 +04:00
|
|
|
|
2001-07-30 01:26:07 +04:00
|
|
|
return 0;
|
2001-07-14 06:10:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2002-12-07 18:33:01 +03:00
|
|
|
exec_mach_probe(path)
|
|
|
|
char **path;
|
|
|
|
{
|
2001-10-28 07:47:27 +03:00
|
|
|
*path = (char *)emul_mach.e_path;
|
2001-07-14 06:10:59 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2002-12-07 18:33:01 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
void
|
2002-12-07 18:33:01 +03:00
|
|
|
mach_e_proc_exec(p, epp)
|
|
|
|
struct proc *p;
|
|
|
|
struct exec_package *epp;
|
|
|
|
{
|
|
|
|
mach_e_proc_init(p, p->p_vmspace);
|
|
|
|
|
2003-12-20 22:43:17 +03:00
|
|
|
if (p->p_emul != epp->ep_es->es_emul)
|
|
|
|
mach_e_lwp_fork(NULL, proc_representative_lwp(p));
|
|
|
|
|
2002-12-07 18:33:01 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-11-21 01:05:25 +03:00
|
|
|
void
|
2004-08-08 12:42:03 +04:00
|
|
|
mach_e_proc_fork(p, parent, forkflags)
|
2002-12-07 18:33:01 +03:00
|
|
|
struct proc *p;
|
|
|
|
struct proc *parent;
|
2004-08-08 12:42:03 +04:00
|
|
|
int forkflags;
|
2003-11-21 01:05:25 +03:00
|
|
|
{
|
2005-02-27 01:58:54 +03:00
|
|
|
mach_e_proc_fork1(p, parent, 1);
|
2003-11-21 01:05:25 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
void
|
2003-11-21 01:05:25 +03:00
|
|
|
mach_e_proc_fork1(p, parent, allocate)
|
|
|
|
struct proc *p;
|
|
|
|
struct proc *parent;
|
|
|
|
int allocate;
|
2002-12-07 18:33:01 +03:00
|
|
|
{
|
|
|
|
struct mach_emuldata *med1;
|
|
|
|
struct mach_emuldata *med2;
|
2003-12-06 18:15:19 +03:00
|
|
|
int i;
|
2002-12-07 18:33:01 +03:00
|
|
|
|
2003-11-21 01:05:25 +03:00
|
|
|
/*
|
|
|
|
* For Darwin binaries, p->p_emuldata has already been
|
|
|
|
* allocated, no need to throw it away and allocate it again.
|
|
|
|
*/
|
|
|
|
if (allocate)
|
|
|
|
p->p_emuldata = NULL;
|
2002-12-07 18:33:01 +03:00
|
|
|
|
2003-12-18 04:10:20 +03:00
|
|
|
/* Use parent's vmspace because our vmspace may not be set up yet */
|
2002-12-07 18:33:01 +03:00
|
|
|
mach_e_proc_init(p, parent->p_vmspace);
|
|
|
|
|
|
|
|
med1 = p->p_emuldata;
|
|
|
|
med2 = parent->p_emuldata;
|
2003-11-18 04:40:18 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2003-12-06 18:15:19 +03:00
|
|
|
* Exception ports are inherited between forks,
|
2005-02-27 01:58:54 +03:00
|
|
|
* but we need to double their reference counts,
|
2003-12-06 18:15:19 +03:00
|
|
|
* since the ports are referenced by rights in the
|
|
|
|
* parent and in the child.
|
2003-12-25 02:22:22 +03:00
|
|
|
*
|
|
|
|
* XXX we need to convert all the parent's rights
|
|
|
|
* to the child namespace. This will make the
|
|
|
|
* following fixup obsolete.
|
2003-12-06 18:15:19 +03:00
|
|
|
*/
|
|
|
|
for (i = 0; i <= MACH_EXC_MAX; i++) {
|
|
|
|
med1->med_exc[i] = med2->med_exc[i];
|
|
|
|
if (med1->med_exc[i] != NULL)
|
|
|
|
med1->med_exc[i]->mp_refcount *= 2;
|
|
|
|
}
|
2002-12-07 18:33:01 +03:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
void
|
2002-12-07 18:33:01 +03:00
|
|
|
mach_e_proc_init(p, vmspace)
|
|
|
|
struct proc *p;
|
|
|
|
struct vmspace *vmspace;
|
|
|
|
{
|
|
|
|
struct mach_emuldata *med;
|
2003-11-18 17:11:33 +03:00
|
|
|
struct mach_right *mr;
|
2002-12-07 18:33:01 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
|
|
|
* Initialize various things if needed.
|
|
|
|
* XXX Not the best place for this.
|
2002-12-15 03:40:24 +03:00
|
|
|
*/
|
|
|
|
if (mach_cold == 1)
|
|
|
|
mach_init();
|
|
|
|
|
2003-11-18 17:11:33 +03:00
|
|
|
/*
|
2003-12-18 04:10:20 +03:00
|
|
|
* For Darwin binaries, p->p_emuldata is always allocated:
|
2003-11-21 01:05:25 +03:00
|
|
|
* from the previous program if it had the same emulation,
|
2005-02-27 01:58:54 +03:00
|
|
|
* or from darwin_e_proc_exec(). In the latter situation,
|
2003-11-18 17:11:33 +03:00
|
|
|
* everything has been set to zero.
|
|
|
|
*/
|
2003-11-21 01:05:25 +03:00
|
|
|
if (!p->p_emuldata) {
|
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (p->p_emul != &emul_mach)
|
|
|
|
printf("mach_emuldata allocated for non Mach binary\n");
|
|
|
|
#endif
|
2002-12-07 18:33:01 +03:00
|
|
|
p->p_emuldata = malloc(sizeof(struct mach_emuldata),
|
|
|
|
M_EMULDATA, M_WAITOK | M_ZERO);
|
2003-11-21 01:05:25 +03:00
|
|
|
}
|
2002-12-07 18:33:01 +03:00
|
|
|
|
|
|
|
med = (struct mach_emuldata *)p->p_emuldata;
|
|
|
|
|
2003-11-18 17:11:33 +03:00
|
|
|
/*
|
2005-02-27 01:58:54 +03:00
|
|
|
* p->p_emudata has med_inited set if we inherited it from
|
2003-11-18 17:11:33 +03:00
|
|
|
* the program that called exec(). In that situation, we
|
|
|
|
* must free anything that will not be used anymore.
|
|
|
|
*/
|
|
|
|
if (med->med_inited != 0) {
|
|
|
|
lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
|
|
|
|
while ((mr = LIST_FIRST(&med->med_right)) != NULL)
|
|
|
|
mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
|
|
|
|
lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
|
|
|
|
|
2003-11-18 18:57:13 +03:00
|
|
|
/*
|
2003-11-25 16:22:38 +03:00
|
|
|
* Do not touch special ports. Some other process (eg: gdb)
|
|
|
|
* might have grabbed them to control the process, and the
|
2003-12-18 04:10:20 +03:00
|
|
|
* controller intend to keep in control even after exec().
|
2003-11-18 18:57:13 +03:00
|
|
|
*/
|
2003-11-25 16:22:38 +03:00
|
|
|
} else {
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2003-12-18 04:10:20 +03:00
|
|
|
* p->p_emuldata is uninitialized. Go ahead and initialize it.
|
2003-11-25 16:22:38 +03:00
|
|
|
*/
|
|
|
|
LIST_INIT(&med->med_right);
|
|
|
|
lockinit(&med->med_rightlock, PZERO|PCATCH, "mach_right", 0, 0);
|
2003-12-25 02:22:22 +03:00
|
|
|
lockinit(&med->med_exclock, PZERO, "exclock", 0, 0);
|
2003-11-25 16:22:38 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
|
|
|
* For debugging purpose, it's convenient to have each process
|
2003-11-25 16:22:38 +03:00
|
|
|
* using distinct port names, so we prefix the first port name
|
2005-02-27 01:58:54 +03:00
|
|
|
* by the PID. Darwin does not do that, but we can remove it
|
2003-11-25 16:22:38 +03:00
|
|
|
* when we want, it will not hurt.
|
|
|
|
*/
|
|
|
|
med->med_nextright = p->p_pid << 16;
|
2002-12-15 03:40:24 +03:00
|
|
|
|
2003-11-25 16:22:38 +03:00
|
|
|
/*
|
|
|
|
* Initialize special ports. Bootstrap port is shared
|
|
|
|
* among all Mach processes in our implementation.
|
|
|
|
*/
|
|
|
|
med->med_kernel = mach_port_get();
|
|
|
|
med->med_host = mach_port_get();
|
2002-12-15 03:40:24 +03:00
|
|
|
|
2003-11-25 16:22:38 +03:00
|
|
|
med->med_kernel->mp_flags |= MACH_MP_INKERNEL;
|
|
|
|
med->med_host->mp_flags |= MACH_MP_INKERNEL;
|
2003-03-29 14:04:08 +03:00
|
|
|
|
2003-11-25 16:22:38 +03:00
|
|
|
med->med_kernel->mp_data = (void *)p;
|
|
|
|
med->med_host->mp_data = (void *)p;
|
2003-03-29 14:04:08 +03:00
|
|
|
|
2003-11-25 16:22:38 +03:00
|
|
|
med->med_kernel->mp_datatype = MACH_MP_PROC;
|
|
|
|
med->med_host->mp_datatype = MACH_MP_PROC;
|
2003-02-06 02:58:09 +03:00
|
|
|
|
2004-01-02 01:48:54 +03:00
|
|
|
MACH_PORT_REF(med->med_kernel);
|
|
|
|
MACH_PORT_REF(med->med_host);
|
2002-12-13 02:18:20 +03:00
|
|
|
|
2003-11-25 16:22:38 +03:00
|
|
|
med->med_bootstrap = mach_bootstrap_port;
|
2004-01-02 01:48:54 +03:00
|
|
|
MACH_PORT_REF(med->med_bootstrap);
|
2003-11-25 16:22:38 +03:00
|
|
|
}
|
2002-12-27 22:57:47 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2003-11-18 17:11:33 +03:00
|
|
|
* Exception ports are inherited accross exec() calls.
|
2005-02-27 01:58:54 +03:00
|
|
|
* If the structure is initialized, the ports are just
|
2003-11-18 17:11:33 +03:00
|
|
|
* here, so leave them untouched. If the structure is
|
2005-02-27 01:58:54 +03:00
|
|
|
* uninitalized, the ports are all set to zero, which
|
2003-11-25 16:22:38 +03:00
|
|
|
* is the default, so do not touch them either.
|
2003-11-18 17:11:33 +03:00
|
|
|
*/
|
2003-03-29 14:04:08 +03:00
|
|
|
|
2003-02-02 22:06:31 +03:00
|
|
|
med->med_dirty_thid = 1;
|
2003-04-06 21:58:49 +04:00
|
|
|
med->med_suspend = 0;
|
2003-11-18 17:11:33 +03:00
|
|
|
med->med_inited = 1;
|
|
|
|
|
2002-12-07 18:33:01 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
void
|
2002-12-07 18:33:01 +03:00
|
|
|
mach_e_proc_exit(p)
|
|
|
|
struct proc *p;
|
|
|
|
{
|
2002-12-17 21:42:54 +03:00
|
|
|
struct mach_emuldata *med;
|
|
|
|
struct mach_right *mr;
|
2003-12-06 18:15:19 +03:00
|
|
|
int i;
|
2002-12-07 18:33:01 +03:00
|
|
|
|
2004-01-02 01:48:54 +03:00
|
|
|
/* There is only one lwp remaining... */
|
2003-12-20 22:43:17 +03:00
|
|
|
mach_e_lwp_exit(proc_representative_lwp(p));
|
|
|
|
|
2002-12-17 21:42:54 +03:00
|
|
|
med = (struct mach_emuldata *)p->p_emuldata;
|
|
|
|
|
2003-01-03 16:40:04 +03:00
|
|
|
lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
|
2002-12-20 01:23:06 +03:00
|
|
|
while ((mr = LIST_FIRST(&med->med_right)) != NULL)
|
2003-01-02 15:46:06 +03:00
|
|
|
mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
|
2003-01-03 16:40:04 +03:00
|
|
|
lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
|
2002-12-17 21:42:54 +03:00
|
|
|
|
2004-01-02 01:48:54 +03:00
|
|
|
MACH_PORT_UNREF(med->med_bootstrap);
|
2003-12-06 20:04:50 +03:00
|
|
|
|
2003-12-25 02:22:22 +03:00
|
|
|
/*
|
|
|
|
* If the lock on this task exception handler is held,
|
|
|
|
* release it now as it will never be released by the
|
|
|
|
* exception handler.
|
|
|
|
*/
|
|
|
|
if (lockstatus(&med->med_exclock) != 0)
|
2003-12-28 16:28:39 +03:00
|
|
|
wakeup(&med->med_exclock);
|
2003-12-25 02:22:22 +03:00
|
|
|
|
2005-02-27 01:58:54 +03:00
|
|
|
/*
|
2003-12-06 20:04:50 +03:00
|
|
|
* If the kernel and host port are still referenced, remove
|
2005-02-27 01:58:54 +03:00
|
|
|
* the pointer to this process' struct proc, as it will
|
2003-12-06 20:04:50 +03:00
|
|
|
* become invalid once the process will exit.
|
|
|
|
*/
|
2004-01-02 01:48:54 +03:00
|
|
|
med->med_kernel->mp_datatype = MACH_MP_NONE;
|
|
|
|
med->med_kernel->mp_data = NULL;
|
|
|
|
MACH_PORT_UNREF(med->med_kernel);
|
2003-12-06 20:04:50 +03:00
|
|
|
|
2004-01-02 01:48:54 +03:00
|
|
|
med->med_host->mp_datatype = MACH_MP_NONE;
|
|
|
|
med->med_host->mp_data = NULL;
|
|
|
|
MACH_PORT_UNREF(med->med_host);
|
2002-12-17 21:42:54 +03:00
|
|
|
|
2003-12-06 18:15:19 +03:00
|
|
|
for (i = 0; i <= MACH_EXC_MAX; i++)
|
2004-01-02 01:48:54 +03:00
|
|
|
if (med->med_exc[i] != NULL)
|
|
|
|
MACH_PORT_UNREF(med->med_exc[i]);
|
2003-11-18 17:11:33 +03:00
|
|
|
|
2002-12-17 21:42:54 +03:00
|
|
|
free(med, M_EMULDATA);
|
|
|
|
p->p_emuldata = NULL;
|
|
|
|
|
2002-12-07 18:33:01 +03:00
|
|
|
return;
|
|
|
|
}
|
2002-12-15 03:40:24 +03:00
|
|
|
|
2003-12-20 22:43:17 +03:00
|
|
|
void
|
|
|
|
mach_e_lwp_fork(l1, l2)
|
|
|
|
struct lwp *l1;
|
|
|
|
struct lwp *l2;
|
|
|
|
{
|
|
|
|
struct mach_lwp_emuldata *mle;
|
|
|
|
|
|
|
|
mle = malloc(sizeof(*mle), M_EMULDATA, M_WAITOK);
|
|
|
|
l2->l_emuldata = mle;
|
|
|
|
|
|
|
|
mle->mle_kernel = mach_port_get();
|
2004-01-02 01:48:54 +03:00
|
|
|
MACH_PORT_REF(mle->mle_kernel);
|
2003-12-20 22:43:17 +03:00
|
|
|
|
|
|
|
mle->mle_kernel->mp_flags |= MACH_MP_INKERNEL;
|
|
|
|
mle->mle_kernel->mp_datatype = MACH_MP_LWP;
|
|
|
|
mle->mle_kernel->mp_data = (void *)l2;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* Nothing to copy from parent thread for now */
|
|
|
|
if (l1 != NULL);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mach_e_lwp_exit(l)
|
|
|
|
struct lwp *l;
|
|
|
|
{
|
|
|
|
struct mach_lwp_emuldata *mle;
|
|
|
|
|
2003-12-30 03:15:46 +03:00
|
|
|
mach_semaphore_cleanup(l);
|
|
|
|
|
2003-12-20 22:43:17 +03:00
|
|
|
#ifdef DIAGNOSTIC
|
|
|
|
if (l->l_emuldata == NULL) {
|
|
|
|
printf("lwp_emuldata already freed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
mle = l->l_emuldata;
|
|
|
|
|
|
|
|
mle->mle_kernel->mp_data = NULL;
|
|
|
|
mle->mle_kernel->mp_datatype = MACH_MP_NONE;
|
2004-01-02 01:48:54 +03:00
|
|
|
MACH_PORT_UNREF(mle->mle_kernel);
|
2003-12-20 22:43:17 +03:00
|
|
|
|
|
|
|
free(mle, M_EMULDATA);
|
|
|
|
l->l_emuldata = NULL;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-12-15 03:40:24 +03:00
|
|
|
static void
|
|
|
|
mach_init(void)
|
|
|
|
{
|
|
|
|
mach_semaphore_init();
|
|
|
|
mach_message_init();
|
|
|
|
mach_port_init();
|
|
|
|
|
|
|
|
mach_cold = 0;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|