summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authortrevtom <none@none>2006-08-30 09:00:25 -0700
committertrevtom <none@none>2006-08-30 09:00:25 -0700
commit5a64ecfaf2325d06eb5ebd8a815f40fef88b3679 (patch)
tree1a5f8b1fd67c1735057b4a92aace0a924f794896 /usr/src
parent2859562fdfd7ef8a00f5c8a5dc05117a732e7983 (diff)
downloadillumos-joyent-5a64ecfaf2325d06eb5ebd8a815f40fef88b3679.tar.gz
6351092 Race for t_ctx in removectx() can lead to panic.
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/disp/thread.c27
-rw-r--r--usr/src/uts/common/sys/thread.h8
2 files changed, 28 insertions, 7 deletions
diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c
index fc2bbb0337..91b4db8103 100644
--- a/usr/src/uts/common/disp/thread.c
+++ b/usr/src/uts/common/disp/thread.c
@@ -909,9 +909,7 @@ installctx(
}
/*
- * Remove thread context ops from the current thread.
- * (Or allow the agent thread to remove thread context ops from another
- * thread in the same, stopped, process)
+ * Remove the thread context ops from a thread.
*/
int
removectx(
@@ -926,9 +924,29 @@ removectx(
{
struct ctxop *ctx, *prev_ctx;
+ /*
+ * The incoming kthread_t (which is the thread for which the
+ * context ops will be removed) should be one of the following:
+ *
+ * a) the current thread,
+ *
+ * b) a thread of a process that's being forked (SIDL),
+ *
+ * c) a thread that belongs to the same process as the current
+ * thread and for which the current thread is the agent thread,
+ *
+ * d) a thread that is TS_STOPPED which is indicative of it
+ * being (if curthread is not an agent) a thread being created
+ * as part of an lwp creation.
+ */
ASSERT(t == curthread || ttoproc(t)->p_stat == SIDL ||
ttoproc(t)->p_agenttp == curthread || t->t_state == TS_STOPPED);
+ /*
+ * Serialize modifications to t->t_ctx to prevent the agent thread
+ * and the target thread from racing with each other during lwp exit.
+ */
+ mutex_enter(&t->t_ctx_lock);
prev_ctx = NULL;
for (ctx = t->t_ctx; ctx != NULL; ctx = ctx->next) {
if (ctx->save_op == save && ctx->restore_op == restore &&
@@ -939,6 +957,7 @@ removectx(
prev_ctx->next = ctx->next;
else
t->t_ctx = ctx->next;
+ mutex_exit(&t->t_ctx_lock);
if (ctx->free_op != NULL)
(ctx->free_op)(ctx->arg, 0);
kmem_free(ctx, sizeof (struct ctxop));
@@ -946,6 +965,8 @@ removectx(
}
prev_ctx = ctx;
}
+ mutex_exit(&t->t_ctx_lock);
+
return (0);
}
diff --git a/usr/src/uts/common/sys/thread.h b/usr/src/uts/common/sys/thread.h
index bf60447de0..c5e406f678 100644
--- a/usr/src/uts/common/sys/thread.h
+++ b/usr/src/uts/common/sys/thread.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -333,6 +332,7 @@ typedef struct _kthread {
uint64_t t_dtrace_regv; /* DTrace saved reg from fasttrap */
#endif
hrtime_t t_hrtime; /* high-res last time on cpu */
+ kmutex_t t_ctx_lock; /* protects t_ctx in removectx() */
} kthread_t;
/*