Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/compat More work on exceptions. Once a task has raised a...
details: https://anonhg.NetBSD.org/src/rev/14c8f29d8ef8
branches: trunk
changeset: 555452:14c8f29d8ef8
user: manu <manu%NetBSD.org@localhost>
date: Tue Nov 18 01:40:18 2003 +0000
description:
More work on exceptions. Once a task has raised an exception, it remains
blocked in the kernel. The task that catched the exception may unblock
it by sending a reply to the exception message (Of course it will have
to change something so that the exception is not immediatly raised again).
Handling of this reply is a bit complicated, as the kernel acts as the
client instead of the server. In this situation, we receive a message
but we will not send any reply (the message we receive is already a reply).
I have not found anything better than a special case in
mach_msg_overwrite_trap() to handle this.
A surprise: exceptions ports are preserved accross forks.
While we are there, use appropriate 64 bit types for make_memory_entry_64.
diffstat:
sys/compat/darwin/darwin_exec.c | 15 ++++-
sys/compat/mach/mach_exec.c | 15 ++--
sys/compat/mach/mach_exec.h | 4 +-
sys/compat/mach/mach_message.c | 88 ++++++++++++++++++++---------
sys/compat/mach/mach_notify.c | 102 +++++++++++++++++++++++++++++++--
sys/compat/mach/mach_notify.h | 26 ++++++++-
sys/compat/mach/mach_services.c | 10 ++-
sys/compat/mach/mach_services.h | 9 ++-
sys/compat/mach/mach_services.master | 12 +++-
sys/compat/mach/mach_services_names.c | 9 ++-
sys/compat/mach/mach_task.c | 6 +-
sys/compat/mach/mach_types.h | 6 +-
sys/compat/mach/mach_vm.h | 16 ++---
13 files changed, 246 insertions(+), 72 deletions(-)
diffs (truncated from 765 to 300 lines):
diff -r ae16afc8eaf7 -r 14c8f29d8ef8 sys/compat/darwin/darwin_exec.c
--- a/sys/compat/darwin/darwin_exec.c Tue Nov 18 01:00:19 2003 +0000
+++ b/sys/compat/darwin/darwin_exec.c Tue Nov 18 01:40:18 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: darwin_exec.c,v 1.23 2003/11/17 01:52:14 manu Exp $ */
+/* $NetBSD: darwin_exec.c,v 1.24 2003/11/18 01:40:18 manu Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
#include "opt_compat_darwin.h" /* For COMPAT_DARWIN in mach_port.h */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.23 2003/11/17 01:52:14 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.24 2003/11/18 01:40:18 manu Exp $");
#include "opt_syscall_debug.h"
@@ -229,6 +229,9 @@
darwin_e_proc_init(p, p->p_vmspace);
+ /* Setup the mach_emuldata part of darwin_emuldata */
+ mach_e_proc_exec(p, epp);
+
ded = (struct darwin_emuldata *)p->p_emuldata;
if (p->p_pid == darwin_init_pid)
ded->ded_fakepid = 1;
@@ -254,6 +257,9 @@
/* Use parent's vmspace because our vmspace may not be setup yet */
darwin_e_proc_init(p, parent->p_vmspace);
+ /* Setup the mach_emuldata part of darwin_emuldata */
+ mach_e_proc_fork(p, parent);
+
ded1 = p->p_emuldata;
ded2 = parent->p_emuldata;
@@ -291,6 +297,7 @@
ded->ded_fakepid = 0;
ded->ded_wsdev = NODEV;
+ /* Initalize the mach_emuldata part of darwin_emuldata */
mach_e_proc_init(p, vmspace);
return;
@@ -373,6 +380,10 @@
}
+ /*
+ * Cleanup mach_emuldata part of darwin_emuldata
+ * It will also free p->p_emuldata.
+ */
mach_e_proc_exit(p);
return;
diff -r ae16afc8eaf7 -r 14c8f29d8ef8 sys/compat/mach/mach_exec.c
--- a/sys/compat/mach/mach_exec.c Tue Nov 18 01:00:19 2003 +0000
+++ b/sys/compat/mach/mach_exec.c Tue Nov 18 01:40:18 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mach_exec.c,v 1.35 2003/11/17 01:52:14 manu Exp $ */
+/* $NetBSD: mach_exec.c,v 1.36 2003/11/18 01:40:18 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.35 2003/11/17 01:52:14 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.36 2003/11/18 01:40:18 manu Exp $");
#include "opt_syscall_debug.h"
@@ -62,9 +62,6 @@
#include <compat/mach/mach_exec.h>
static int mach_cold = 1; /* Have we initialized COMPAT_MACH structures? */
-
-static void mach_e_proc_exec(struct proc *, struct exec_package *);
-static void mach_e_proc_fork(struct proc *, struct proc *);
static void mach_init(void);
extern struct sysent sysent[];
@@ -192,7 +189,7 @@
return 0;
}
-static void
+void
mach_e_proc_exec(p, epp)
struct proc *p;
struct exec_package *epp;
@@ -202,7 +199,7 @@
return;
}
-static void
+void
mach_e_proc_fork(p, parent)
struct proc *p;
struct proc *parent;
@@ -217,7 +214,9 @@
med1 = p->p_emuldata;
med2 = parent->p_emuldata;
- /* Nothing is inherited across forks in struct mach_emuldata */
+
+ /* Exception ports are inherited between forks. */
+ (void)memcpy(med1->med_exc, med2->med_exc, sizeof(med1->med_exc));
return;
}
diff -r ae16afc8eaf7 -r 14c8f29d8ef8 sys/compat/mach/mach_exec.h
--- a/sys/compat/mach/mach_exec.h Tue Nov 18 01:00:19 2003 +0000
+++ b/sys/compat/mach/mach_exec.h Tue Nov 18 01:40:18 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mach_exec.h,v 1.20 2003/11/17 13:20:06 manu Exp $ */
+/* $NetBSD: mach_exec.h,v 1.21 2003/11/18 01:40:18 manu Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -68,6 +68,8 @@
int exec_mach_probe(char **);
void mach_e_proc_init(struct proc *, struct vmspace *);
void mach_e_proc_exit(struct proc *);
+void mach_e_proc_exec(struct proc *, struct exec_package *);
+void mach_e_proc_fork(struct proc *, struct proc *);
extern const struct emul emul_mach;
diff -r ae16afc8eaf7 -r 14c8f29d8ef8 sys/compat/mach/mach_message.c
--- a/sys/compat/mach/mach_message.c Tue Nov 18 01:00:19 2003 +0000
+++ b/sys/compat/mach/mach_message.c Tue Nov 18 01:40:18 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mach_message.c,v 1.29 2003/11/15 22:55:35 manu Exp $ */
+/* $NetBSD: mach_message.c,v 1.30 2003/11/18 01:40:18 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.29 2003/11/15 22:55:35 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_message.c,v 1.30 2003/11/18 01:40:18 manu Exp $");
#include "opt_ktrace.h"
#include "opt_compat_mach.h" /* For COMPAT_MACH in <sys/ktrace.h> */
@@ -180,15 +180,7 @@
if (mp->mp_flags & MACH_MP_INKERNEL) {
struct mach_trap_args args;
mach_msg_header_t *rm;
-
- /*
- * Check that the local port is valid, else
- * we will not be able to send the reply
- */
- if (lr == NULL) {
- *retval = MACH_SEND_INVALID_REPLY;
- goto out1;
- }
+ size_t min_reqlen, max_replen;
/*
* Look for the function that will handle it,
@@ -207,6 +199,35 @@
*retval = MACH_SEND_INVALID_DEST;
goto out1;
}
+ min_reqlen = srv->srv_reqlen;
+ max_replen = srv->srv_replen;
+
+ /*
+ * Special case when the kernel behaves as
+ * the client: replies to exceptions and
+ * notifications. There will be no reply,
+ * as we already receive a reply.
+ * - request and reply are swapped
+ * - there will be no reply, so set lr to NULL.
+ * - skip the lr == NULL test
+ * XXX This is inelegant.
+ */
+ if ((sm->msgh_id >= 2501) && (sm->msgh_id <= 2503)) {
+ min_reqlen = srv->srv_replen;
+ max_replen = srv->srv_reqlen;
+ lr = NULL;
+ goto skip_null_lr;
+ }
+
+ /*
+ * Check that the local port is valid, else
+ * we will not be able to send the reply
+ */
+ if (lr == NULL) {
+ *retval = MACH_SEND_INVALID_REPLY;
+ goto out1;
+ }
+skip_null_lr:
/*
* Sanity check message length. We do not want the
@@ -214,11 +235,11 @@
* 1) use kernel memory located after
* the end of the request message.
*/
- if (send_size < srv->srv_reqlen) {
+ if (send_size < min_reqlen) {
#ifdef DEBUG_MACH
printf("mach server %s: smsg overflow: "
"send = %d, min = %d\n",
- srv->srv_name, send_size, srv->srv_reqlen);
+ srv->srv_name, send_size, min_reqlen);
#endif
*retval = MACH_SEND_MSG_TOO_SMALL;
goto out1;
@@ -228,13 +249,13 @@
* 2) give away random kernel data to the user program
* when the reply message is copied out.
*/
- if (rcv_size > srv->srv_replen) {
+ if (rcv_size > max_replen) {
#ifdef DEBUG_MACH
printf("mach server %s: rmsg overflow: "
"recv = %d, max = %d\n",
- srv->srv_name, rcv_size, srv->srv_replen);
+ srv->srv_name, rcv_size, max_replen);
#endif
- rcv_size = srv->srv_replen;
+ rcv_size = max_replen;
}
/*
@@ -249,9 +270,13 @@
* Invoke the server. We give it the opportunity
* to shorten rcv_size if there is less data in
* the reply than what the sender expected.
+ * If lr is NULL, this is a no reply operation.
*/
- rm = malloc(srv->srv_replen,
- M_EMULDATA, M_WAITOK | M_ZERO);
+ if (lr != NULL)
+ rm = malloc(max_replen,
+ M_EMULDATA, M_WAITOK | M_ZERO);
+ else
+ rm = NULL;
args.l = l;
args.smsg = sm;
@@ -261,14 +286,20 @@
if ((*retval = (*srv->srv_handler)(&args)) != 0)
goto out1;
+ /*
+ * No-reply opration: everything is done.
+ */
+ if (lr == NULL)
+ goto out1;
+
#ifdef DIAGNOSTIC
/*
- * Catch potential bug in the server (santity
+ * Catch potential bug in the server (sanity
* check #3): did it output a larger message
* then the one that was allocated?
*/
if ((SCARG(uap, option) & MACH_RCV_MSG) &&
- (rcv_size > srv->srv_replen)) {
+ (rcv_size > max_replen)) {
uprintf("mach_msg: reply too big in %s\n",
srv->srv_name);
}
@@ -290,8 +321,17 @@
mach_bootstrap_port->mp_recv->mr_sethead);
#endif
wakeup(mp->mp_recv->mr_sethead);
+ *retval = 0;
+out1:
free(sm, M_EMULDATA);
- *retval = 0;
+ /*
+ * Skip the recieve part and return now if
+ * - there has been an error in the send part
+ * - this is a no-reply operation (lr == NULL)
+ */
+ if ((*retval != 0) || (lr == NULL))
+ return 0;
+
} else {
/*
* The message is not to be handled by the kernel.
@@ -353,12 +393,6 @@
*/
wakeup(mp->mp_recv->mr_sethead);
}
-
-out1:
- if (*retval != 0) {
- free(sm, M_EMULDATA);
Home |
Main Index |
Thread Index |
Old Index