diff options
author | davidxu <davidxu@FreeBSD.org> | 2003-08-05 12:00:55 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2003-08-05 12:00:55 +0000 |
commit | 93e075cf7ad1df05ef58d1fc49abc48e4340661c (patch) | |
tree | bdace5637a0cb7d5c390e9e3998079586fffda05 /sys/kern | |
parent | 6620306b94c8bc7c1067170441e089311af47afe (diff) | |
download | FreeBSD-src-93e075cf7ad1df05ef58d1fc49abc48e4340661c.zip FreeBSD-src-93e075cf7ad1df05ef58d1fc49abc48e4340661c.tar.gz |
Introduce a thread mailbox flag TMF_NOUPCALL. On some architectures other
than i386 or AMD64, TP register points to thread mailbox, and they can not
atomically clear km_curthread in kse mailbox, in this case, thread retrieves
its thread pointer from TP register and sets flag TMF_NOUPCALL in its thread
mailbox to indicate a critical region.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_kse.c | 25 | ||||
-rw-r--r-- | sys/kern/kern_thread.c | 25 |
2 files changed, 36 insertions, 14 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index 421e437..bf21150 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -1565,6 +1565,7 @@ thread_user_enter(struct proc *p, struct thread *td) struct ksegrp *kg; struct kse_upcall *ku; struct kse_thr_mailbox *tmbx; + uint32_t tflags; kg = td->td_ksegrp; @@ -1594,18 +1595,28 @@ thread_user_enter(struct proc *p, struct thread *td) KASSERT(!TD_CAN_UNBIND(td), ("%s: can unbind", __func__)); ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags); tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread); - if ((tmbx == NULL) || (tmbx == (void *)-1)) { + if ((tmbx == NULL) || (tmbx == (void *)-1L) || + (ku->ku_mflags & KMF_NOUPCALL)) { td->td_mailbox = NULL; } else { - td->td_mailbox = tmbx; if (td->td_standin == NULL) thread_alloc_spare(td, NULL); - mtx_lock_spin(&sched_lock); - if (ku->ku_mflags & KMF_NOUPCALL) - td->td_flags &= ~TDF_CAN_UNBIND; - else + tflags = fuword32(tmbx); + /* + * On some architectures, TP register points to thread + * mailbox but not points to kse mailbox, and userland + * can not atomically clear km_curthread, but can + * use TP register, and set TMF_NOUPCALL in thread + * flag to indicate a critical region. + */ + if (tflags & TMF_NOUPCALL) { + td->td_mailbox = NULL; + } else { + td->td_mailbox = tmbx; + mtx_lock_spin(&sched_lock); td->td_flags |= TDF_CAN_UNBIND; - mtx_unlock_spin(&sched_lock); + mtx_unlock_spin(&sched_lock); + } } } } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 421e437..bf21150 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -1565,6 +1565,7 @@ thread_user_enter(struct proc *p, struct thread *td) struct ksegrp *kg; struct kse_upcall *ku; struct kse_thr_mailbox *tmbx; + uint32_t tflags; kg = td->td_ksegrp; @@ -1594,18 +1595,28 @@ thread_user_enter(struct proc *p, struct thread *td) KASSERT(!TD_CAN_UNBIND(td), ("%s: can unbind", __func__)); ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags); tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread); - if ((tmbx == NULL) || (tmbx == (void *)-1)) { + if ((tmbx == NULL) || (tmbx == (void *)-1L) || + (ku->ku_mflags & KMF_NOUPCALL)) { td->td_mailbox = NULL; } else { - td->td_mailbox = tmbx; if (td->td_standin == NULL) thread_alloc_spare(td, NULL); - mtx_lock_spin(&sched_lock); - if (ku->ku_mflags & KMF_NOUPCALL) - td->td_flags &= ~TDF_CAN_UNBIND; - else + tflags = fuword32(tmbx); + /* + * On some architectures, TP register points to thread + * mailbox but not points to kse mailbox, and userland + * can not atomically clear km_curthread, but can + * use TP register, and set TMF_NOUPCALL in thread + * flag to indicate a critical region. + */ + if (tflags & TMF_NOUPCALL) { + td->td_mailbox = NULL; + } else { + td->td_mailbox = tmbx; + mtx_lock_spin(&sched_lock); td->td_flags |= TDF_CAN_UNBIND; - mtx_unlock_spin(&sched_lock); + mtx_unlock_spin(&sched_lock); + } } } } |