diff options
author | trevtom <none@none> | 2006-08-30 09:00:25 -0700 |
---|---|---|
committer | trevtom <none@none> | 2006-08-30 09:00:25 -0700 |
commit | 5a64ecfaf2325d06eb5ebd8a815f40fef88b3679 (patch) | |
tree | 1a5f8b1fd67c1735057b4a92aace0a924f794896 /usr/src | |
parent | 2859562fdfd7ef8a00f5c8a5dc05117a732e7983 (diff) | |
download | illumos-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.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/sys/thread.h | 8 |
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; /* |