Fix suspend and resume.
Submitted (in part) by: Kazuaki Oda <kaakun@highway.ne.jp>
This commit is contained in:
parent
452855111a
commit
40791d9d15
@ -259,8 +259,10 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
new_thread->flags = 0;
|
||||
new_thread->continuation = NULL;
|
||||
|
||||
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
|
||||
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
|
||||
new_thread->state = PS_SUSPENDED;
|
||||
new_thread->flags = THR_FLAGS_SUSPENDED;
|
||||
}
|
||||
else
|
||||
new_thread->state = PS_RUNNING;
|
||||
|
||||
|
@ -913,10 +913,6 @@ kse_sched_multi(struct kse *curkse)
|
||||
if ((curframe == NULL) && (curthread->check_pending != 0))
|
||||
signalcontext(&curthread->tmbx.tm_context, 0,
|
||||
(__sighandler_t *)thr_resume_wrapper);
|
||||
#endif
|
||||
#ifdef GS_HACK
|
||||
/* XXX - The kernel sometimes forgets to restore %gs properly. */
|
||||
_ksd_setprivate(&curkse->k_ksd);
|
||||
#endif
|
||||
/*
|
||||
* Continue the thread at its current frame:
|
||||
@ -1259,8 +1255,12 @@ kse_check_completed(struct kse *kse)
|
||||
thread,
|
||||
(thread->name == NULL) ? "none" : thread->name);
|
||||
thread->blocked = 0;
|
||||
if (thread != kse->k_curthread)
|
||||
KSE_RUNQ_INSERT_TAIL(kse, thread);
|
||||
if (thread != kse->k_curthread) {
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
else
|
||||
KSE_RUNQ_INSERT_TAIL(kse, thread);
|
||||
}
|
||||
completed = completed->tm_next;
|
||||
}
|
||||
}
|
||||
@ -1293,8 +1293,12 @@ kse_check_waitq(struct kse *kse)
|
||||
pthread->timeout = 1;
|
||||
|
||||
/* Add the thread to the priority queue: */
|
||||
THR_SET_STATE(pthread, PS_RUNNING);
|
||||
KSE_RUNQ_INSERT_TAIL(kse, pthread);
|
||||
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(pthread, PS_SUSPENDED);
|
||||
else {
|
||||
THR_SET_STATE(pthread, PS_RUNNING);
|
||||
KSE_RUNQ_INSERT_TAIL(kse, pthread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1390,7 +1394,8 @@ kse_switchout_thread(struct kse *kse, struct pthread *thread)
|
||||
break;
|
||||
|
||||
case PS_RUNNING:
|
||||
/* Nothing to do here. */
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
break;
|
||||
|
||||
case PS_COND_WAIT:
|
||||
@ -1662,16 +1667,23 @@ _thr_setrunnable(struct pthread *curthread, struct pthread *thread)
|
||||
void
|
||||
_thr_setrunnable_unlocked(struct pthread *thread)
|
||||
{
|
||||
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0)
|
||||
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0) {
|
||||
/* No silly queues for these threads. */
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
else if (thread->state != PS_RUNNING) {
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
else
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
}else if (thread->state != PS_RUNNING) {
|
||||
if ((thread->flags & THR_FLAGS_IN_WAITQ) != 0)
|
||||
KSE_WAITQ_REMOVE(thread->kse, thread);
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
if ((thread->blocked == 0) &&
|
||||
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
THR_RUNQ_INSERT_TAIL(thread);
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
else {
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
if ((thread->blocked == 0) &&
|
||||
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
THR_RUNQ_INSERT_TAIL(thread);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* XXX - Threads are not yet assigned to specific KSEs; they are
|
||||
|
@ -953,6 +953,11 @@ do { \
|
||||
((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd))
|
||||
|
||||
#define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
|
||||
|
||||
#define THR_IS_SUSPENDED(thrd) \
|
||||
(((thrd)->state == PS_SUSPENDED) || \
|
||||
(((thrd)->flags & THR_FLAGS_SUSPENDED) != 0))
|
||||
#define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0)
|
||||
|
||||
/*
|
||||
* Global variables for the pthread kernel.
|
||||
|
@ -50,19 +50,10 @@ _pthread_resume_np(pthread_t thread)
|
||||
|
||||
/* Add a reference to the thread: */
|
||||
if ((ret = _thr_ref_add(curthread, thread, /*include dead*/0)) == 0) {
|
||||
/* Is it currently suspended? */
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0) {
|
||||
/* Lock the threads scheduling queue: */
|
||||
THR_SCHED_LOCK(curthread, thread);
|
||||
|
||||
if ((curthread->state != PS_DEAD) &&
|
||||
(curthread->state != PS_DEADLOCK) &&
|
||||
((curthread->flags & THR_FLAGS_EXITING) != 0))
|
||||
resume_common(thread);
|
||||
|
||||
/* Unlock the threads scheduling queue: */
|
||||
THR_SCHED_UNLOCK(curthread, thread);
|
||||
}
|
||||
/* Lock the threads scheduling queue: */
|
||||
THR_SCHED_LOCK(curthread, thread);
|
||||
resume_common(thread);
|
||||
THR_SCHED_UNLOCK(curthread, thread);
|
||||
_thr_ref_delete(curthread, thread);
|
||||
}
|
||||
return (ret);
|
||||
@ -80,11 +71,7 @@ _pthread_resume_all_np(void)
|
||||
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock);
|
||||
|
||||
TAILQ_FOREACH(thread, &_thread_list, tle) {
|
||||
if ((thread != curthread) &&
|
||||
((thread->flags & THR_FLAGS_SUSPENDED) != 0) &&
|
||||
(thread->state != PS_DEAD) &&
|
||||
(thread->state != PS_DEADLOCK) &&
|
||||
((thread->flags & THR_FLAGS_EXITING) == 0)) {
|
||||
if (thread != curthread) {
|
||||
THR_SCHED_LOCK(curthread, thread);
|
||||
resume_common(thread);
|
||||
THR_SCHED_UNLOCK(curthread, thread);
|
||||
|
@ -316,11 +316,10 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
|
||||
}
|
||||
else if ((pthread->state == PS_DEAD) ||
|
||||
(pthread->state == PS_DEADLOCK) ||
|
||||
((pthread->flags & THR_FLAGS_EXITING) != 0))
|
||||
THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
|
||||
; /* Skip this thread. */
|
||||
else if ((handler_installed != 0) &&
|
||||
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig) &&
|
||||
((pthread->flags & THR_FLAGS_SUSPENDED) == 0)) {
|
||||
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
|
||||
if (pthread->state == PS_SIGSUSPEND) {
|
||||
if (suspended_thread == NULL)
|
||||
suspended_thread = pthread;
|
||||
@ -710,9 +709,7 @@ thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
|
||||
* will run the signal handler when it is resumed.
|
||||
*/
|
||||
pthread->active_priority |= THR_SIGNAL_PRIORITY;
|
||||
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(pthread, PS_SUSPENDED);
|
||||
else if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
THR_RUNQ_INSERT_TAIL(pthread);
|
||||
}
|
||||
}
|
||||
|
@ -97,9 +97,10 @@ suspend_common(struct pthread *thread)
|
||||
(thread->state != PS_DEADLOCK) &&
|
||||
((thread->flags & THR_FLAGS_EXITING) == 0)) {
|
||||
thread->flags |= THR_FLAGS_SUSPENDED;
|
||||
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0)
|
||||
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0) {
|
||||
THR_RUNQ_REMOVE(thread);
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
}
|
||||
#ifdef NOT_YET
|
||||
if ((thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0)
|
||||
/* ??? */
|
||||
|
@ -259,8 +259,10 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
|
||||
new_thread->flags = 0;
|
||||
new_thread->continuation = NULL;
|
||||
|
||||
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
|
||||
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
|
||||
new_thread->state = PS_SUSPENDED;
|
||||
new_thread->flags = THR_FLAGS_SUSPENDED;
|
||||
}
|
||||
else
|
||||
new_thread->state = PS_RUNNING;
|
||||
|
||||
|
@ -913,10 +913,6 @@ kse_sched_multi(struct kse *curkse)
|
||||
if ((curframe == NULL) && (curthread->check_pending != 0))
|
||||
signalcontext(&curthread->tmbx.tm_context, 0,
|
||||
(__sighandler_t *)thr_resume_wrapper);
|
||||
#endif
|
||||
#ifdef GS_HACK
|
||||
/* XXX - The kernel sometimes forgets to restore %gs properly. */
|
||||
_ksd_setprivate(&curkse->k_ksd);
|
||||
#endif
|
||||
/*
|
||||
* Continue the thread at its current frame:
|
||||
@ -1259,8 +1255,12 @@ kse_check_completed(struct kse *kse)
|
||||
thread,
|
||||
(thread->name == NULL) ? "none" : thread->name);
|
||||
thread->blocked = 0;
|
||||
if (thread != kse->k_curthread)
|
||||
KSE_RUNQ_INSERT_TAIL(kse, thread);
|
||||
if (thread != kse->k_curthread) {
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
else
|
||||
KSE_RUNQ_INSERT_TAIL(kse, thread);
|
||||
}
|
||||
completed = completed->tm_next;
|
||||
}
|
||||
}
|
||||
@ -1293,8 +1293,12 @@ kse_check_waitq(struct kse *kse)
|
||||
pthread->timeout = 1;
|
||||
|
||||
/* Add the thread to the priority queue: */
|
||||
THR_SET_STATE(pthread, PS_RUNNING);
|
||||
KSE_RUNQ_INSERT_TAIL(kse, pthread);
|
||||
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(pthread, PS_SUSPENDED);
|
||||
else {
|
||||
THR_SET_STATE(pthread, PS_RUNNING);
|
||||
KSE_RUNQ_INSERT_TAIL(kse, pthread);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1390,7 +1394,8 @@ kse_switchout_thread(struct kse *kse, struct pthread *thread)
|
||||
break;
|
||||
|
||||
case PS_RUNNING:
|
||||
/* Nothing to do here. */
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
break;
|
||||
|
||||
case PS_COND_WAIT:
|
||||
@ -1662,16 +1667,23 @@ _thr_setrunnable(struct pthread *curthread, struct pthread *thread)
|
||||
void
|
||||
_thr_setrunnable_unlocked(struct pthread *thread)
|
||||
{
|
||||
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0)
|
||||
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0) {
|
||||
/* No silly queues for these threads. */
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
else if (thread->state != PS_RUNNING) {
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
else
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
}else if (thread->state != PS_RUNNING) {
|
||||
if ((thread->flags & THR_FLAGS_IN_WAITQ) != 0)
|
||||
KSE_WAITQ_REMOVE(thread->kse, thread);
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
if ((thread->blocked == 0) &&
|
||||
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
THR_RUNQ_INSERT_TAIL(thread);
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
else {
|
||||
THR_SET_STATE(thread, PS_RUNNING);
|
||||
if ((thread->blocked == 0) &&
|
||||
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
THR_RUNQ_INSERT_TAIL(thread);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* XXX - Threads are not yet assigned to specific KSEs; they are
|
||||
|
@ -953,6 +953,11 @@ do { \
|
||||
((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd))
|
||||
|
||||
#define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
|
||||
|
||||
#define THR_IS_SUSPENDED(thrd) \
|
||||
(((thrd)->state == PS_SUSPENDED) || \
|
||||
(((thrd)->flags & THR_FLAGS_SUSPENDED) != 0))
|
||||
#define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0)
|
||||
|
||||
/*
|
||||
* Global variables for the pthread kernel.
|
||||
|
@ -50,19 +50,10 @@ _pthread_resume_np(pthread_t thread)
|
||||
|
||||
/* Add a reference to the thread: */
|
||||
if ((ret = _thr_ref_add(curthread, thread, /*include dead*/0)) == 0) {
|
||||
/* Is it currently suspended? */
|
||||
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0) {
|
||||
/* Lock the threads scheduling queue: */
|
||||
THR_SCHED_LOCK(curthread, thread);
|
||||
|
||||
if ((curthread->state != PS_DEAD) &&
|
||||
(curthread->state != PS_DEADLOCK) &&
|
||||
((curthread->flags & THR_FLAGS_EXITING) != 0))
|
||||
resume_common(thread);
|
||||
|
||||
/* Unlock the threads scheduling queue: */
|
||||
THR_SCHED_UNLOCK(curthread, thread);
|
||||
}
|
||||
/* Lock the threads scheduling queue: */
|
||||
THR_SCHED_LOCK(curthread, thread);
|
||||
resume_common(thread);
|
||||
THR_SCHED_UNLOCK(curthread, thread);
|
||||
_thr_ref_delete(curthread, thread);
|
||||
}
|
||||
return (ret);
|
||||
@ -80,11 +71,7 @@ _pthread_resume_all_np(void)
|
||||
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock);
|
||||
|
||||
TAILQ_FOREACH(thread, &_thread_list, tle) {
|
||||
if ((thread != curthread) &&
|
||||
((thread->flags & THR_FLAGS_SUSPENDED) != 0) &&
|
||||
(thread->state != PS_DEAD) &&
|
||||
(thread->state != PS_DEADLOCK) &&
|
||||
((thread->flags & THR_FLAGS_EXITING) == 0)) {
|
||||
if (thread != curthread) {
|
||||
THR_SCHED_LOCK(curthread, thread);
|
||||
resume_common(thread);
|
||||
THR_SCHED_UNLOCK(curthread, thread);
|
||||
|
@ -316,11 +316,10 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
|
||||
}
|
||||
else if ((pthread->state == PS_DEAD) ||
|
||||
(pthread->state == PS_DEADLOCK) ||
|
||||
((pthread->flags & THR_FLAGS_EXITING) != 0))
|
||||
THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
|
||||
; /* Skip this thread. */
|
||||
else if ((handler_installed != 0) &&
|
||||
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig) &&
|
||||
((pthread->flags & THR_FLAGS_SUSPENDED) == 0)) {
|
||||
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
|
||||
if (pthread->state == PS_SIGSUSPEND) {
|
||||
if (suspended_thread == NULL)
|
||||
suspended_thread = pthread;
|
||||
@ -710,9 +709,7 @@ thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
|
||||
* will run the signal handler when it is resumed.
|
||||
*/
|
||||
pthread->active_priority |= THR_SIGNAL_PRIORITY;
|
||||
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
|
||||
THR_SET_STATE(pthread, PS_SUSPENDED);
|
||||
else if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
|
||||
THR_RUNQ_INSERT_TAIL(pthread);
|
||||
}
|
||||
}
|
||||
|
@ -97,9 +97,10 @@ suspend_common(struct pthread *thread)
|
||||
(thread->state != PS_DEADLOCK) &&
|
||||
((thread->flags & THR_FLAGS_EXITING) == 0)) {
|
||||
thread->flags |= THR_FLAGS_SUSPENDED;
|
||||
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0)
|
||||
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0) {
|
||||
THR_RUNQ_REMOVE(thread);
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
THR_SET_STATE(thread, PS_SUSPENDED);
|
||||
}
|
||||
#ifdef NOT_YET
|
||||
if ((thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0)
|
||||
/* ??? */
|
||||
|
Loading…
Reference in New Issue
Block a user