summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_kse.c75
-rw-r--r--sys/sys/kse.h9
2 files changed, 51 insertions, 33 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index 9555687..c85c165 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -185,6 +185,9 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
{
struct proc *p;
struct thread *td2;
+ struct kse_upcall *ku;
+ struct kse_thr_mailbox *tmbx;
+ uint32_t flags;
p = td->td_proc;
@@ -236,6 +239,30 @@ kse_thr_interrupt(struct thread *td, struct kse_thr_interrupt_args *uap)
PROC_LOCK(p);
sigexit(td, (int)uap->data);
break;
+
+ case KSE_INTR_DBSUSPEND:
+ /* this sub-function is only for bound thread */
+ if (td->td_pflags & TDP_SA)
+ return (EINVAL);
+ ku = td->td_upcall;
+ tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread);
+ if (tmbx == NULL || tmbx == (void *)-1)
+ return (EINVAL);
+ flags = 0;
+ while ((p->p_flag & P_TRACED) && !(p->p_flag & P_SINGLE_EXIT)) {
+ flags = fuword32(&tmbx->tm_dflags);
+ if (!(flags & TMDF_SUSPEND))
+ break;
+ PROC_LOCK(p);
+ mtx_lock_spin(&sched_lock);
+ thread_stopped(p);
+ thread_suspend_one(td);
+ PROC_UNLOCK(p);
+ mi_switch(SW_VOL, NULL);
+ mtx_unlock_spin(&sched_lock);
+ }
+ return (0);
+
default:
return (EINVAL);
}
@@ -297,6 +324,9 @@ kse_exit(struct thread *td, struct kse_exit_args *uap)
* XXX need to check it that can be deliverred without a mailbox.
*/
error = suword32(&ku->ku_mailbox->km_flags, ku->ku_mflags|KMF_DONE);
+ if (!(td->td_pflags & TDP_SA))
+ if (suword32(&td->td_mailbox->tm_lwp, 0))
+ error = EFAULT;
PROC_LOCK(p);
if (error)
psignal(p, SIGSEGV);
@@ -361,7 +391,8 @@ kse_release(struct thread *td, struct kse_release_args *uap)
PROC_LOCK(p);
if (ku->ku_mflags & KMF_WAITSIGEVENT) {
/* UTS wants to wait for signal event */
- if (!(p->p_flag & P_SIGEVENT) && !(ku->ku_flags & KUF_DOUPCALL)) {
+ if (!(p->p_flag & P_SIGEVENT) &&
+ !(ku->ku_flags & KUF_DOUPCALL)) {
td->td_kflags |= TDK_KSERELSIG;
error = msleep(&p->p_siglist, &p->p_mtx, PPAUSE|PCATCH,
"ksesigwait", (uap->timeout ? tvtohz(&tv) : 0));
@@ -373,7 +404,9 @@ kse_release(struct thread *td, struct kse_release_args *uap)
error = copyout(&sigset, &ku->ku_mailbox->km_sigscaught,
sizeof(sigset));
} else {
- if (! kg->kg_completed && !(ku->ku_flags & KUF_DOUPCALL)) {
+ if ((ku->ku_flags & KUF_DOUPCALL) == 0 &&
+ ((ku->ku_mflags & KMF_NOCOMPLETED) ||
+ (kg->kg_completed == NULL))) {
kg->kg_upsleeps++;
td->td_kflags |= TDK_KSEREL;
error = msleep(&kg->kg_completed, &p->p_mtx,
@@ -424,7 +457,7 @@ kse_wakeup(struct thread *td, struct kse_wakeup_args *uap)
kg = td->td_ksegrp;
if (kg->kg_upsleeps) {
mtx_unlock_spin(&sched_lock);
- wakeup_one(&kg->kg_completed);
+ wakeup(&kg->kg_completed);
PROC_UNLOCK(p);
return (0);
}
@@ -1078,10 +1111,14 @@ thread_switchout(struct thread *td)
* If it is a short term event, just suspend it in
* a way that takes its KSE with it.
* Select the events for which we want to schedule upcalls.
- * For now it's just sleep.
+ * For now it's just sleep or if thread is suspended but
+ * process wide suspending flag is not set (debugger
+ * suspends thread).
* XXXKSE eventually almost any inhibition could do.
*/
- if (TD_CAN_UNBIND(td) && (td->td_standin) && TD_ON_SLEEPQ(td)) {
+ if (TD_CAN_UNBIND(td) && (td->td_standin) &&
+ (TD_ON_SLEEPQ(td) || (TD_IS_SUSPENDED(td) &&
+ !P_SHOULDSTOP(td->td_proc)))) {
/*
* Release ownership of upcall, and schedule an upcall
* thread, this new upcall thread becomes the owner of
@@ -1134,14 +1171,14 @@ thread_user_enter(struct proc *p, struct thread *td)
KASSERT(ku->ku_owner == td, ("wrong owner"));
KASSERT(!TD_CAN_UNBIND(td), ("can unbind"));
+ if (td->td_standin == NULL)
+ thread_alloc_spare(td);
ku->ku_mflags = fuword32((void *)&ku->ku_mailbox->km_flags);
tmbx = (void *)fuword((void *)&ku->ku_mailbox->km_curthread);
if ((tmbx == NULL) || (tmbx == (void *)-1L) ||
(ku->ku_mflags & KMF_NOUPCALL)) {
td->td_mailbox = NULL;
} else {
- if (td->td_standin == NULL)
- thread_alloc_spare(td);
flags = fuword32(&tmbx->tm_flags);
/*
* On some architectures, TP register points to thread
@@ -1210,16 +1247,6 @@ thread_userret(struct thread *td, struct trapframe *frame)
td->td_pflags &= ~TDP_USTATCLOCK;
}
- /*
- * Check if we should unbind and schedule upcall
- * after returned from interrupt or etcs, this
- * is usually true when process is being debugged.
- */
- if (td->td_mailbox == NULL && ku != NULL &&
- !(td->td_pflags & TDP_UPCALLING) &&
- (kg->kg_completed || ku->ku_flags & KUF_DOUPCALL))
- thread_user_enter(p, td);
-
uts_crit = (td->td_mailbox == NULL);
/*
* Optimisation:
@@ -1257,13 +1284,8 @@ thread_userret(struct thread *td, struct trapframe *frame)
} else if (td->td_mailbox && (ku == NULL)) {
thread_export_context(td, 1);
PROC_LOCK(p);
- /*
- * There are upcall threads waiting for
- * work to do, wake one of them up.
- * XXXKSE Maybe wake all of them up.
- */
if (kg->kg_upsleeps)
- wakeup_one(&kg->kg_completed);
+ wakeup(&kg->kg_completed);
mtx_lock_spin(&sched_lock);
thread_stopped(p);
thread_exit();
@@ -1372,12 +1394,6 @@ out:
}
ku->ku_mflags = 0;
- /*
- * Clear thread mailbox first, then clear system tick count.
- * The order is important because thread_statclock() use
- * mailbox pointer to see if it is an userland thread or
- * an UTS kernel thread.
- */
td->td_mailbox = NULL;
td->td_usticks = 0;
return (error); /* go sync */
@@ -1422,6 +1438,7 @@ thread_continued(struct proc *p)
continue;
FOREACH_UPCALL_IN_GROUP(kg, ku) {
ku->ku_flags |= KUF_DOUPCALL;
+ wakeup(&kg->kg_completed);
if (TD_IS_SUSPENDED(ku->ku_owner)) {
thread_unsuspend_one(ku->ku_owner);
}
diff --git a/sys/sys/kse.h b/sys/sys/kse.h
index bd9f34b..2de3d95 100644
--- a/sys/sys/kse.h
+++ b/sys/sys/kse.h
@@ -107,10 +107,11 @@ struct kse_mailbox {
#define KSE_SWITCHIN_SETTMBX 0x01
/* Commands for kse_thr_interrupt */
-#define KSE_INTR_INTERRUPT 0x01
-#define KSE_INTR_RESTART 0x02
-#define KSE_INTR_SENDSIG 0x03
-#define KSE_INTR_SIGEXIT 0x04
+#define KSE_INTR_INTERRUPT 1
+#define KSE_INTR_RESTART 2
+#define KSE_INTR_SENDSIG 3
+#define KSE_INTR_SIGEXIT 4
+#define KSE_INTR_DBSUSPEND 5
#ifndef _KERNEL
int kse_create(struct kse_mailbox *, int);
OpenPOWER on IntegriCloud