From d3b5e418bc6bda019ac100d8194743e6147373cc Mon Sep 17 00:00:00 2001 From: David Xu Date: Tue, 5 Aug 2003 12:00:55 +0000 Subject: [PATCH] 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. --- sys/kern/kern_kse.c | 25 ++++++++++++++++++------- sys/kern/kern_thread.c | 25 ++++++++++++++++++------- sys/sys/kse.h | 4 ++++ 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index 421e4373b13c..bf21150786bf 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); + } } } } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 421e4373b13c..bf21150786bf 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.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); + } } } } diff --git a/sys/sys/kse.h b/sys/sys/kse.h index 1108c4cb99b5..9cb096b40006 100644 --- a/sys/sys/kse.h +++ b/sys/sys/kse.h @@ -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