summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_kse.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2003-08-05 12:00:55 +0000
committerdavidxu <davidxu@FreeBSD.org>2003-08-05 12:00:55 +0000
commit93e075cf7ad1df05ef58d1fc49abc48e4340661c (patch)
treebdace5637a0cb7d5c390e9e3998079586fffda05 /sys/kern/kern_kse.c
parent6620306b94c8bc7c1067170441e089311af47afe (diff)
downloadFreeBSD-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/kern_kse.c')
-rw-r--r--sys/kern/kern_kse.c25
1 files changed, 18 insertions, 7 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);
+ }
}
}
}
OpenPOWER on IntegriCloud