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