Try to do a better job at Mach port refcount. That's not perfect, though.

This commit is contained in:
manu 2004-01-01 22:48:54 +00:00
parent 50d7e2cb8b
commit 996e659ce6
6 changed files with 84 additions and 71 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exception.c,v 1.2 2003/12/24 23:22:22 manu Exp $ */
/* $NetBSD: mach_exception.c,v 1.3 2004/01/01 22:48:54 manu Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.2 2003/12/24 23:22:22 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_exception.c,v 1.3 2004/01/01 22:48:54 manu Exp $");
#include "opt_ktrace.h"
#include "opt_compat_darwin.h"
@ -160,10 +160,15 @@ mach_exception(exc_l, exc, code)
*/
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))
if ((exc_port = exc_med->med_exc[exc]) == NULL)
return EINVAL;
MACH_PORT_REF(exc_port);
if (exc_port->mp_recv == NULL) {
error = EINVAL;
goto out;
}
#ifdef DEBUG_MACH
printf("catcher is %d.%d, state %d\n",
exc_port->mp_recv->mr_lwp->l_proc->p_pid,
@ -173,8 +178,10 @@ mach_exception(exc_l, exc, code)
/*
* Don't send exceptions to dying processes
*/
if (P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc))
return ESRCH;
if (P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc)) {
error = ESRCH;
goto out;
}
/*
* XXX Avoid a nasty deadlock because process in TX state
@ -201,14 +208,16 @@ mach_exception(exc_l, exc, code)
#ifdef DEBUG_MACH
printf("mach_exception: deadlock avoided\n");
#endif
return EINVAL;
error = EINVAL;
goto out;
}
if (exc_port->mp_datatype != MACH_MP_EXC_INFO) {
#ifdef DIAGNOSTIC
printf("mach_exception: unexpected datatype");
#endif
return EINVAL;
error = EINVAL;
goto out;
}
mei = exc_port->mp_data;
behavior = mei->mei_behavior;
@ -328,7 +337,8 @@ mach_exception(exc_l, exc, code)
default:
printf("unknown exception bevahior %d\n", behavior);
return EINVAL;
error = EINVAL;
goto out;
break;
}
@ -346,8 +356,10 @@ mach_exception(exc_l, exc, code)
*/
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;
(P_ZOMBIE(exc_port->mp_recv->mr_lwp->l_proc))) {
error = ESRCH;
goto out;
}
(void)mach_message_get(msgh, msglen, exc_port, NULL);
wakeup(exc_port->mp_recv->mr_sethead);
@ -371,6 +383,8 @@ mach_exception(exc_l, exc, code)
*/
lockmgr(&catcher_med->med_exclock, LK_RELEASE, NULL);
out:
MACH_PORT_UNREF(exc_port);
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_exec.c,v 1.51 2003/12/30 00:15:46 manu Exp $ */
/* $NetBSD: mach_exec.c,v 1.52 2004/01/01 22:48:54 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.51 2003/12/30 00:15:46 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.52 2004/01/01 22:48:54 manu Exp $");
#include "opt_syscall_debug.h"
@ -336,12 +336,11 @@ mach_e_proc_init(p, vmspace)
med->med_kernel->mp_datatype = MACH_MP_PROC;
med->med_host->mp_datatype = MACH_MP_PROC;
/* Make sure they will not be deallocated */
med->med_kernel->mp_refcount++;
med->med_host->mp_refcount++;
MACH_PORT_REF(med->med_kernel);
MACH_PORT_REF(med->med_host);
med->med_bootstrap = mach_bootstrap_port;
med->med_bootstrap->mp_refcount++;
MACH_PORT_REF(med->med_bootstrap);
}
/*
@ -367,6 +366,7 @@ mach_e_proc_exit(p)
struct mach_right *mr;
int i;
/* There is only one lwp remaining... */
mach_e_lwp_exit(proc_representative_lwp(p));
med = (struct mach_emuldata *)p->p_emuldata;
@ -376,8 +376,7 @@ mach_e_proc_exit(p)
mach_right_put_exclocked(mr, MACH_PORT_TYPE_ALL_RIGHTS);
lockmgr(&med->med_rightlock, LK_RELEASE, NULL);
if (--med->med_bootstrap->mp_refcount <= 0)
mach_port_put(med->med_bootstrap);
MACH_PORT_UNREF(med->med_bootstrap);
/*
* If the lock on this task exception handler is held,
@ -392,24 +391,17 @@ mach_e_proc_exit(p)
* the pointer to this process' struct proc, as it will
* become invalid once the process will exit.
*/
if (--med->med_kernel->mp_refcount <= 0) {
mach_port_put(med->med_kernel);
} else {
med->med_kernel->mp_datatype = MACH_MP_NONE;
med->med_kernel->mp_data = NULL;
}
med->med_kernel->mp_datatype = MACH_MP_NONE;
med->med_kernel->mp_data = NULL;
MACH_PORT_UNREF(med->med_kernel);
if (--med->med_host->mp_refcount <= 0) {
mach_port_put(med->med_host);
} else {
med->med_host->mp_datatype = MACH_MP_NONE;
med->med_host->mp_data = NULL;
}
med->med_host->mp_datatype = MACH_MP_NONE;
med->med_host->mp_data = NULL;
MACH_PORT_UNREF(med->med_host);
for (i = 0; i <= MACH_EXC_MAX; i++)
if ((med->med_exc[i] != NULL) &&
(--med->med_exc[i]->mp_refcount <= 0))
mach_port_put(med->med_exc[i]);
if (med->med_exc[i] != NULL)
MACH_PORT_UNREF(med->med_exc[i]);
free(med, M_EMULDATA);
p->p_emuldata = NULL;
@ -428,7 +420,7 @@ mach_e_lwp_fork(l1, l2)
l2->l_emuldata = mle;
mle->mle_kernel = mach_port_get();
mle->mle_kernel->mp_refcount++;
MACH_PORT_REF(mle->mle_kernel);
mle->mle_kernel->mp_flags |= MACH_MP_INKERNEL;
mle->mle_kernel->mp_datatype = MACH_MP_LWP;
@ -460,9 +452,7 @@ mach_e_lwp_exit(l)
mle->mle_kernel->mp_data = NULL;
mle->mle_kernel->mp_datatype = MACH_MP_NONE;
if (--mle->mle_kernel->mp_refcount <= 0)
mach_port_put(mle->mle_kernel);
MACH_PORT_UNREF(mle->mle_kernel);
free(mle, M_EMULDATA);
l->l_emuldata = NULL;

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_notify.c,v 1.14 2003/12/09 12:13:44 manu Exp $ */
/* $NetBSD: mach_notify.c,v 1.15 2004/01/01 22:48:54 manu Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_notify.c,v 1.14 2003/12/09 12:13:44 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_notify.c,v 1.15 2004/01/01 22:48:54 manu Exp $");
#include "opt_ktrace.h"
@ -64,6 +64,7 @@ mach_notify_port_destroyed(l, mr)
if (mr->mr_notify_destroyed == NULL)
return;
mp = mr->mr_notify_destroyed->mr_port;
#ifdef DIAGNOSTIC
@ -73,6 +74,8 @@ mach_notify_port_destroyed(l, mr)
}
#endif
MACH_PORT_REF(mp);
req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO);
req->req_msgh.msgh_bits =
@ -93,6 +96,8 @@ mach_notify_port_destroyed(l, mr)
#endif
wakeup(mp->mp_recv->mr_sethead);
MACH_PORT_UNREF(mp);
return;
}
@ -117,8 +122,9 @@ mach_notify_port_no_senders(l, mr)
return;
}
#endif
MACH_PORT_REF(mp);
if ((int)mp->mp_data >= mr->mr_refcount)
return;
goto out;
req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO);
@ -139,6 +145,8 @@ mach_notify_port_no_senders(l, mr)
#endif
wakeup(mp->mp_recv->mr_sethead);
out:
MACH_PORT_UNREF(mp);
return;
}
@ -153,7 +161,7 @@ mach_notify_port_dead_name(l, mr)
if ((mr->mr_notify_dead_name == NULL) ||
(mr->mr_notify_dead_name->mr_port == NULL))
return;
mp = mr->mr_notify_no_senders->mr_port;
mp = mr->mr_notify_dead_name->mr_port;
#ifdef DIAGNOSTIC
if ((mp == NULL) || (mp->mp_recv)) {
@ -161,6 +169,7 @@ mach_notify_port_dead_name(l, mr)
return;
}
#endif
MACH_PORT_REF(mp);
req = malloc(sizeof(*req), M_EMULDATA, M_WAITOK | M_ZERO);
@ -175,7 +184,6 @@ mach_notify_port_dead_name(l, mr)
mr->mr_refcount++;
mp = mr->mr_notify_dead_name->mr_port;
(void)mach_message_get((mach_msg_header_t *)req, sizeof(*req), mp, l);
#ifdef DEBUG_MACH_MSG
printf("pid %d: message queued on port %p (%d) [%p]\n",
@ -183,6 +191,7 @@ mach_notify_port_dead_name(l, mr)
mp->mp_recv->mr_sethead);
#endif
wakeup(mp->mp_recv->mr_sethead);
MACH_PORT_UNREF(mp);
return;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_port.c,v 1.50 2003/12/30 00:15:46 manu Exp $ */
/* $NetBSD: mach_port.c,v 1.51 2004/01/01 22:48:54 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include "opt_compat_darwin.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.50 2003/12/30 00:15:46 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_port.c,v 1.51 2004/01/01 22:48:54 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -179,7 +179,8 @@ mach_port_destroy(args)
mn = req->req_name;
if ((mr = mach_right_check(mn,
l, MACH_PORT_TYPE_ALL_RIGHTS)) != NULL) {
mr->mr_refcount = 0; /* Make sure it will be kicked away */
MACH_PORT_UNREF(mr->mr_port);
mr->mr_port = NULL;
mach_right_put(mr, MACH_PORT_TYPE_ALL_RIGHTS);
}
@ -632,11 +633,12 @@ mach_port_put(mp)
{
struct mach_message *mm;
printf("port_put: %p\n", mp);
#ifdef DIAGNOSTIC
if (mp->mp_refcount > 0) {
uprintf("mach_port_put: trying to free a referenced port\n");
return;
}
#endif
lockmgr(&mp->mp_msglock, LK_EXCLUSIVE, NULL);
while ((mm = TAILQ_FIRST(&mp->mp_msglist)) != NULL)
@ -669,6 +671,9 @@ mach_right_get(mp, l, type, hint)
#endif
med = (struct mach_emuldata *)l->l_proc->p_emuldata;
if (mp != NULL)
MACH_PORT_REF(mp);
/* Send and receive right must return an existing right */
rights = (MACH_PORT_TYPE_SEND | MACH_PORT_TYPE_RECEIVE);
if (type & rights) {
@ -700,9 +705,6 @@ mach_right_get(mp, l, type, hint)
LIST_INIT(&mr->mr_set);
if (mp != NULL)
mp->mp_refcount++;
/* Insert the right in the right lists */
if (type & MACH_PORT_TYPE_ALL_RIGHTS) {
lockmgr(&med->med_rightlock, LK_EXCLUSIVE, NULL);
@ -810,9 +812,7 @@ mach_right_put_exclocked(mr, right)
#endif
mr->mr_port->mp_recv = NULL;
mr->mr_port->mp_refcount--;
if (mr->mr_port->mp_refcount <= 0)
mach_port_put(mr->mr_port);
MACH_PORT_UNREF(mr->mr_port);
mr->mr_port = NULL;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_port.h,v 1.33 2003/12/24 23:22:22 manu Exp $ */
/* $NetBSD: mach_port.h,v 1.34 2004/01/01 22:48:54 manu Exp $ */
/*-
* Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
@ -38,6 +38,9 @@
#ifndef _MACH_PORT_H_
#define _MACH_PORT_H_
#define MACH_PORT_REF(mp) (mp)->mp_refcount++
#define MACH_PORT_UNREF(mp) if (--(mp)->mp_refcount <= 0) mach_port_put(mp)
#define MACH_PORT_NULL (struct mach_right *)0
#define MACH_PORT_DEAD (struct mach_right *)-1

View File

@ -1,4 +1,4 @@
/* $NetBSD: mach_task.c,v 1.52 2003/12/24 23:22:22 manu Exp $ */
/* $NetBSD: mach_task.c,v 1.53 2004/01/01 22:48:54 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.52 2003/12/24 23:22:22 manu Exp $");
__KERNEL_RCSID(0, "$NetBSD: mach_task.c,v 1.53 2004/01/01 22:48:54 manu Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -212,25 +212,25 @@ mach_task_set_special_port(args)
case MACH_TASK_KERNEL_PORT:
mp = med->med_kernel;
med->med_kernel = mr->mr_port;
mp->mp_refcount--;
if (mp->mp_refcount == 0)
mach_port_put(mp);
if (mr->mr_port != NULL)
MACH_PORT_REF(mr->mr_port);
MACH_PORT_UNREF(mp);
break;
case MACH_TASK_HOST_PORT:
mp = med->med_host;
med->med_host = mr->mr_port;
mp->mp_refcount--;
if (mp->mp_refcount == 0)
mach_port_put(mp);
if (mr->mr_port != NULL)
MACH_PORT_REF(mr->mr_port);
MACH_PORT_UNREF(mp);
break;
case MACH_TASK_BOOTSTRAP_PORT:
mp = med->med_bootstrap;
med->med_bootstrap = mr->mr_port;
mp->mp_refcount--;
if (mp->mp_refcount == 0)
mach_port_put(mp);
if (mr->mr_port != NULL)
MACH_PORT_REF(mr->mr_port);
MACH_PORT_UNREF(mp);
#ifdef COMPAT_DARWIN
/*
* mach_init sets the bootstrap port for any new process.
@ -374,13 +374,10 @@ update_exception_port(med, exc, mp)
int exc;
struct mach_port *mp;
{
if (med->med_exc[exc] != NULL) {
med->med_exc[exc]->mp_refcount--;
if (med->med_exc[exc]->mp_refcount <= 0)
mach_port_put(med->med_exc[exc]);
}
if (med->med_exc[exc] != NULL)
MACH_PORT_UNREF(med->med_exc[exc]);
med->med_exc[exc] = mp;
mp->mp_refcount++;
MACH_PORT_REF(mp);
return;
}