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.
This commit is contained in:
parent
d35feded85
commit
576c004216
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,10 @@ struct kse_mailbox {
|
||||
#define KMF_BOUND 0x08
|
||||
#define KMF_WAITSIGEVENT 0x10
|
||||
|
||||
/* These flags are kept in tm_flags */
|
||||
#define TMF_NOUPCALL 0x01
|
||||
|
||||
/* Commands for kse_thr_interrupt */
|
||||
#define KSE_INTR_INTERRUPT 0x01
|
||||
#define KSE_INTR_RESTART 0x02
|
||||
#define KSE_INTR_SENDSIG 0x03
|
||||
|
Loading…
Reference in New Issue
Block a user