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
c9cbdf3393
commit
d3b5e418bc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=118486
@ -1565,6 +1565,7 @@ thread_user_enter(struct proc *p, struct thread *td)
|
|||||||
struct ksegrp *kg;
|
struct ksegrp *kg;
|
||||||
struct kse_upcall *ku;
|
struct kse_upcall *ku;
|
||||||
struct kse_thr_mailbox *tmbx;
|
struct kse_thr_mailbox *tmbx;
|
||||||
|
uint32_t tflags;
|
||||||
|
|
||||||
kg = td->td_ksegrp;
|
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__));
|
KASSERT(!TD_CAN_UNBIND(td), ("%s: can unbind", __func__));
|
||||||
ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
|
ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
|
||||||
tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread);
|
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;
|
td->td_mailbox = NULL;
|
||||||
} else {
|
} else {
|
||||||
td->td_mailbox = tmbx;
|
|
||||||
if (td->td_standin == NULL)
|
if (td->td_standin == NULL)
|
||||||
thread_alloc_spare(td, NULL);
|
thread_alloc_spare(td, NULL);
|
||||||
mtx_lock_spin(&sched_lock);
|
tflags = fuword32(tmbx);
|
||||||
if (ku->ku_mflags & KMF_NOUPCALL)
|
/*
|
||||||
td->td_flags &= ~TDF_CAN_UNBIND;
|
* On some architectures, TP register points to thread
|
||||||
else
|
* 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;
|
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 ksegrp *kg;
|
||||||
struct kse_upcall *ku;
|
struct kse_upcall *ku;
|
||||||
struct kse_thr_mailbox *tmbx;
|
struct kse_thr_mailbox *tmbx;
|
||||||
|
uint32_t tflags;
|
||||||
|
|
||||||
kg = td->td_ksegrp;
|
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__));
|
KASSERT(!TD_CAN_UNBIND(td), ("%s: can unbind", __func__));
|
||||||
ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
|
ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
|
||||||
tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread);
|
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;
|
td->td_mailbox = NULL;
|
||||||
} else {
|
} else {
|
||||||
td->td_mailbox = tmbx;
|
|
||||||
if (td->td_standin == NULL)
|
if (td->td_standin == NULL)
|
||||||
thread_alloc_spare(td, NULL);
|
thread_alloc_spare(td, NULL);
|
||||||
mtx_lock_spin(&sched_lock);
|
tflags = fuword32(tmbx);
|
||||||
if (ku->ku_mflags & KMF_NOUPCALL)
|
/*
|
||||||
td->td_flags &= ~TDF_CAN_UNBIND;
|
* On some architectures, TP register points to thread
|
||||||
else
|
* 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;
|
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_BOUND 0x08
|
||||||
#define KMF_WAITSIGEVENT 0x10
|
#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_INTERRUPT 0x01
|
||||||
#define KSE_INTR_RESTART 0x02
|
#define KSE_INTR_RESTART 0x02
|
||||||
#define KSE_INTR_SENDSIG 0x03
|
#define KSE_INTR_SENDSIG 0x03
|
||||||
|
Loading…
Reference in New Issue
Block a user