diff options
author | davidxu <davidxu@FreeBSD.org> | 2003-06-20 09:12:12 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2003-06-20 09:12:12 +0000 |
commit | fc5cfc90b555ef39d68c80f55ee809b4382bdcd1 (patch) | |
tree | 62c2902e56b4d57cd1b2672edbffcb6b0fea8805 /sys/kern/kern_thread.c | |
parent | e5ce0c046f73b21456cfe796fb2431293b063e75 (diff) | |
download | FreeBSD-src-fc5cfc90b555ef39d68c80f55ee809b4382bdcd1.zip FreeBSD-src-fc5cfc90b555ef39d68c80f55ee809b4382bdcd1.tar.gz |
cpu_set_upcall_kse needs to access userspace, release schedule lock
before calling it for bound thread. To avoid this problem, change
thread_schedule_upcall to not put new thread on run queue, let caller
do it, so we can tweak the new thread before setting it to run.
Reported by: pho
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r-- | sys/kern/kern_thread.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index c71b74d..7695643 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -735,13 +735,18 @@ kse_create(struct thread *td, struct kse_create_args *uap) } } if (!sa) { - if (newtd != td) - cpu_set_upcall_kse(newtd, newku); newtd->td_mailbox = mbx.km_curthread; newtd->td_flags &= ~TDF_SA; + if (newtd != td) { + mtx_unlock_spin(&sched_lock); + cpu_set_upcall_kse(newtd, newku); + mtx_lock_spin(&sched_lock); + } } else { newtd->td_flags |= TDF_SA; } + if (newtd != td) + setrunqueue(newtd); mtx_unlock_spin(&sched_lock); return (0); } @@ -1394,7 +1399,6 @@ thread_schedule_upcall(struct thread *td, struct kse_upcall *ku) td2->td_kse = NULL; td2->td_state = TDS_CAN_RUN; td2->td_inhibitors = 0; - setrunqueue(td2); return (td2); /* bogus.. should be a void function */ } @@ -1447,6 +1451,7 @@ void thread_switchout(struct thread *td) { struct kse_upcall *ku; + struct thread *td2; mtx_assert(&sched_lock, MA_OWNED); @@ -1471,7 +1476,8 @@ thread_switchout(struct thread *td) ku->ku_owner = NULL; td->td_upcall = NULL; td->td_flags &= ~TDF_CAN_UNBIND; - thread_schedule_upcall(td, ku); + td2 = thread_schedule_upcall(td, ku); + setrunqueue(td2); } } |