Try to do a better job at Mach port refcount. That's not perfect, though.
This commit is contained in:
parent
50d7e2cb8b
commit
996e659ce6
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue