Rework Mach exception and Darwin's ptrace. gdb is now able to attach a
remote process. This new implementation also passes all the test programs I've written so far. - When exceptions come from traps, no UNIX signal should evet be sent. - Add a lock to ensure a debugger handles only one exception at a time - Use a structure to hold flavor and behavior in exception ports, instead of stuffing the two argument into an int. - Implement new Mach services: thread_suspend, thread_resume and thread_abort - Implement Darwin's ptrace PT_ATTACHEXC and PT_THUPDATE commands - Handle NULL second argument correctly in sigprocmask. - One mistake in the last commit (darwin_tracesig prototype)
This commit is contained in:
parent
3bc6a59873
commit
834aafd284
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: darwin_ptrace.c,v 1.2 2003/12/04 23:59:50 manu Exp $ */
|
||||
/* $NetBSD: darwin_ptrace.c,v 1.3 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: darwin_ptrace.c,v 1.2 2003/12/04 23:59:50 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: darwin_ptrace.c,v 1.3 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -56,47 +56,8 @@ __KERNEL_RCSID(0, "$NetBSD: darwin_ptrace.c,v 1.2 2003/12/04 23:59:50 manu Exp $
|
||||
#include <compat/darwin/darwin_ptrace.h>
|
||||
#include <compat/darwin/darwin_syscallargs.h>
|
||||
|
||||
#if 0
|
||||
#define ISSET(t, f) ((t) & (f))
|
||||
|
||||
static inline int ptrace_sanity_check(struct proc *, struct proc *);
|
||||
|
||||
/* Sanity checks copied from native sys_ptrace() */
|
||||
static inline int
|
||||
ptrace_sanity_check(p, t)
|
||||
struct proc *p;
|
||||
struct proc *t;
|
||||
{
|
||||
/*
|
||||
* You can't do what you want to the process if:
|
||||
* (1) It's not being traced at all,
|
||||
*/
|
||||
if (!ISSET(t->p_flag, P_TRACED))
|
||||
return (EPERM);
|
||||
|
||||
/*
|
||||
* (2) it's being traced by procfs (which has
|
||||
* different signal delivery semantics),
|
||||
*/
|
||||
if (ISSET(t->p_flag, P_FSTRACE))
|
||||
return (EBUSY);
|
||||
|
||||
/*
|
||||
* (3) it's not being traced by _you_, or
|
||||
*/
|
||||
if (t->p_pptr != p)
|
||||
return (EBUSY);
|
||||
|
||||
/*
|
||||
* (4) it's not currently stopped.
|
||||
*/
|
||||
if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
|
||||
return (EBUSY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
darwin_sys_ptrace(l, v, retval)
|
||||
struct lwp *l;
|
||||
@ -115,32 +76,100 @@ darwin_sys_ptrace(l, v, retval)
|
||||
struct proc *t; /* target process */
|
||||
int error;
|
||||
|
||||
ded = (struct darwin_emuldata *)p->p_emuldata;
|
||||
|
||||
switch (req) {
|
||||
case DARWIN_PT_ATTACHEXC:
|
||||
if ((t = pfind(SCARG(uap, pid))) == NULL)
|
||||
return ESRCH;
|
||||
|
||||
if (t->p_emul != &emul_darwin)
|
||||
return ESRCH;
|
||||
ded = t->p_emuldata;
|
||||
|
||||
if (ded->ded_flags & DARWIN_DED_SIGEXC)
|
||||
return EBUSY;
|
||||
|
||||
ded->ded_flags |= DARWIN_DED_SIGEXC;
|
||||
|
||||
SCARG(uap, req) = PT_ATTACH;
|
||||
if ((error = sys_ptrace(l, v, retval)) != 0)
|
||||
ded->ded_flags &= ~DARWIN_DED_SIGEXC;
|
||||
|
||||
return error;
|
||||
break;
|
||||
|
||||
case DARWIN_PT_SIGEXC:
|
||||
ded = (struct darwin_emuldata *)p->p_emuldata;
|
||||
if ((p->p_flag & P_TRACED) == 0)
|
||||
return EBUSY;
|
||||
|
||||
ded->ded_flags |= DARWIN_DED_SIGEXC;
|
||||
break;
|
||||
|
||||
case DARWIN_PT_DETACH:
|
||||
case DARWIN_PT_DETACH: {
|
||||
int had_sigexc = 0;
|
||||
|
||||
if ((t = pfind(SCARG(uap, pid))) == NULL)
|
||||
return (ESRCH);
|
||||
|
||||
/*
|
||||
* Clear signal-as-exceptions flag if detaching is
|
||||
* successful and if it is a Darwin process.
|
||||
*/
|
||||
if (((error = sys_ptrace(l, v, retval)) == 0) &&
|
||||
(t->p_emul != &emul_darwin)) {
|
||||
ded = (struct darwin_emuldata *)t->p_emuldata;
|
||||
ded->ded_flags &= ~DARWIN_DED_SIGEXC;
|
||||
if ((t->p_emul == &emul_darwin) &&
|
||||
(t->p_flag & P_TRACED) &&
|
||||
(t->p_pptr == p)) {
|
||||
ded = t->p_emuldata;
|
||||
if (ded->ded_flags & DARWIN_DED_SIGEXC) {
|
||||
had_sigexc = 1;
|
||||
ded->ded_flags &= ~DARWIN_DED_SIGEXC;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the process is not marked as stopped,
|
||||
* sys_ptrace sanity checks will return EBUSY.
|
||||
*/
|
||||
proc_stop(t, 0);
|
||||
|
||||
if ((error = sys_ptrace(l, v, retval)) != 0) {
|
||||
proc_unstop(t);
|
||||
if (had_sigexc)
|
||||
ded->ded_flags |= DARWIN_DED_SIGEXC;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DARWIN_PT_THUPDATE: {
|
||||
int signo = SCARG(uap, data);
|
||||
|
||||
if ((t = pfind(SCARG(uap, pid))) == NULL)
|
||||
return ESRCH;
|
||||
|
||||
/* Checks from native ptrace */
|
||||
if (!ISSET(t->p_flag, P_TRACED))
|
||||
return EPERM;
|
||||
|
||||
if (ISSET(t->p_flag, P_FSTRACE))
|
||||
return EBUSY;
|
||||
|
||||
if (t->p_pptr != p)
|
||||
return EBUSY;
|
||||
|
||||
#if 0
|
||||
if (t->p_stat != SSTOP || !ISSET(t->p_flag, P_WAITED))
|
||||
return EBUSY;
|
||||
#endif
|
||||
if ((signo < 0) || (signo > NSIG))
|
||||
return EINVAL;
|
||||
|
||||
t->p_xstat = signo;
|
||||
if (signo != 0)
|
||||
sigaddset(&p->p_sigctx.ps_siglist, signo);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DARWIN_PT_READ_U:
|
||||
case DARWIN_PT_WRITE_U:
|
||||
case DARWIN_PT_STEP:
|
||||
case DARWIN_PT_THUPDATE:
|
||||
case DARWIN_PT_ATTACHEXC:
|
||||
case DARWIN_PT_FORCEQUOTA:
|
||||
case DARWIN_PT_DENY_ATTACH:
|
||||
printf("darwin_sys_ptrace: unimplemented command %d\n", req);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: darwin_signal.c,v 1.16 2003/12/24 22:57:22 manu Exp $ */
|
||||
/* $NetBSD: darwin_signal.c,v 1.17 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: darwin_signal.c,v 1.16 2003/12/24 22:57:22 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: darwin_signal.c,v 1.17 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -138,48 +138,29 @@ darwin_trapsignal(l, ksi)
|
||||
|
||||
int
|
||||
darwin_tracesig(p, signo)
|
||||
struct proc *l;
|
||||
struct proc *p;
|
||||
int signo;
|
||||
{
|
||||
struct proc *p = l->l_proc;
|
||||
struct darwin_emuldata *ded;
|
||||
struct lwp *l;
|
||||
int code[2];
|
||||
int error;
|
||||
int signo;
|
||||
|
||||
/*
|
||||
* Don't generate Mach exeption for non
|
||||
* maskable, stop and continue signals
|
||||
*/
|
||||
if (sigprop[signo] & (SA_CANTMASK | SA_STOP | SA_CONT | SA_TTYSTOP))
|
||||
return EINVAL;
|
||||
|
||||
/* Don't send an exception if the signal is masked or ignored */
|
||||
if ((p->p_flag & P_TRACED) == 0) {
|
||||
if ((sigismember(&p->p_sigctx.ps_sigignore, signo)) ||
|
||||
(sigismember(&p->p_sigctx.ps_sigmask, signo)))
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send signals as software exception if the process requested that.
|
||||
* If the process does not have softsignals,
|
||||
* we are done, normal signal delivery should
|
||||
* occur.
|
||||
*/
|
||||
ded = (struct darwin_emuldata *)p->p_emuldata;
|
||||
if (ded->ded_flags & DARWIN_DED_SIGEXC) {
|
||||
code[0] = MACH_SOFT_SIGNAL;
|
||||
code[1] = signo;
|
||||
error = mach_exception(l, MACH_EXC_SOFTWARE, code);
|
||||
if ((ded->ded_flags & DARWIN_DED_SIGEXC) == 0)
|
||||
return 0;
|
||||
|
||||
/* Like if the signal was sent, wakeup any waiting process */
|
||||
if ((error == 0) &&
|
||||
p->p_sigctx.ps_sigwaited &&
|
||||
sigismember(p->p_sigctx.ps_sigwait, signo) &&
|
||||
(p->p_stat != SSTOP))
|
||||
wakeup_one(&p->p_sigctx.ps_sigwait);
|
||||
|
||||
return error;
|
||||
}
|
||||
code[0] = MACH_SOFT_SIGNAL;
|
||||
code[1] = signo;
|
||||
l = proc_representative_lwp(p);
|
||||
error = mach_exception(l, MACH_EXC_SOFTWARE, code);
|
||||
|
||||
/* Inhibit normal signal delivery */
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
@ -199,7 +180,7 @@ darwin_sys_sigprocmask(l, v, retval)
|
||||
int error;
|
||||
sigset13_t kdset, kdoset;
|
||||
sigset_t kbset, kboset;
|
||||
sigset_t *ubset;
|
||||
sigset_t *ubset = NULL;
|
||||
sigset_t *uboset = NULL;
|
||||
|
||||
caddr_t sg = stackgap_init(p, 0);
|
||||
@ -207,13 +188,16 @@ darwin_sys_sigprocmask(l, v, retval)
|
||||
if (SCARG(uap, oset) != NULL)
|
||||
uboset = stackgap_alloc(p, &sg, sizeof(*uboset));
|
||||
|
||||
if ((error = copyin(SCARG(uap, set), &kdset, sizeof(kdset))) != 0)
|
||||
return error;
|
||||
if (SCARG(uap, set) != NULL) {
|
||||
error = copyin(SCARG(uap, set), &kdset, sizeof(kdset));
|
||||
if (error != 0)
|
||||
return error;
|
||||
|
||||
native_sigset13_to_sigset(&kdset, &kbset);
|
||||
native_sigset13_to_sigset(&kdset, &kbset);
|
||||
|
||||
if ((error = copyout(&kbset, ubset, sizeof(kbset))) != 0)
|
||||
return error;
|
||||
if ((error = copyout(&kbset, ubset, sizeof(kbset))) != 0)
|
||||
return error;
|
||||
}
|
||||
|
||||
SCARG(&cup, how) = SCARG(uap, how);
|
||||
SCARG(&cup, set) = ubset;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_exception.c,v 1.1 2003/12/09 12:13:44 manu Exp $ */
|
||||
/* $NetBSD: mach_exception.c,v 1.2 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
@ -37,9 +37,10 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.1 2003/12/09 12:13:44 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.2 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_compat_darwin.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -47,8 +48,13 @@ __KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.1 2003/12/09 12:13:44 manu Exp
|
||||
#include <sys/proc.h>
|
||||
#include <sys/malloc.h>
|
||||
|
||||
#ifdef COMPAT_DARWIN
|
||||
#include <compat/darwin/darwin_exec.h>
|
||||
#endif
|
||||
|
||||
#include <compat/mach/mach_types.h>
|
||||
#include <compat/mach/mach_exec.h>
|
||||
#include <compat/mach/mach_errno.h>
|
||||
#include <compat/mach/mach_thread.h>
|
||||
#include <compat/mach/mach_exception.h>
|
||||
#include <compat/mach/mach_message.h>
|
||||
@ -119,8 +125,8 @@ mach_trapsignal1(l, ksi)
|
||||
}
|
||||
|
||||
int
|
||||
mach_exception(l, exc, code)
|
||||
struct lwp *l;
|
||||
mach_exception(exc_l, exc, code)
|
||||
struct lwp *exc_l; /* currently running lwp */
|
||||
int exc;
|
||||
int *code;
|
||||
{
|
||||
@ -128,32 +134,47 @@ mach_exception(l, exc, code)
|
||||
mach_msg_header_t *msgh;
|
||||
size_t msglen;
|
||||
struct mach_right *exc_mr;
|
||||
struct mach_emuldata *med;
|
||||
struct mach_emuldata *exc_med;
|
||||
struct mach_lwp_emuldata *exc_mle;
|
||||
struct mach_emuldata *catcher_med;
|
||||
struct mach_right *kernel_mr;
|
||||
struct lwp *catcher_lwp;
|
||||
struct mach_right *task;
|
||||
struct mach_right *thread;
|
||||
struct lwp *catcher_l; /* The lwp catching the exception */
|
||||
struct mach_right *exc_task;
|
||||
struct mach_right *exc_thread;
|
||||
struct mach_port *exc_port;
|
||||
int error;
|
||||
struct mach_exc_info *mei;
|
||||
int error = 0;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (exc_l == NULL) {
|
||||
printf("mach_exception: exc_l = %p\n", exc_l);
|
||||
return ESRCH;
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_exception: pid %d, exc %d, code (%d, %d)\n",
|
||||
l->l_proc->p_pid, exc, code[0], code[1]);
|
||||
printf("mach_exception: %d.%d, exc %d, code (%d, %d)\n",
|
||||
exc_l->l_proc->p_pid, exc_l->l_lid, exc, code[0], code[1]);
|
||||
#endif
|
||||
/*
|
||||
* No exception if there is no exception port or if it has no receiver
|
||||
*/
|
||||
med = l->l_proc->p_emuldata;
|
||||
if (((exc_port = med->med_exc[exc]) == NULL) ||
|
||||
exc_mle = exc_l->l_emuldata;
|
||||
exc_med = exc_l->l_proc->p_emuldata;
|
||||
if (((exc_port = exc_med->med_exc[exc]) == NULL) ||
|
||||
(exc_port->mp_recv == NULL))
|
||||
return EINVAL;
|
||||
|
||||
#ifdef DEBUG_MACH
|
||||
printf("catcher is %d.%d, state %d\n",
|
||||
exc_port->mp_recv->mr_lwp->l_proc->p_pid,
|
||||
exc_port->mp_recv->mr_lwp->l_lid,
|
||||
exc_port->mp_recv->mr_lwp->l_proc->p_stat);
|
||||
#endif
|
||||
/*
|
||||
* Don't send exceptions to dying processes
|
||||
*/
|
||||
if (P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc))
|
||||
return EINVAL;
|
||||
return ESRCH;
|
||||
|
||||
/*
|
||||
* XXX Avoid a nasty deadlock because process in TX state
|
||||
@ -175,33 +196,38 @@ mach_exception(l, exc, code)
|
||||
* a dying parent, a signal is sent instead of the
|
||||
* notification, this fixes the problem.
|
||||
*/
|
||||
if ((l->l_proc->p_flag & P_TRACED) &&
|
||||
(l->l_proc->p_pptr->p_flag & P_WEXIT)) {
|
||||
if ((exc_l->l_proc->p_flag & P_TRACED) &&
|
||||
(exc_l->l_proc->p_pptr->p_flag & P_WEXIT)) {
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_exception: deadlock avoided\n");
|
||||
#endif
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (exc_port->mp_datatype != MACH_MP_EXC_INFO) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (exc_port->mp_datatype != MACH_MP_EXC_FLAGS)
|
||||
printf("mach_exception: unexpected datatype");
|
||||
#endif
|
||||
behavior = (int)exc_port->mp_data >> 16;
|
||||
flavor = (int)exc_port->mp_data & 0xffff;
|
||||
return EINVAL;
|
||||
}
|
||||
mei = exc_port->mp_data;
|
||||
behavior = mei->mei_behavior;
|
||||
flavor = mei->mei_flavor;
|
||||
|
||||
/*
|
||||
* We want the port names in the target process, that is,
|
||||
* the process with receive right for exc_port.
|
||||
*/
|
||||
catcher_lwp = exc_port->mp_recv->mr_lwp;
|
||||
catcher_med = catcher_lwp->l_proc->p_emuldata;
|
||||
exc_mr = mach_right_get(exc_port, catcher_lwp, MACH_PORT_TYPE_SEND, 0);
|
||||
catcher_l = exc_port->mp_recv->mr_lwp;
|
||||
catcher_med = catcher_l->l_proc->p_emuldata;
|
||||
exc_mr = mach_right_get(exc_port, catcher_l, MACH_PORT_TYPE_SEND, 0);
|
||||
kernel_mr = mach_right_get(catcher_med->med_kernel,
|
||||
catcher_lwp, MACH_PORT_TYPE_SEND, 0);
|
||||
catcher_l, MACH_PORT_TYPE_SEND, 0);
|
||||
|
||||
/* XXX Thread and task should have different ports */
|
||||
task = mach_right_get(med->med_kernel,
|
||||
catcher_lwp, MACH_PORT_TYPE_SEND, 0);
|
||||
thread = mach_right_get(med->med_kernel,
|
||||
catcher_lwp, MACH_PORT_TYPE_SEND, 0);
|
||||
exc_task = mach_right_get(exc_med->med_kernel,
|
||||
catcher_l, MACH_PORT_TYPE_SEND, 0);
|
||||
exc_thread = mach_right_get(exc_mle->mle_kernel,
|
||||
catcher_l, MACH_PORT_TYPE_SEND, 0);
|
||||
|
||||
switch (behavior) {
|
||||
case MACH_EXCEPTION_DEFAULT: {
|
||||
@ -220,13 +246,15 @@ mach_exception(l, exc, code)
|
||||
req->req_msgh.msgh_local_port = exc_mr->mr_name;
|
||||
req->req_msgh.msgh_id = MACH_EXC_RAISE_MSGID;
|
||||
|
||||
mach_add_port_desc(req, thread->mr_name);
|
||||
mach_add_port_desc(req, task->mr_name);
|
||||
mach_add_port_desc(req, exc_thread->mr_name);
|
||||
mach_add_port_desc(req, exc_task->mr_name);
|
||||
|
||||
req->req_exc = exc;
|
||||
req->req_codecount = 2;
|
||||
memcpy(&req->req_code[0], code, sizeof(req->req_code));
|
||||
|
||||
mach_set_trailer(req, msglen);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -250,11 +278,13 @@ mach_exception(l, exc, code)
|
||||
req->req_codecount = 2;
|
||||
memcpy(&req->req_code[0], code, sizeof(req->req_code));
|
||||
req->req_flavor = flavor;
|
||||
mach_thread_get_state_machdep(l, flavor, req->req_state, &dc);
|
||||
mach_thread_get_state_machdep(exc_l,
|
||||
flavor, req->req_state, &dc);
|
||||
|
||||
msglen = msglen -
|
||||
sizeof(req->req_state) +
|
||||
(dc * sizeof(req->req_state[0]));
|
||||
mach_set_trailer(req, msglen);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -277,20 +307,22 @@ mach_exception(l, exc, code)
|
||||
req->req_msgh.msgh_id = MACH_EXC_RAISE_STATE_IDENTITY_MSGID;
|
||||
req->req_body.msgh_descriptor_count = 2;
|
||||
|
||||
mach_add_port_desc(req, thread->mr_name);
|
||||
mach_add_port_desc(req, task->mr_name);
|
||||
mach_add_port_desc(req, exc_thread->mr_name);
|
||||
mach_add_port_desc(req, exc_task->mr_name);
|
||||
|
||||
req->req_exc = exc;
|
||||
req->req_codecount = 2;
|
||||
memcpy(&req->req_code[0], code, sizeof(req->req_code));
|
||||
req->req_flavor = flavor;
|
||||
mach_thread_get_state_machdep(l, flavor, req->req_state, &dc);
|
||||
/* Trailer */
|
||||
req->req_state[(dc / sizeof(req->req_state[0])) + 1] = 8;
|
||||
mach_thread_get_state_machdep(exc_l,
|
||||
flavor, req->req_state, &dc);
|
||||
|
||||
msglen = msglen -
|
||||
sizeof(req->req_state) +
|
||||
(dc * sizeof(req->req_state[0]));
|
||||
|
||||
mach_set_trailer(req, msglen);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -302,20 +334,44 @@ mach_exception(l, exc, code)
|
||||
|
||||
mach_set_trailer(msgh, msglen);
|
||||
|
||||
/*
|
||||
* Once an exception is sent on the exception port,
|
||||
* no new exception will be taken until the catcher
|
||||
* acknowledge the first one.
|
||||
*/
|
||||
lockmgr(&catcher_med->med_exclock, LK_EXCLUSIVE, NULL);
|
||||
|
||||
/*
|
||||
* If the catcher died, we are done.
|
||||
*/
|
||||
if (((exc_port = exc_med->med_exc[exc]) == NULL) ||
|
||||
(exc_port->mp_recv == NULL) ||
|
||||
(P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc)))
|
||||
return ESRCH;
|
||||
|
||||
(void)mach_message_get(msgh, msglen, exc_port, NULL);
|
||||
wakeup(exc_port->mp_recv->mr_sethead);
|
||||
|
||||
/*
|
||||
* The thread that caused the exception is now
|
||||
* supposed to wait for a reply to its message.
|
||||
* This is to avoid an endless loop on the same
|
||||
* exception.
|
||||
*/
|
||||
error = tsleep(kernel_mr->mr_port, PZERO|PCATCH, "mach_exc", 0);
|
||||
if ((error == ERESTART) || (error == EINTR))
|
||||
return error;
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_exception: %d.%d sleep on catcher_med->med_exclock = %p\n",
|
||||
exc_l->l_proc->p_pid, exc_l->l_lid, &catcher_med->med_exclock);
|
||||
#endif
|
||||
error = tsleep(&catcher_med->med_exclock, PZERO, "mach_exc", 0);
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_exception: %d.%d resumed, error = %d\n",
|
||||
exc_l->l_proc->p_pid, exc_l->l_lid, error);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
/*
|
||||
* Unlock the catcher's exception handler
|
||||
*/
|
||||
lockmgr(&catcher_med->med_exclock, LK_RELEASE, NULL);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -396,10 +452,8 @@ int
|
||||
mach_exception_raise(args)
|
||||
struct mach_trap_args *args;
|
||||
{
|
||||
mach_exception_raise_reply_t *rep;
|
||||
struct lwp *l = args->l;
|
||||
mach_port_t mn;
|
||||
struct mach_right *mr;
|
||||
mach_exception_raise_reply_t *rep;
|
||||
struct mach_emuldata *med;
|
||||
|
||||
/*
|
||||
@ -409,30 +463,38 @@ mach_exception_raise(args)
|
||||
*/
|
||||
rep = args->smsg;
|
||||
|
||||
/*
|
||||
* Sanity check the remote port: it should be a
|
||||
* right to the process' kernel port
|
||||
*/
|
||||
mn = rep->rep_msgh.msgh_remote_port;
|
||||
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_ALL_RIGHTS)) == 0)
|
||||
return MACH_SEND_INVALID_RIGHT;
|
||||
|
||||
med = (struct mach_emuldata *)l->l_proc->p_emuldata;
|
||||
if (med->med_kernel != mr->mr_port) {
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_exception_raise: remote port not kernel port\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This message is sent by the process catching the
|
||||
* exception to release the process that raised the exception.
|
||||
* We wake it up if the return value is 0 (no error), else
|
||||
* we should ignore this message.
|
||||
*/
|
||||
if (rep->rep_retval == 0)
|
||||
wakeup(mr->mr_port);
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_excpetion_raise: retval = %ld\n", (long)rep->rep_retval);
|
||||
#endif
|
||||
if (rep->rep_retval != 0)
|
||||
return 0;
|
||||
|
||||
med = l->l_proc->p_emuldata;
|
||||
|
||||
/*
|
||||
* Check for unexpected exception acknowledge, whereas
|
||||
* the kernel sent no exception message.
|
||||
*/
|
||||
if (lockstatus(&med->med_exclock) == 0) {
|
||||
#ifdef DEBUG_MACH
|
||||
printf("spurious mach_exception_raise\n");
|
||||
#endif
|
||||
return mach_msg_error(args, EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wakeup the thread that raised the exception.
|
||||
*/
|
||||
#ifdef DEBUG_MACH
|
||||
printf("mach_exception_raise: wakeup at %p\n", &med->med_exclock);
|
||||
#endif
|
||||
wakeup(&med->med_exclock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_exception.h,v 1.2 2003/12/18 01:10:20 grant Exp $ */
|
||||
/* $NetBSD: mach_exception.h,v 1.3 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003 The NetBSD Foundation, Inc.
|
||||
@ -142,6 +142,10 @@ typedef struct {
|
||||
mach_kern_return_t rep_retval;
|
||||
} mach_exception_raise_state_identity_reply_t;
|
||||
|
||||
struct mach_exc_info {
|
||||
int mei_flavor;
|
||||
int mei_behavior;
|
||||
};
|
||||
|
||||
void mach_trapsignal(struct lwp *, const struct ksiginfo *);
|
||||
int mach_trapsignal1(struct lwp *, const struct ksiginfo *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_exec.c,v 1.48 2003/12/20 19:43:17 manu Exp $ */
|
||||
/* $NetBSD: mach_exec.c,v 1.49 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.48 2003/12/20 19:43:17 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.49 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include "opt_syscall_debug.h"
|
||||
|
||||
@ -242,6 +242,10 @@ mach_e_proc_fork1(p, parent, allocate)
|
||||
* but we need to double their reference counts,
|
||||
* since the ports are referenced by rights in the
|
||||
* parent and in the child.
|
||||
*
|
||||
* XXX we need to convert all the parent's rights
|
||||
* to the child namespace. This will make the
|
||||
* following fixup obsolete.
|
||||
*/
|
||||
for (i = 0; i <= MACH_EXC_MAX; i++) {
|
||||
med1->med_exc[i] = med2->med_exc[i];
|
||||
@ -306,6 +310,7 @@ mach_e_proc_init(p, vmspace)
|
||||
*/
|
||||
LIST_INIT(&med->med_right);
|
||||
lockinit(&med->med_rightlock, PZERO|PCATCH, "mach_right", 0, 0);
|
||||
lockinit(&med->med_exclock, PZERO, "exclock", 0, 0);
|
||||
|
||||
/*
|
||||
* For debugging purpose, it's convenient to have each process
|
||||
@ -376,6 +381,14 @@ mach_e_proc_exit(p)
|
||||
if (--med->med_bootstrap->mp_refcount <= 0)
|
||||
mach_port_put(med->med_bootstrap);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
lockmgr(&med->med_exclock, LK_RELEASE, NULL);
|
||||
|
||||
/*
|
||||
* If the kernel and host port are still referenced, remove
|
||||
* the pointer to this process' struct proc, as it will
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_exec.h,v 1.25 2003/12/20 19:43:17 manu Exp $ */
|
||||
/* $NetBSD: mach_exec.h,v 1.26 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
@ -61,12 +61,11 @@ struct mach_emuldata {
|
||||
|
||||
int med_dirty_thid; /* Thread id not yet initialized */
|
||||
int med_suspend; /* Suspend semaphore */
|
||||
|
||||
struct lock med_exclock; /* Process exception handler lock */
|
||||
};
|
||||
|
||||
struct mach_lwp_emuldata {
|
||||
struct mach_port *mle_kernel; /* Thread's kernel port */
|
||||
struct mach_port *mle_exc; /* Exception we stop on */
|
||||
};
|
||||
|
||||
int exec_mach_copyargs(struct proc *, struct exec_package *,
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_message.c,v 1.40 2003/12/21 07:53:59 simonb Exp $ */
|
||||
/* $NetBSD: mach_message.c,v 1.41 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.40 2003/12/21 07:53:59 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.41 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
|
||||
@ -603,6 +603,8 @@ mach_msg_recv(l, urm, option, recv_size, timeout, mn)
|
||||
/*
|
||||
* Get rights carried by the message if it is not a
|
||||
* reply from the kernel.
|
||||
* XXX mm->mm_l could contain stall data. Reference
|
||||
* the thread's kernel port instead?
|
||||
*/
|
||||
if (mm->mm_l != NULL) {
|
||||
mach_port_t *mnp;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_port.h,v 1.32 2003/12/20 19:43:17 manu Exp $ */
|
||||
/* $NetBSD: mach_port.h,v 1.33 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
|
||||
@ -316,7 +316,7 @@ struct mach_port {
|
||||
#define MACH_MP_PROC 0x4 /* (struct proc *) */
|
||||
#define MACH_MP_NOTIFY_SYNC 0x5 /* int */
|
||||
#define MACH_MP_MEMORY_ENTRY 0x6 /* (struct mach_memory_entry *) */
|
||||
#define MACH_MP_EXC_FLAGS 0x7 /* Two shorts: behavior, flavor */
|
||||
#define MACH_MP_EXC_INFO 0x7 /* (struct mach_exc_info *) */
|
||||
#define MACH_MP_SEMAPHORE 0x8 /* (struct mach_semaphore *) */
|
||||
|
||||
void mach_port_init(void);
|
||||
|
@ -1,14 +1,14 @@
|
||||
/* $NetBSD: mach_services.c,v 1.11 2003/12/09 12:13:44 manu Exp $ */
|
||||
/* $NetBSD: mach_services.c,v 1.12 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*
|
||||
* Mach services table.
|
||||
*
|
||||
* DO NOT EDIT -- this file is automatically generated.
|
||||
* created from NetBSD: mach_services.master,v 1.7 2003/11/30 20:42:03 manu Exp
|
||||
* created from NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_services.c,v 1.11 2003/12/09 12:13:44 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_services.c,v 1.12 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -255,9 +255,9 @@ struct mach_service mach_services_table[] = {
|
||||
{3602, NULL, "unimpl. act_set_state", 0, 0},
|
||||
{3603, mach_thread_get_state, "thread_get_state", sizeof(mach_thread_get_state_request_t), sizeof(mach_thread_get_state_reply_t)},
|
||||
{3604, mach_thread_set_state, "thread_set_state", sizeof(mach_thread_set_state_request_t), sizeof(mach_thread_set_state_reply_t)},
|
||||
{3605, NULL, "unimpl. thread_suspend", 0, 0},
|
||||
{3606, NULL, "unimpl. thread_resume", 0, 0},
|
||||
{3607, NULL, "unimpl. thread_abort", 0, 0},
|
||||
{3605, mach_thread_suspend, "thread_suspend", sizeof(mach_thread_suspend_request_t), sizeof(mach_thread_suspend_reply_t)},
|
||||
{3606, mach_thread_resume, "thread_resume", sizeof(mach_thread_resume_request_t), sizeof(mach_thread_resume_reply_t)},
|
||||
{3607, mach_thread_abort, "thread_abort", sizeof(mach_thread_abort_request_t), sizeof(mach_thread_abort_reply_t)},
|
||||
{3608, NULL, "unimpl. thread_abort_safely", 0, 0},
|
||||
{3609, NULL, "unimpl. thread_depress_abort", 0, 0},
|
||||
{3610, NULL, "unimpl. thread_get_special_port", 0, 0},
|
||||
|
@ -1,14 +1,14 @@
|
||||
/* $NetBSD: mach_services.h,v 1.11 2003/12/09 12:13:44 manu Exp $ */
|
||||
/* $NetBSD: mach_services.h,v 1.12 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*
|
||||
* Mach services prototypes.
|
||||
*
|
||||
* DO NOT EDIT -- this file is automatically generated.
|
||||
* created from NetBSD: mach_services.master,v 1.7 2003/11/30 20:42:03 manu Exp
|
||||
* created from NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_services.h,v 1.11 2003/12/09 12:13:44 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_services.h,v 1.12 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include <compat/mach/mach_types.h>
|
||||
#include <compat/mach/mach_message.h>
|
||||
@ -74,6 +74,9 @@ int mach_semaphore_create(struct mach_trap_args *);
|
||||
int mach_semaphore_destroy(struct mach_trap_args *);
|
||||
int mach_thread_get_state(struct mach_trap_args *);
|
||||
int mach_thread_set_state(struct mach_trap_args *);
|
||||
int mach_thread_suspend(struct mach_trap_args *);
|
||||
int mach_thread_resume(struct mach_trap_args *);
|
||||
int mach_thread_abort(struct mach_trap_args *);
|
||||
int mach_thread_info(struct mach_trap_args *);
|
||||
int mach_thread_policy(struct mach_trap_args *);
|
||||
int mach_vm_region(struct mach_trap_args *);
|
||||
|
@ -1,4 +1,4 @@
|
||||
$NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp $
|
||||
$NetBSD: mach_services.master,v 1.9 2003/12/24 23:22:22 manu Exp $
|
||||
;
|
||||
; Mach services list.
|
||||
;
|
||||
@ -333,9 +333,9 @@
|
||||
3602 UNIMPL act_set_state
|
||||
3603 STD thread_get_state
|
||||
3604 STD thread_set_state
|
||||
3605 UNIMPL thread_suspend
|
||||
3606 UNIMPL thread_resume
|
||||
3607 UNIMPL thread_abort
|
||||
3605 STD thread_suspend
|
||||
3606 STD thread_resume
|
||||
3607 STD thread_abort
|
||||
3608 UNIMPL thread_abort_safely
|
||||
3609 UNIMPL thread_depress_abort
|
||||
3610 UNIMPL thread_get_special_port
|
||||
|
@ -1,15 +1,15 @@
|
||||
/* $NetBSD: mach_services_names.c,v 1.8 2003/12/09 12:13:44 manu Exp $ */
|
||||
/* $NetBSD: mach_services_names.c,v 1.9 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*
|
||||
* Mach services names. This file is not built
|
||||
* by the kernel, it is included by kdump sources.
|
||||
*
|
||||
* DO NOT EDIT -- this file is automatically generated.
|
||||
* created from NetBSD: mach_services.master,v 1.7 2003/11/30 20:42:03 manu Exp
|
||||
* created from NetBSD: mach_services.master,v 1.8 2003/12/09 12:13:44 manu Exp
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_services_names.c,v 1.8 2003/12/09 12:13:44 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_services_names.c,v 1.9 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
struct mach_service_name {
|
||||
int srv_id;
|
||||
@ -244,9 +244,9 @@ struct mach_service_name mach_services_names[] = {
|
||||
{3602, "unimpl. act_set_state"},
|
||||
{3603, "thread_get_state"},
|
||||
{3604, "thread_set_state"},
|
||||
{3605, "unimpl. thread_suspend"},
|
||||
{3606, "unimpl. thread_resume"},
|
||||
{3607, "unimpl. thread_abort"},
|
||||
{3605, "thread_suspend"},
|
||||
{3606, "thread_resume"},
|
||||
{3607, "thread_abort"},
|
||||
{3608, "unimpl. thread_abort_safely"},
|
||||
{3609, "unimpl. thread_depress_abort"},
|
||||
{3610, "unimpl. thread_get_special_port"},
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_task.c,v 1.51 2003/12/20 19:43:17 manu Exp $ */
|
||||
/* $NetBSD: mach_task.c,v 1.52 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
|
||||
@ -40,7 +40,7 @@
|
||||
#include "opt_compat_darwin.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.51 2003/12/20 19:43:17 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.52 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -326,6 +326,7 @@ mach_task_get_exception_ports(args)
|
||||
size_t *msglen = args->rsize;
|
||||
struct mach_emuldata *med;
|
||||
struct mach_right *mr;
|
||||
struct mach_exc_info *mei;
|
||||
int i, j, count;
|
||||
|
||||
med = tl->l_proc->p_emuldata;
|
||||
@ -342,13 +343,21 @@ mach_task_get_exception_ports(args)
|
||||
if (med->med_exc[i] == NULL)
|
||||
continue;
|
||||
|
||||
if (med->med_exc[i]->mp_datatype != MACH_MP_EXC_INFO) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("Exception port without mach_exc_info\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
mei = med->med_exc[i]->mp_data;
|
||||
|
||||
mr = mach_right_get(med->med_exc[i], l, MACH_PORT_TYPE_SEND, 0);
|
||||
|
||||
mach_add_port_desc(rep, mr->mr_name);
|
||||
|
||||
rep->rep_masks[j] = 1 << i;
|
||||
rep->rep_old_behaviors[j] = (int)mr->mr_port->mp_data >> 16;
|
||||
rep->rep_old_flavors[j] = (int)mr->mr_port->mp_data & 0xffff;
|
||||
rep->rep_old_behaviors[j] = mei->mei_behavior;
|
||||
rep->rep_old_flavors[j] = mei->mei_flavor;
|
||||
|
||||
j++;
|
||||
}
|
||||
@ -389,6 +398,7 @@ mach_task_set_exception_ports(args)
|
||||
mach_port_name_t mn;
|
||||
struct mach_right *mr;
|
||||
struct mach_port *mp;
|
||||
struct mach_exc_info *mei;
|
||||
|
||||
mn = req->req_new_port.name;
|
||||
if ((mr = mach_right_check(mn, l, MACH_PORT_TYPE_SEND)) == 0)
|
||||
@ -396,12 +406,17 @@ mach_task_set_exception_ports(args)
|
||||
|
||||
mp = mr->mr_port;
|
||||
#ifdef DIAGNOSTIC
|
||||
if ((mp->mp_datatype != MACH_MP_EXC_FLAGS) &&
|
||||
if ((mp->mp_datatype != MACH_MP_EXC_INFO) &&
|
||||
(mp->mp_datatype != MACH_MP_NONE))
|
||||
printf("mach_task_set_exception_ports: data exists\n");
|
||||
#endif
|
||||
mp->mp_datatype = MACH_MP_EXC_FLAGS;
|
||||
mp->mp_data = (void *)((req->req_behavior << 16) | req->req_flavor);
|
||||
mei = malloc(sizeof(*mei), M_EMULDATA, M_WAITOK);
|
||||
mei->mei_flavor = req->req_flavor;
|
||||
mei->mei_behavior = req->req_behavior;
|
||||
|
||||
mp->mp_data = mei;
|
||||
mp->mp_flags |= MACH_MP_DATA_ALLOCATED;
|
||||
mp->mp_datatype = MACH_MP_EXC_INFO;
|
||||
|
||||
med = tl->l_proc->p_emuldata;
|
||||
if (req->req_mask & MACH_EXC_MASK_BAD_ACCESS)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_thread.c,v 1.31 2003/12/20 19:43:17 manu Exp $ */
|
||||
/* $NetBSD: mach_thread.c,v 1.32 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
|
||||
@ -37,7 +37,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_thread.c,v 1.31 2003/12/20 19:43:17 manu Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: mach_thread.c,v 1.32 2003/12/24 23:22:22 manu Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
@ -411,3 +411,62 @@ mach_thread_set_state(args)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mach_thread_suspend(args)
|
||||
struct mach_trap_args *args;
|
||||
{
|
||||
mach_thread_suspend_request_t *req = args->smsg;
|
||||
mach_thread_suspend_reply_t *rep = args->rmsg;
|
||||
size_t *msglen = args->rsize;
|
||||
struct lwp *l = args->l;
|
||||
struct lwp *tl = args->tl;
|
||||
int error;
|
||||
|
||||
error = lwp_suspend(l, tl);
|
||||
|
||||
*msglen = sizeof(*rep);
|
||||
mach_set_header(rep, req, *msglen);
|
||||
rep->rep_retval = native_to_mach_errno[error];
|
||||
mach_set_trailer(rep, *msglen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mach_thread_resume(args)
|
||||
struct mach_trap_args *args;
|
||||
{
|
||||
mach_thread_resume_request_t *req = args->smsg;
|
||||
mach_thread_resume_reply_t *rep = args->rmsg;
|
||||
size_t *msglen = args->rsize;
|
||||
struct lwp *tl = args->tl;
|
||||
|
||||
lwp_continue(tl);
|
||||
|
||||
*msglen = sizeof(*rep);
|
||||
mach_set_header(rep, req, *msglen);
|
||||
rep->rep_retval = 0;
|
||||
mach_set_trailer(rep, *msglen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mach_thread_abort(args)
|
||||
struct mach_trap_args *args;
|
||||
{
|
||||
mach_thread_abort_request_t *req = args->smsg;
|
||||
mach_thread_abort_reply_t *rep = args->rmsg;
|
||||
size_t *msglen = args->rsize;
|
||||
struct lwp *tl = args->tl;
|
||||
|
||||
lwp_exit(tl);
|
||||
|
||||
*msglen = sizeof(*rep);
|
||||
mach_set_header(rep, req, *msglen);
|
||||
rep->rep_retval = 0;
|
||||
mach_set_trailer(rep, *msglen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: mach_thread.h,v 1.14 2003/12/18 01:10:20 grant Exp $ */
|
||||
/* $NetBSD: mach_thread.h,v 1.15 2003/12/24 23:22:22 manu Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
|
||||
@ -188,6 +188,45 @@ typedef struct {
|
||||
mach_msg_trailer_t rep_trailer;
|
||||
} mach_thread_set_state_reply_t;
|
||||
|
||||
/* thread_suspend */
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t req_msgh;
|
||||
} mach_thread_suspend_request_t;
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t rep_msgh;
|
||||
mach_ndr_record_t rep_ndr;
|
||||
mach_kern_return_t rep_retval;
|
||||
mach_msg_trailer_t rep_trailer;
|
||||
} mach_thread_suspend_reply_t;
|
||||
|
||||
/* thread_resume */
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t req_msgh;
|
||||
} mach_thread_resume_request_t;
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t rep_msgh;
|
||||
mach_ndr_record_t rep_ndr;
|
||||
mach_kern_return_t rep_retval;
|
||||
mach_msg_trailer_t rep_trailer;
|
||||
} mach_thread_resume_reply_t;
|
||||
|
||||
/* thread_abort */
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t req_msgh;
|
||||
} mach_thread_abort_request_t;
|
||||
|
||||
typedef struct {
|
||||
mach_msg_header_t rep_msgh;
|
||||
mach_ndr_record_t rep_ndr;
|
||||
mach_kern_return_t rep_retval;
|
||||
mach_msg_trailer_t rep_trailer;
|
||||
} mach_thread_abort_reply_t;
|
||||
|
||||
/* These are machine dependent functions */
|
||||
int mach_thread_get_state_machdep(struct lwp *, int, void *, int *);
|
||||
int mach_thread_set_state_machdep(struct lwp *, int, void *);
|
||||
|
Loading…
Reference in New Issue
Block a user