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:
davidxu 2003-08-05 12:00:55 +00:00
parent d35feded85
commit 576c004216
3 changed files with 40 additions and 14 deletions

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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