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:
David Xu 2003-08-05 12:00:55 +00:00
parent c9cbdf3393
commit d3b5e418bc
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=118486
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 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);
}
} }
} }
} }

View File

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

View File

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